AVR frequency meter – from 1Hz to 10MHz

Frequency meter with some of quite good performance, capable of measuring frequencies from 1Hz to 10MHz (9,999,999 Hz) with a resolution of 1 Hz over the entire range. Ideal for function generators or as a standalone meter. It is cheap and easy to make, with parts that can be bought anywhere, and with a small size that allow it to be mounted in the panel on any device.

Construction

The circuit consists of seven 7-segment displays, AVR ATtiny2313 uController, and a few transistors and resistors. AVR does all the work and other ICs are not needed here. Its work is simple, AVR counts pulses on the input given at the time of 1 second and displays the result. The most important thing is very accurate time base, and this is handled by 16-bit Timer1 in CTC mode. The second, 8-bit timer counter operates as Counter0 and it counts pulses given to its input, the T0 pin. Every 256 pulses it causes the interruption, where program increases the multiplier. When we receive the 1 second interrupt , the content of this multiplier is multiplied by 256 (shifted left by 8 bits). The rest of the pulses that counter got, are written down and added to the result of the multiplication. This value is then broken into single digits that can be displayed each on a single display. After that, just before leaving the 1 second interrupt, both counters are reset at the same time and the measurement starts again. AVR in his spare time is multiplexing 7 displays. More details in the source code that I put in the attachment.

Resolution vs accuracy:
f-meter-6Accuracy mainly depends on the clock source with which meter is fed. The code itself can occasionally add one pulse at very high frequencies, but it is almost negligible. Crystal, which we use, should be of good quality, and have small as possible ppm (tolerance). It is best if the frequency is divisible by 1024, for example, 16MHz or 22.1184MHz. For get the measurement up to 10MHz, use 21MHz or more crystal, for example, previously mentioned 22.1184MHz. The meter can measure the frequency up to about 47% of its own crystal, so for 20MHz we get a bit below 10MHz, for 16MHz we get a bit below 8MHz measurment – so 22.1184MHz crystal will be perfect for this and its worth to buy. Unfortunately, it is not very popular, and if you find it, it will have a tolerance of 10 to 100 ppm which is not suitable for any accurate measurements. If we have another device to measure the exact frequency (eg oscilloscope with hardware measurement), we can calibrate our circuit by adding a little trimming – (cap pot) (about 1p-10p) to one of the legs of crystal and to ground, and tune the frequency of the oscillation in such a way to get same measurement as on the oscilloscope. If you can not do that, you should to get a small as possible ppm crystal, crystal generator, or simply assume that crystal will work exactly at frequency that is given by the manufacturer.

Attachment provides a few compiled codes for few different crystals, but you can compile it for your own. In Crystal type in the crystal frequency, in Compare type in the result of dividing this frequency by 1024, (do not type the rest after the comma, if crystal is not divisible by 1024).

Wave:
Basically, you can put anything from 0-5V into the input, not just a rectangle. Circuit counts sine or triangle as well, counting is done during the falling edge at the 0.8V. Please note that the input is not protected in any way from higher voltages. Input is not pulled up to VCC, it is a high impedance input so it will not load the measured circuit – you should be even able to measure the mains frequency by touching the input pin with your finger :) Meter measurement can be extended up to 100MHz with 10Hz step, by adding appropriate high-speed frequency divider to input.


Display:
Seven 7-segment multiplexed displays with common anode (common plus). If the brightness is too low, you can change the current limiting resistors of the segments to the stronger ones, but remember to not exceed 40mA impulse current for each pin of the microcontroller. Displays have also their current limit, so you should check it. By default, these resistors are 100ohm. Unneeded displays, f.e. those displaying zero’s, are blanked out in order to make reading more comfortable. For example, the value of “0.000.980” will result with “980” – dot points are also blanked out. Measurement is refreshed every each second, because the time base is 1 second.

PCB:
f-meter-2Double-sided PCB with dimensions of 109mm x 23mm – unfortunately the seventh display does not fit in the free version of Eagle so its drawn from the hand. Three wire connections should be made on the PCB, the first one on the top side of the board, connect power to the VCC pin of the processor – this connection is shown on the silkscreen layer. Two more connections are the displays dots points that should be connected to 330ohm resistor located on the bottom side of the board. At the top of the PCB, Atmel ISP-6 edge connector pads are placed, looking from the top, pin no.1 is the first one from crystal side. No need to solder the connector permanently, or even do not solder it at all, you can program the chip in your own way. Displays must be mounted at some distance from the PCB, so you be able to hand solder the top surface pads (4 pads for each display). The project itself does not provide mounting pads for mentioned before cap trimmer, if needed, solder it on your own, for example see the pictures. PCB on the pictures is different from the one from the attachment, this is the first version 1.0 which was assumed to make only 1MHz measurement.

Gallery:

Files:
DOWNLOAD – .BAS source file and compiled code version 1.1; Eagle 6.4.0 project files and PDF’s version 1.1


F_meter_7_1 18.10.2013 – version working with the LCD HD44780 display, thanks to Waldek, who also made a LED version. There’s no PCB project at the moment, everything is made on the protoboard. Display handling is done in the “1s” interrupt, main loop is empty. Format and content of the LCD text can be modified in the source code. Because of lack of a tunable frequency generator with f above 500kHz, higher frequencies was only spot tested (1, 3, 6, 8MHz) – code should display the same measurement as the LED version.

DOWNLOAD – .BAS source file and compiled code version 1.1 for LCD; schematic version 1.1 for LCD



AVR frequency meter – from 1Hz to 10MHz
0 votes, 0.00 avg. rating (0% score)

79 Comments

  1. Jak miernik radzi sobie z przebiegami prostokątnymi o różnym od 50% wypełnieniu? Widzę, że zaczyna Pan korzystać z języka maszynowego.
    Z Poważaniem,
    Luigi

    • Testowałem do 400kHz, od 10 do 90% – żadnego problemu. Myślę że i wyżej nie będzie problemu, aby przebieg miał cokolwiek co przypomina zbocza :)

      Assemblerem zaraził mnie znajomy, i bardzo dobrze, będę mógł w nim skrobać krytyczne elementy programu, takie jak właśnie obsługa przerwania (do której Bascom bezmyślnie dokłada 100 cykli procesora gratis).

      Pozdrawiam

  2. Tu jeszcze nie ma takiej zabawy z assemblerem, tu wystarczyłoby zrobić obsługę wyświetlacza a linii kodu przybędzie kilkukrotnie. Polecam napisanie tego w czystym assemblerze a z pewnością zmieni się spojrzenie na wiele aspektów programowania mikro kontrolera. Mnie się zmieniło.

  3. Nie o sarkazm mi chodziło. Chodziło tylko o to, że języki “niskiego poziomu” jak C czy ten dziwny Basic, w przypadku kontrolerów są j. “wysokiego poziomu”. Można szybko wyprodukować kod, ale nie zawsze ma się taką kontrolę nad zegarem i przerwaniami jak w Asm. Z czego wniosek, że nie do wszystkiego trzeba Asm. Swoją drogą, nim więcej poznaję Bascom tym bardziej przekonuje się, że nic nie wnosi, nic nie ułatwia, jest nieczytelny i jest jedynie ze względów komercyjnych czy czegoś takiego. Chyba nie ja pierwszy to zauważyłem, że C jest piękny w swej prostocie.
    Mocim Panie.

    • I ja, czym więcej ASM poznaję, tym bardziej Bascom jest dla mnie niezrozumiały i dziwny. Przykładowo, jeśli już jesteśmy przy przerwaniach, bascom nie wiedzieć czemu odkłada na stos wszystkie dostępne rejestry, pomimo tego że kompilator doskonale wie jakich faktycznie użyje. Jedno słowo ciśnie się na usta :)

      A poprzedniego komentarza wcale nie odebrałem negatywnie :)

  4. Skoro już tak sobie rozmawiamy to podzielę się swoimi spostrzeżeniami, może komuś się przydadzą. Może nie dotyczy tego projektu. Wyświetlanie obsługuje też jakieś przerwanie, które? Nie mówię o zmianie cyfr na wyświetlaczu, to jest co 1s. Jeśli przerwanie Counter wypada w czasie przerwania timera wyświetlacza, musi czekać na stosie. Dochodzi kilka, kilkanaście, kilkaset, cykli zegara. Priorytety przerwań nie mają nic do tego, można zagnieżdżać przerwania i liczyć na palcach ile cykli ewentualnie dodać. Jest jeszcze jedno przerwanie – Watchdog. Jeśli nie ma trybu uśpienia to, watchdog tylko przeszkadza. To są tylko spostrzeżenia amatora. Ktoś kto zajmuje się tym dłużej i na poważnie na pewno zdaje sobie z tego sprawę. A ktoś kto właśnie zachodzi w głowę czemu coś nie jest tak w jego prog może mu coś zaświta.
    Pozdrawiam.

    • Nie, wyświetlanie nie jest na przerwaniu, to procesor robi w wolnej chwili. Licznik impulsów to Counter0, podstawa czasu to Timer1 – i to koniec – attiny2313 ma dwa liczniki. Multpileksowanie wyświetlaczy jest w pętli głównej oparte na zwykłym “waitms 1″. Gdyby się uprzeć robić je w przerwaniu, gdzie z resztą początkowo się znajdowało, to bardziej by to przeszkadzało jak pomagało – właśnie z powodu tego że przerwanie counter0 jest wywoływane co 256 impulsów, a jeśli mierzymy 10MHz no to wiadomo.

      Ale to nie problem, aby obsłużyć jedno przerwanie w drugim, jeśli jest taka potrzeba to ok, jeśli nie to po co dodatkowo mieszać :)

      Jak pewnie zauważyłeś przy wychodzeniu z przerwania podstawy czasu, kasuję flagę czekającego już w kolejce przerwania timer0, w rejestrze TIFR – przy częstotliwościach mierzonych powyżej 800KHz przerwanie timer0 już nachodziło na to drugie i było powodem zawyżania wyniku o 256 (zwiększanie mnożnika w przerwaniu). Program nie jest jeszcze doskonały pod tym względem – niestety pewne rzeczy chciało by się zrobić sprzętowo, a tak czekając na coś nawet te 4 cykle, w tym czasie może akurat przypaść inne przerwanie i namieszać.

      Watchdoga nie używam, nie widzę tutaj potrzeby. Inne przerwania oprócz tych dwóch nie występują.

  5. Czyżby szykował się fajny generator z wykorzystaniem tego miernika? http://mdiy.pl/tworzenie-prostego-front-panelu-do-obudowy/
    :)

  6. czy pin resetu nie powinien być podciągnięty do plus przez 10K ?

  7. Uruchomiłem w/w miernik z pewnymi zmianami , dodałem kondensatory na zasilaniu i rezystor (10K) podciągający RESET do plusa,
    I dziwnie się zachowuje miernik f , tzn pokazuje 50Hz – nawet w pewnym momencie zasiliłem z baterii 4,5V i to samo , potem dałem przewód ekranowany na wejście pomiarowe na chwilę pomogło wróciłem do zasilania ze stabilizatora 7805 – fajnie działa ale dolutowałem na przewodzie pomiarowym krokodylki i znów pokazuje 50 .

    2) miałem miernik z generatorem 48Hz 3Vpp i prawidłowo pokazuje – ale bez pomiaru wraca 50
    3) jak zewrę na przewodzie GND i (TO)/PD4/pin8 to pokazuje zero
    4) mam jakiś generator samoróbkę 5Vpp-okoł (prostokąt) to zauważyłem dziwne zachowanie na dzielniku rezystorów jak jest większe napięcie na rezystorze to jest większa częstotliwość ?

    • Miernik działa dobrze, zgodnie z opisem. Te 50Hz wyłapuje z otoczenia, to są 50Hz z sieci :) Wejściem jest goły pin mikrokontrolera ustawiony w tryb wysokiej impedancji. Można ściągnąć wejście jakimś rezystorem – rzędu 1Mohm i powinno pomóc. A tak w ogóle to dobrze będzie dodać jakiś układ wejściowy żeby nie uszkodzić pinu przy próbkowaniu różnych sygnałów spoza zakresu 0-5V.

      Co do czwartego pytania, czy ten generator nie ma przypadkiem na wyjściu +-2,5V? Jeśli tak to wiadomo, napięcie jest poza zakresem pinu wejściowego.

    • 3) jak zewrę na przewodzie GND i (TO)/PD4 to pokazuje zero -można tak robić ?

  8. Dzięki za wszystkie odpowiedzi , trochę zaśmiecam ci bloga .

    „Te 50 wyłapuje z otoczenia” tak myślałem nawet wszystkie świetlówki pogasiłem na warsztacie :-) , ależ pracuje w nie przyjaznym środowisku :-) może nie będę miał pasożytów :-).

    „A tak w ogóle to dobrze będzie dodać jakiś układ wejściowy żeby nie uszkodzić pinu przy próbkowaniu różnych sygnałów spoza zakresu 0-5V. „
    – mógłbyś coś pokazać bliżej jakiś odnośnik – bo ja na razie raczkuję w tym temacie

    4) nie jest GND do prawie 5V na 555 ale niestabilizowane z otwartym kolektorem – a jak wiesz pomiar szczytu takiego czegoś to nie jest łatwa sprawa – przynajmniej dla mnie

  9. Czy 09/04/2013 o 13:22 miałeś na myśli generator 400 Mhz, który pojawił się kilka dni później, czy moźe planujesz też projekt generatora do 1-10 Mhz ?
    Przydałby mi się :)

  10. Czy któryś z kolegów próbował skompilować program w Bascomie z załączonego pliku? Ja nie mogę go skompilować wyrzuca mi błąd na linii programu: Str2digits Freq_str , Freq_num(1). Posiadam bascom AVR 1.11.9.5

    • Program był kompilowany pod wersją 2.0.7.6 czyli chyba najnowszą na tamtą chwilę. Ta instrukcja jest dosyć nowa, na pewno nie ma jej w tak starej wersji.

  11. To nie jest przyczyna wersji bascoma tylko błędów w programie gdyż zainstalowałem wersję bascoma 2.0.7.6 i jest to samo. Bascom wyżuca błąd nieznanej instrukcji również w linii programu: “Dim Frequency As Dword” powinno być As Word. Inst
    rukcja Dword nie występuje w żadnej wersji bascom. również linia programu “Str2digits Freq_str , Freq_num(1)” nieznaną instrukcję. Mam prośbę da Pana manekinen. Pisze Pan że testował już ten miernik na różnych częstotliwościach i było wszystko ok. Ja go zmontowałem na kwarcu 16Mhz, załadowałem wsad do procka z powyższego pliku 16MHz.hex i na wyświetlaczu pokazują się jakieś przypadkowe znaki zamiast cyfer. Dlatego chciałem skompilować wsad pod rezonator 12MHz i się go nie da skompilować ze względu na błędy w programie. Proszę mi powiedzieć z jakiego wsadu Pan skożystał jeśli Pański miernik działa prawidłowo i jakie fusebity Pan wgrywał do procka. Gdyż ja próbowałem z innymi kwarcami i fusebitami i miernik zachowuje się tak samo. Mój email:

    email wymoderowałem, nie ma potrzeby podawania takich danych publicznie, email jest dla mnie widoczny jeśli zostanie podany w polu “email” podczas wysyłania komentarza :)

    • A ja polecam jednak prawidłowo wykonać aktualizację Bascoma, bo nawet definicja Dword została wprowadzona już dawno temu, już w tamtym roku z powodzeniem z niej korzystałem. Dword to Double Word czyli w tym przypadku zmienna 32-bitowa.

      Wersja 2.0.7.6 poprawnie kompiluje kod, proszę nie zarzucać że w programie są błędy uniemożliwiające kompilację. Chyba że wersja darmowa ma kłopoty, to nie wiem, ja korzystam z pełnej.

      Układ został wykonany przez kilka osób i wyświetlacz pracował poprawnie. Prędkość rezonatora nie ma na to nawet najmniejszego wpływu. Proszę się upewnić że zostały użyte prawidłowe tranzystory (być może odwracają fazę), oraz wyświetlacze zgodne pinowo (segmenty pod właściwymi pinami). Fusebity oczywiście adekwatne do zamontowanego zewnętrznego rezonatora, czyli external crystal 8-20MHz. Dla attiny2313 będzie to L:FF H:DF E:FF (na szybko sprawdzane).

      Jeśli kodu nie uda się skompilować to spróbuję podesłać ustawiony na 12MHz ale dopiero w niedzielę.

  12. Używam wersji Bascom 2.0.7.5, kompilowałem program dla rezonatorów 16MHz i 22.1184MHz bez żadnych komunikatów o błędach. Wykonany przeze mnie miernik działa bez zarzutu.
    Koledze manekinen gratuluję kolejnego udanego projektu!
    http://obrazki.elektroda.pl/7244456500_1375472103.jpg

    • Wyszło ładnie i zgrabnie, Kolego czy kalibrowałeś w jakiś sposób ten miernik? Bo rozumiem że na zdjęciu jest testwany kwarc 8MHz – ja uzyskiwałem podobne rezultaty, t.j. około 100-200Hz odchyłki przy tych najtańszych kwarcach, przy czym ja swój miernik kalibrowałem.

      I dzięki za dobre słowa :)

  13. Bardzo bym prosił kolegę manekinen o podesłanie pliku na kwarc 12MHz za co bym był bardzo wdzięczny. Mam wersję demo Bascom 2.0.7.5 być może dla tego nie da się skompilować pliku.

    • Ja kompilowałem na wrsji demo i poszło ,
      Ale może źle przeliczyłeś
      ja mam na 20MHz
      [code]’Crystal, put here your crystal frequency
      $crystal = 20000000

      ‘Divide your crystal frequency by 1024 and put below
      ‘F.e. 16000000/1024=15625; 20000000/1024=19531,25 (use 19531); 25000000/1024=24414,0625 (use 24414)
      Const Compare = 19531
      [/code]

  14. Miernika nie kalibrowałem – nie dobierałem rezonatora kwarcowego, zastosowałem kondensatory 22pF (C2 i C3) dla obu testowanych rezonatorów (16MHz i 22.1184MHz). Nie mam dostępu do generatora sygnału wzorcowego (lub innego, legalizowanego częstościomierza). Dla moich potrzeb (identyfikacja nieoznaczonych rezonatorów, porównanie częstotliwości kilku “kwarców”, itp.) istotna jest stabilność i powtarzalność pomiarów (odczytów), a te zalety posiada prezentowany miernik. Wynika to – moim skromnym zdaniem – z zastosowania w programie wstawek asemblerowych, program napisany w “czystym” Bascomie nie zapewnia (o ile pamiętam swoje eksperymenty) tak dobrych rezultatów.
    Pozdrawiam.

    • Program początkowo był bez żadnych wstawek, czysty bascom osiągał coś około 600-800kHz przy taktowaniu 16MHz :) Po prostu przerwania wykonywały się koszmarnie długo i po przekroczeniu tej ilości impulsów podanych na wejście wskazania były zawyżane.

      Podoba mi się ten mini generatorek do testowania kwarców (ze zdjęcia) – można prosić o namiary na jakiś schemat?

    • Wysłałem wiadomość ok. 2godz. temu – nie wiem, dlaczego “nie doszła”.
      Mój “tester kwarców” pracuje w układzie generatora Colpittsa-Pierce’a. Wzbudza się w zakresie 4MHz-10MHz (tyle sprawdzałem). Wartości R1 i C1 mogą być dobierane w zależności od typu (egzemplarza) tranzystora oraz częstotliwości rezonatora kwarcowego.
      http://obrazki.elektroda.pl/5752394100_1375544183.jpg

    • Poprawiam: zamiast C1 ma być C2.
      A na razie nie widzę linka do obrazka ze schematem, może jednak pokaże się z opóźnieniem?

    • Ok dzięki, będę musiał potestować :)

      Niestety mam problem z linkami wklejanymi przez komentujących. Muszę je ręcznie poprawiać aby się wyświetlały. Już jest ok.

  15. hi…my frequency counter cannot run well,seven segment sowing 8.8.8.8.8.8.8 with no number can read…trying to setting fuse bit not help…nothing wrong in circuit , use pnp bc548 as driver , and attiny in dip socket. anyone can help me please…

  16. Gocha…!! thanks manekinen , this is embarrasing me..:-) yeah its NPN, when i replace with PNP problem solved …!! one more question why the dot point alway on ..?? is it normal..??

    • Dots are enabled because transistors are open all the time. Only two dots should be enabled (wired).

      Do you made a troughhole version of this meter?

    • no, i didnt build in pcb, just trying on breadboard , on you circuit the dot point connect to ground via R330 ..?? my seven segment led display all dot point was connected. so all desimal point always on when the next digit on.

  17. ups … the result of counter always 3 times from the source signal…why..??

    • And whats the source signal? Its square TTL or something else? Did you use proper code for your crystal?

      And for the dots, connect only those dots you need (1st and 4th)

  18. yups the source signal is from Kenwood Function generator. I use 20Mhz crystal on Attiny and burn into the chip your hex file for 20Mhz too .

  19. yups fuse are on correct setting for ext 8-20 Mhz its L:FF H:DF E:FF

    • Well, maybe your crystal is oscilating at 1/3 of its frequency? Try a different one. You can enable the CKOUT fuse to get operating frequency on the PD2 and check it with other frequency meter / oscilloscope. Or your input signal is distorted (check with oscilloscope). I dont have more ideas why this is happening.

  20. czy da rade przerobić kod na lcd 2×16

  21. projekt super ale mam prośbę czy autor udostępni kod pod
    lcd 2×16 bo z ledami u mnie problem brak zasobów

    • Kolego, kod bez problemu da się zmodyfikować tak aby współpracował z takim wyświetlaczem, ale z racji braku wolnego czasu nie mogę się tym zająć (budowa układu, pisanie kodu, testowanie, poprawki etc, to z pół dnia pracy). Być może ktoś na forum elektrody mógłby w tym pomóc.

  22. odp WALDEK
    ja robiłem na FET i się poddałem – aż jutro spróbuję twoje rozwiązanie
    http://www.fotosik.pl/pokaz_obrazek/b28c286db3cd9fd1.html

  23. Mam pytania co do w/w projektu miernika częstotliwości. Konkretnie to czy można go jakoś zmodyfikować by pracowal z preskalerem przez 256 i nierozumię jak jest realizowane przeliczanie kwarcu by timer odliczał podstawe czasu. Podałeś wzór, że nalezy częstotliwość użytego kwarcu podzielić przez 1024,czyli preskaler timera, a co z ilością impulsów timera 256. No i ostatnie pytanie, jak narazie, czy przy pomierze do 1,3 GHz kropki na wyswietlaczach będą się przesuwać, czy automatycznie dobiera on zakres pomiarowy?
    A tak wogule to z ASM to kompletnie nic nieznam, no bardziej BASCOM AVR, ale tez nie idealnie.

    • Jak jest uzyskiwany czas 1s? Przyjmując kwarc 16MHz (czyli 16 milionów impulsów na sekundę), dwubajtowy licznik T1 nie będzie w stanie pomieścić tych 16 milionów ponieważ jego zakres to 65536. Ale jeśli do licznika wpadnie jeden impuls na każde 1024 taktów z kwarcu, to zliczenie sekundy zajmie mu dokładnie 15625 impulsów (16,000,000 / 1024) co już będzie w stanie pomieścić – stąd to dzielenie przez 1024. Dla tego wartość Compare (porównująca) to wynik dzielenia kwarcu przez 1024, i gdy licznik zliczy te 15625 impulsów to wywoła przerwanie dokładnie po 1 sekundzie.

      Drugi timer liczący impulsy z wejścia (chyba o ten pytasz pisząc timer 256) nie jest sprzężony z tym pierwszym i pracuje niezależnie, kwarc nie ma na niego żadnego wpływu.

      Jeśli chcesz zastosować preskaler 256, to znaczy że każdy impuls na wejściu będzie oznaczał zwiększanie wyniku nie o 1 a o 256. Więc przed wyświetleniem wyniku należy go pomnożyć przez 256 (przesunąć w lewo o 8 bitów). Wtedy teoretycznie uzyskamy zakres do 2,560GHz z rozdzielczością 256Hz – teoretycznie, bo zastosowany preskaler też ma swoje ograniczenia. Wtedy kropki pozostawiamy bez zmian, a cały wynik będzie przesunięty o 3 zera – ostatnia cyfra będzie oznaczać 1kHz a nie 1Hz.

      Być może coś pokręciłem ale z grubsza tak to właśnie wygląda.

  24. Witam,

    mnie interesuje taka rzecz, czy jeśli przestawię procek na zewnętrzny kwarc 22.1184, to czy potem programator USBasp mi do wykryje na takiej częstotliwości?

    • Bez problemu. Pamiętaj jednak że to wartość po za specyfikacją mikrokontrolera. Attiny2313 pracujący do 20MHz sobie z tym poradzi, ale dla innego układu np Atmega8 pracującego do 16MHz takie przetaktowanie może być za duże i mogą pojawić się np błędy w zapisie do pamięci podczas programowania – stąd już niedaleka droga do ubicia układu.

  25. Dziekuję za wyjaśnienie zagadnienia. W związku z kompletną nieznajomością Asm i pobieżną znajomością Bascoma czy mogłbyś zrobić dla mnie poprawki swojego programu właśnie do współpracy z preskalerem 256?

    • Spróbuję w weekend znaleźć czas żeby pogrzebać, bo po za przemnożeniem wyniku przez 256 trzeba też prawidłowo go wyświetlić (uciąć i przesunąć o 3 miejsca). Odezwę się na email.

  26. Ok. Dzięki wiëc czekam na maila od Ciebie.

  27. To skoro wiąże się to z większymi poprawkami możliwe jest to by wartos w GHz byla prezentowana na 8 wyświetlaczach LED. Chodzi o to by ostatnią cyfrą byla 100 kHz. A także by wartości częstotliwości do 30MHz byla wyświetlana jak najdokładniej można. Chodzi też o to by np. częstotliwości pasma KF 2m czy 70 cm byla jak najdokladniej wskazywana.

  28. Chodziło mi o 100Hz.

  29. Witam !
    Mam problem z miernikiem na Lcd. Wykonałem zgodnie z opisem i niestety nie działa. Fuse bity ustawione prawidłowo pod kwarc 16 MHz. Const Compare = 15625. Działanie microkontrolera prawidłowe. Na TRX VX7-R “słyszę” działanie kwarcu na częstotliwości 16 MHz z elementami działania bramkowania co 1 sekundę. Mimo dotykania nóżki numer osiem nie pokazuje 50 Hz.
    Podłączony do generatora 1 KHz Vpp 3V z oscyloskopu Sigelent nadal nic nie pokazuje.
    Czasami pokazuje jakieś częstotliwości rodem z piekła
    Czy robię coś źle ? Gdzie szukać problemu ?
    Kompilacja programu w Bascom 2.0.6.2
    Pozdrawiam!
    P.s.
    Bardzo fajna konstrukcja. Jak kupię Wyświetlacze LED to zrobię to na wyświetlaczach. Gratuluję ! i oby więcej takich konstrukcji.

    • Cześć, nie powielałem wersji LCD więc nie mam jak się odnieść do tego problemu, ale dam znać dla autora bo z tego co widzę to nie zostawił w plikach kontaktu do siebie.

    • Witam,
      problemy mogą wynikać z parametrów sygnału wejściowego o ile, oczywiście, nie ma pomyłek montażowych, układ jest prawidłowo zasilany (stabilność napięcia, kondensatory blokujące), itp.

      “Mimo dotykania nóżki numer osiem nie pokazuje 50 Hz.
      Podłączony do generatora 1 KHz Vpp 3V z oscyloskopu”.

      Dotykanie nóżki nie może być traktowane jako poprawne sterowanie wejścia miernika.
      Również opis sygnału z oscyloskopu jest nieprecyzyjny: czy 3Vpp oznacza poziomy od 0V do 3V, czy też od -1.5V do +1.5V, jaki jest kształt i wypełnienie tego sygnału?
      Radziłbym zbudowanie prostego multiwibratora astabilnego, np. na bramkach TTL lub CMOS albo użycie źródła sygnału o poziomach TTL.
      Prawidłowa praca układu (działanie programu)jest oczywiście sygnalizowana miganiem (co 1s) diody LED.

    • A ja dodam jeszcze że 3V jako stan wysoki dla wejścia może być za małą wartością. Minimum rozpoznawane jako stan wysoki jakie gwarantuje producent to 0.6 * VCC (patrz nota, dc characteristics) czyli przy zasilaniu układu AVR napięciem 5V, minimum rozpoznawane jako stan wysoki to właśnie 3V. Wystarczy że napięcie zasilania będzie wynosiło nieco powyżej 5V a amplituda sygnału nieco poniżej 3V i będzie duże prawdopodobieństwo że układ nie zobaczy stanu wysokiego – tym bardziej przy takich częstotliwościach.

  30. Witam!
    Już wszystko działa dobrze.Problemem były ze stany na wejściu mikrokontrolera. Po podłączeniu zewnętrznego generatora (z płyty starego komputera wyciągnięty ) do wejścia wszystko się ładnie wyświetliło.
    Dzięki za naprowadzenie na trop i za pomoc!
    Pozdrawiam serdecznie!

    Jak się nauczę wklejać zdjęcia (nie wiem jaka rozdzielczość zdjęcia )to wyślę.

  31. Повторил ваш мерник. :)
    Добавил входной усилитель на транзиторе и индикаторы заменил на BA56+CA56.
    Огромное спасибо за разработку, просто и удобно.

  32. Hi! Can you make the code for 24 MHz and 32 MHz crystals?

    • Sorry i missed your question… from march :( You can compile it yourself for 24MHz crystal with free version of bascom avr. 32MHz is way too much for attiny2313 and it won’t run for sure. 24MHz is also too much, but with a tiny bit of luck it will work :)

  33. Witam serdecznie…

    Mam pytanie odnośnie wstawek assemblerowych.
    Dlaczego w obsłudze przerwania 1s kładziesz na stos taką duża ilość rejestrów? Czy wszystkie one są używane w tym przerwaniu ?

    Pozdrawiam.

  34. Ok to może będziesz w stanie poradzić coś z moim kodem.
    Oto mój schemat:

    http://postimg.org/image/hepzm9n5v

    Oraz kod:
    #include “global.h”
    #include //delay
    #include
    #include
    #include “uart.h”
    #include

    #define LED D,7
    #define INPUT_PIN D,4 //input for counts.
    #define CLR D,3 // Reset of 74HCT393E

    volatile uint32_t m = 0;

    ISR (TIMER0_OVF_vect,ISR_NAKED){
    asm(
    “push r0″ “\n”
    “in r0, __SREG__” “\n\t”
    “push r24″ “\n\t”
    “push r25″ “\n\t”
    );
    m++;
    asm(
    “pop r25″ “\n\t”
    “pop r24″ “\n\t”
    “out __SREG__, r0″ “\n\t”
    “pop r0″ “\n\t”
    “reti” “\n\t”
    );

    // m++;
    // uprint(“TIMER0_OVF_vect called\n”);
    }

    ISR(TIMER1_COMPA_vect){
    //TCCR0B |= (0 << CS02) | (0 << CS01) | (0 << CS00);
    m = (m << 8) + TCNT0;
    SET(CLR); //This will hold down 74HCT393 so TIMER0_OVF_vect should not be trigered.
    TCNT0 = 0;
    /*62406~62407
    snprintf(buf, sizeof(buf), "%lu", m);
    uprint(buf);
    */

    // 62410~62411
    USART_send(m/10000+0x30);
    USART_send((m%10000)/1000+0x30);
    USART_send((m%1000)/100+0x30);
    USART_send((m%100)/10+0x30);
    USART_send((m%10)+0x30);

    /* 62410~62411 reversed…
    USART_send(m%10+0x30);
    for(;(m/=10);){
    USART_send(m%10+0x30);
    }
    */

    m = 0;
    USART_send('\n');
    RESET(CLR);
    //TCCR0B |= (1 << CS02) | (1 << CS01) | (0 << CS00);
    }

    int main(void){
    SET_OUTPUT(LED);
    SET_OUTPUT(CLR);
    SET(CLR);
    USART_init();
    uint8_t i = 0;

    for (i=0;i<=10;++i){
    TOGGLE(LED);
    _delay_ms(50);
    }

    OCR1A = 0x3D08; // 16000000 ÷ 1024 – 1 = 15624
    // Set interrupt on compare match.
    TIMSK1 |= (1 << OCIE1A);
    // Mode 4, CTC on OCR1A, set prescaler to 1024 and start the timer.
    TCCR1B |= (1 << WGM12) | (1 << CS12) | (1 << CS10);
    // Ok, time to configure second timer for input.

    // PD4 is now an input with pull-up enabled.
    SET_INPUT(INPUT_PIN);
    //SET(INPUT_PIN);

    // Enable timer0 interrupt.
    TIMSK0 |= (1 << TOIE0);
    // External Clock Source on T0 pin, Clock on Rising Edge.
    // TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);
    // External Clock Source on T0 pin, Clock on Falling Edge.
    TCCR0B |= (1 << CS02) | (1 << CS01) | (0 << CS00);

    sei();
    while (1){}
    return 0;
    }

    Teoretycznie w terminalu powinienem dostać przy częstotliwości 16Mhz/256 wartość 62500 a dostaje pływające 62410.

    Jakiś pomysł na udoskonalenie kodu ?

    • Wyrzuć zawartość przerwania TIMER1_COMPA poza funkcję obsługi tego przerwania. Dodatkowo, też można w tej funkcji dodać atrybut naked i w tej funkcji inkrementować wybrana zmienną. Dopiero w funkcji main zrealizuj wysyłanie danych przez interfejs szeregowy do komputera (po określonym czasie).

    • Widzę że zrezygnowałeś z kasowania flagi oczekującego przerwania licznika impulsów w rejestrze TIFR, zamiast tego sprzętowo blokujesz nadchodzące impulsy na wejście. Są odblokowywane pod sam koniec przerwania, więc niby ok. Ale gdzie następuje reset licznika podstawy czasu? Czy to jest to “m = 0;”? Nie jestem biegły w tym języku. Potem następuje dłuuuugie i różne w czasie wysyłanie po uart, i na końcu odblokowanie impulsów. Obydwa te liczniki powinny być wyzerowane w możliwie tym samym momencie, najlepiej na samym końcu przerwania podstawy czasu. Gdybyś miał problem z wynikiem skaczącym po 256Hz to powodem byłby brak wyzerowania flagi w TIFR, ale skoro wynik pływa, to całkiem możliwe że to przez różne czasy obsługi uartu – wywal go stamtąd lub po wysłaniu danych kasuj obydwa liczniki “na raz”.

      Pozdrawiam

  35. Układ pracuje na MCU atmega328p, jest tam rejestr tifr1 ale jego resetowanie raczej nic tutaj nie wnosi, tym bardziej że impulsy są blokowane przez 74hct393.

    Z racji iż licznik podstawy czasu pracuje w trybie CTC to jego rejestr jest sam kasowany z wystąpieniem każdego przerwania 1s.

    “m = 0″, jest resetowaniem mnożnika po wysłaniu danych przez uart.
    Generalnie obsługę uarta dałem tam tylko tymczasowo do testów. Faktycznie w nie najlepszym miejscu, z racji iż chcemy aby obsługa przerwania trwała jak najkrócej.

    Obecnie nieco poprawiony kod znajduje się tutaj:
    https://bitbucket.org/hetii/freq/src/4bdfa054c9e4ce64758edc41214e741798e1b2b7/main.c?at=master

    Wyniki:
    Kwarc 4Mhz/256 = 15625 -> 15616
    Kwarc 16 Mhz/256 = 62500 -> 62470

    Niestety nie mam jak innego skalibrowanego przyrządu aby sprawdzić faktyczne częstotliwości generatorów.

    Obecnie kod assembler-a dla przerwań wygląda następująco:

    00000522 : //counter:
    522: 0f 92 push r0
    524: 0f b6 in r0, 0x3f ; 63
    526: 8f 93 push r24
    528: 9f 93 push r25
    52a: 80 91 11 01 lds r24, 0x0111
    52e: 90 91 12 01 lds r25, 0x0112
    532: 01 96 adiw r24, 0x01 ; 1
    534: 90 93 12 01 sts 0x0112, r25
    538: 80 93 11 01 sts 0x0111, r24
    53c: 9f 91 pop r25
    53e: 8f 91 pop r24
    540: 0f be out 0x3f, r0 ; 63
    542: 0f 90 pop r0
    544: 18 95 reti

    00000546 : //1s
    546: 0f 92 push r0
    548: 0f b6 in r0, 0x3f ; 63
    54a: 1f 92 push r1
    54c: 2f 93 push r18
    54e: 8f 93 push r24
    550: 9f 93 push r25
    552: 5b 9a sbi 0x0b, 3 ; 11
    554: 80 91 11 01 lds r24, 0x0111
    558: 90 91 12 01 lds r25, 0x0112
    55c: 26 b5 in r18, 0x26 ; 38
    55e: 98 2f mov r25, r24
    560: 88 27 eor r24, r24
    562: 82 0f add r24, r18
    564: 91 1d adc r25, r1
    566: 90 93 10 01 sts 0x0110, r25
    56a: 80 93 0f 01 sts 0x010F, r24
    56e: 10 92 12 01 sts 0x0112, r1
    572: 10 92 11 01 sts 0x0111, r1
    576: 16 bc out 0x26, r1 ; 38
    578: 5b 98 cbi 0x0b, 3 ; 11
    57a: 81 e2 ldi r24, 0x21 ; 33
    57c: 86 bb out 0x16, r24 ; 22
    57e: 9f 91 pop r25
    580: 8f 91 pop r24
    582: 2f 91 pop r18
    584: 1f 90 pop r1
    586: 0f be out 0x3f, r0 ; 63
    588: 0f 90 pop r0
    58a: 18 95 reti

    P.S. Poprawki mile widziane :)

    • Z racji iż licznik podstawy czasu pracuje w trybie CTC to jego rejestr jest sam kasowany z wystąpieniem każdego przerwania 1s.

      Czyli podczas wejścia do przerwania, a nie z jego wyjścia. Chyba że się mylę to mnie popraw, nie pamiętam już. Obydwa liczniki MUSZĄ być zerowane w TYM SAMYM CZASIE. Jest to bardzo ważne, dla tego zerowanie zrobiłem w ASM, są tam zaledwie 1 czy 2 cykle poślizgu.

      Jeśli jesteś pewien swojego rozwiązania w oparciu o blokowanie impulsów, to rejestr TIFR nie jest potrzebny, choć jego wyzerowanie na pewno nie zaszkodzi.

      Jeśli wyniki są stabilne, zmieniają się płynnie podczas zmiany częstotliwości (nie skokowo), to kod powinien być ok. Reszta zależy od dokładności zegara którym jest taktowany cały układ.

  36. Hmm z tego co widze to kompilator
    instrukcje:

    m = 0;
    TCNT0 = 0;

    Sprowadza do:
    sts 0x0112, r1
    sts 0x0111, r1
    out 0x26, r1 ; 38

    czyli do 5 cykli maszynowych.

    Co do zerowania timera1 to faktycznie możesz mieć racje.
    Muszę to jeszcze sprawdzić.

    Generalnie podłączyłem sygnal z generatora 16Mhz który mierze do wysterowania także atmegi i mam swoją wartość 62500 :)

    • To teraz daj inne źródełko do taktowania, a generatorem (rozumiem że przestrajany) lekko zmień f i zobacz czy zmiany wyniku są płynne. Ewentualnie zwykły kwarc 16mhz i trymerek pozwoli to srpawdzić.

      Fajnie że udało się to poskromić. Jeśli kod przetestujesz i będzie działał poprawnie, i jeśli oczywiście chcesz, mogę go dodać do opisu jako alternatywa dla bascoma :)

  37. Oczywiście kod będzie udostępniony i nie widzę problemu abyś o nim wspomniał :)

  38. Ok porobiłem kilka dodatkowych testów.
    Niestety nie posiadam przestrajanego generatora, ale zamiast niego
    użyłem wspomnianego dzielnika dla różnych potęg dwójki.

    Oto wyniki:
    4MHz/256 = 15625 -> 15622
    4MHz/128 = 31250 -> 31244
    4MHz/64 = 62500 -> 62488
    4MHz/32 = 125000 -> 124975
    4MHz/16 = 250000 -> 249951
    4MHz/8 = 500000 -> 499901
    4MHz/4 = 1000000 -> 999803

    Co ciekawe dla dzielnika 2 i 1 dostaje już krzaki zamiast wyliczonej wartości.
    Znak końca linii jest na swoim miejscu (sprawdzany różny baudrate).
    Wygląda mi to na jakiś problem z przeliczeniami.

  39. Niestety dopiero koło niedzieli wrócę do tematu.
    Z tego co sprawdzałem to jest problem gdy zmienne s i m mają wpisana wartosc powyzej 1000000, dam znać gdy bede miał dostęp do miernika.

  40. Ok problem rozwiązany jeżeli chodzi o pomiar powyżej 1Mhz, spowodowany był brakiem resetowania rejestru r1 w przerwaniu timera0.

    Niestety sam dzielnik także może wpływać na precyzje pomiaru.
    Przy podziale 16Mhz przez 16 dostaje wynik: 00999998

    Generalnie kod działa już w miarę stabilnie także gdyby komuś się chciało pobawić to jest dostępny pod adresem https://bitbucket.org/hetii/freq

    Obecnie do reprezentacji danych używam wyświetlacza LED hcms2913 lub uarta.

    Dla innych wyświetlaczy postaram się napisać obsługę w wolnej chwili.

    Pozdrawiam.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Please leave these two fields as-is: