Spisu treści:

Licznik częstotliwości o wysokiej rozdzielczości: 5 kroków (ze zdjęciami)
Licznik częstotliwości o wysokiej rozdzielczości: 5 kroków (ze zdjęciami)

Wideo: Licznik częstotliwości o wysokiej rozdzielczości: 5 kroków (ze zdjęciami)

Wideo: Licznik częstotliwości o wysokiej rozdzielczości: 5 kroków (ze zdjęciami)
Wideo: Odjazdowy test słuchu: czy masz nadludzkie zdolności? 2024, Lipiec
Anonim

Ta instrukcja pokazuje odwrotny licznik częstotliwości zdolny do pomiaru częstotliwości szybko i z rozsądną precyzją. Wykonany jest ze standardowych komponentów i można go zrobić w weekend (zajęło mi to trochę dłużej:-))

EDYCJA: Kod jest już dostępny na GitLab:

gitlab.com/WilkoL/licznik-częstotliwości-wysokiej-rozdzielczości

Krok 1: Liczenie częstotliwości w starej szkole

Liczenie częstotliwości w starej szkole
Liczenie częstotliwości w starej szkole
Liczenie częstotliwości w starej szkole
Liczenie częstotliwości w starej szkole

Starym szkolnym sposobem mierzenia częstotliwości sygnału jest użycie logicznej bramki AND, podanie mierzonego sygnału do jednego portu i sygnału o dokładnie 1 sekundowym wysokim czasie do drugiego portu i zliczanie wyjścia. Działa to całkiem dobrze w przypadku sygnałów o częstotliwości kilku kHz w gHz. Ale co, jeśli chcesz zmierzyć sygnał o niskiej częstotliwości z dobrą rozdzielczością? Powiedzmy, że chcesz zmierzyć częstotliwość sieci (tutaj 50 Hz). Dzięki starej metodzie zobaczysz stałe 50 na ekranie, jeśli masz szczęście, ale bardziej prawdopodobne jest, że zobaczysz zmianę wyświetlacza z 49 na 50 lub z 50 na 51. Rozdzielczość wynosi 1 Hz i to wszystko. Nigdy nie zobaczysz 50,002 Hz, chyba że chcesz zwiększyć czas bramki do 1000 sekund. To ponad 16 minut na pojedynczy pomiar!

Lepszym sposobem pomiaru sygnałów o niskiej częstotliwości jest zmierzenie ich okresu. Biorąc ponownie przykład z sieci, ma okres 20 milisekund. Weź tę samą bramkę logiczną AND, podaj ją, powiedzmy 10 MHz (0,1 us impulsów) i twój sygnał na drugim porcie, a wyjdzie 200000 impulsów, więc okres czasu wynosi 20000,0 uS, co przekłada się z powrotem na 50 Hz. Kiedy mierzysz tylko 199650 impulsów, częstotliwość wynosi 50,087 Hz, to o wiele lepiej, i jest to tylko jedna sekunda czasu pomiaru. Niestety nie działa to dobrze przy wyższych częstotliwościach. Weźmy na przykład teraz chcemy zmierzyć 40 kHz. Z taką samą częstotliwością wejściową 10 MHz, jak w przypadku odniesienia, mierzymy teraz tylko 250 impulsów. Gdy policzymy tylko 249 impulsów, wyliczenie daje 40161 Hz, a przy 251 wynik to 39840 Hz. To nie jest akceptowalna rozdzielczość. Oczywiście zwiększenie częstotliwości odniesienia poprawia wyniki, ale jest limit tego, czego można użyć w mikrokontrolerze.

Krok 2: Wzajemna droga

Wzajemna droga
Wzajemna droga
Wzajemna droga
Wzajemna droga

Rozwiązaniem, które działa zarówno dla niskich, jak i wyższych częstotliwości, jest licznik odwrotności częstotliwości. Spróbuję wyjaśnić jego zasadę. Zaczynasz od czasu pomiaru, który wynosi około 1 sekundy, nie musi być bardzo dokładny, ale jest to rozsądny czas na pomiar. Podaj ten sygnał 1 Hz do D-flipflop na wejściu D. Na wyjściu (wyjściach) jeszcze nic się nie dzieje. Podłącz sygnał, który chcesz zmierzyć, do wejścia CLOCK przerzutnika D-flipflop.

Gdy tylko ten sygnał zmieni się z LOW na HIGH, wyjście przerzutnika D przekazuje stan wejścia D na wyjście (Q). Ten sygnał WSCHODZĄCY jest używany do rozpoczęcia zliczania sygnału wejściowego, a także referencyjnego sygnału zegarowego.

Tak więc liczysz DWA sygnały dokładnie w tym samym czasie, sygnał, który chcesz zmierzyć i zegar referencyjny. Ten zegar referencyjny musi mieć dokładną wartość i być stabilny, normalny oscylator kwarcowy jest w porządku. Wartość nie ma większego znaczenia, o ile jest to wysoka częstotliwość i jej wartość jest dobrze znana.

Po pewnym czasie, powiedzmy, kilku milisekundach, ponownie ustawiasz wejście D w D-flipflopie. Przy następnym wejściu CLOCK wyjście Q podąża za stanem wejścia, ale nic więcej się nie dzieje, ponieważ mikrokontroler jest ustawiony tak, aby reagował tylko na sygnał WZNOSZĄCY. Następnie po upływie czasu pomiaru (ok. 1 sekundy) ustawiasz wejście D na WYSOKIE.

Ponownie przy następnym wejściu CLOCK następuje wyjście Q i ten sygnał WZNOSZĄCY wyzwala mikrokontroler, tym razem kończąc zliczanie obu liczników.

Wynik to dwie liczby. Pierwsza liczba to liczba impulsów liczonych od referencji. Ponieważ znamy częstotliwość odniesienia, znamy również czas potrzebny na zliczenie tych impulsów.

Druga liczba to liczba impulsów z mierzonego sygnału wejściowego. Ponieważ zaczęliśmy dokładnie na zboczach narastających tego sygnału, jesteśmy bardzo pewni liczby impulsów tego sygnału wejściowego.

Teraz wystarczy tylko wyliczyć częstotliwość sygnału wejściowego.

Na przykład, powiedzmy, że mamy te sygnały i chcemy zmierzyć f-input. Odniesienie to 10 MHz, generowane przez oscylator kwarcowy. f_input = 31,416 Hz f_reference = 10000000 Hz (10 MHz), czas pomiaru wynosi około. 1 sekunda

W tym czasie naliczyliśmy 32 impulsy. Teraz jeden okres tego sygnału zajmuje 1/31.416 = 31830.9 uS. Tak więc 32 okresy zajęły nam 1,0185892 sekundy, czyli nieco ponad 1 sekundę.

W ciągu tej 1,0186 sekundy zliczymy również 10185892 impulsy sygnału odniesienia.

Daje nam to następujące informacje: liczba_wejść = 32 liczba_odniesień = 10185892 f_odniesienia = 10000000 Hz

Wzór na obliczenie częstotliwości wynikowej jest następujący: freq = (liczba_wejść * liczba_odniesień) / liczba_odn

W naszym przykładzie jest to: f-input = (32 * 10000000) / 10185892 = 31,416 Hz

I działa to dobrze zarówno dla niskich, jak i wysokich częstotliwości, tylko wtedy, gdy sygnał wejściowy zbliża się (lub nawet wyżej) do częstotliwości odniesienia, lepiej jest zastosować standardowy „bramkowy” sposób pomiaru. Ale wtedy moglibyśmy również po prostu dodać dzielnik częstotliwości do sygnału wejściowego, ponieważ ta odwrotna metoda ma taką samą rozdzielczość dla dowolnej częstotliwości (ponownie do wartości odniesienia). Więc niezależnie od tego, czy mierzysz 100 kHz bezpośrednio lub dzielone przez zewnętrzny dzielnik 1000x, rozdzielczość jest taka sama.

Krok 3: Sprzęt i jego schemat

Sprzęt i jego schemat
Sprzęt i jego schemat
Sprzęt i jego schemat
Sprzęt i jego schemat

Zrobiłem kilka tego typu liczników częstotliwości. Dawno temu zrobiłem taki z ATMEGA328 (ten sam kontroler, który jest w Arduino), później z mikrokontrolerami ARM firmy ST. Najnowsza została wykonana na STM32F407 taktowanym zegarem 168 MHz. Ale teraz zastanawiałem się, co jeśli zrobię to samo z *dużo* mniejszym. Wybrałem ATTINY2313, który ma tylko 2kbajty pamięci FLASH i 128 bajtów RAM. Wyświetlacz, który mam to MAX7219 z 8 siedmiosegmentowymi wyświetlaczami, te wyświetlacze są dostępne w serwisie eBay za jedyne 2 euro. ATTINY2313 można kupić za około 1,5 euro, pozostałe części, których użyłem, kosztują tylko centy za sztukę. Najdroższe było prawdopodobnie plastikowe pudełko projektowe. Później zdecydowałem, że będzie działał na akumulatorze litowo-jonowym, więc musiałem dodać stabilizator napięcia (LDO) 3,3 V, moduł ładujący akumulator i samą baterię. To nieco podnosi cenę, ale myślę, że można go zbudować za mniej niż 20 euro.

Krok 4: Kodeks

Kod
Kod
Kod
Kod

Kod został napisany w C w Atmel (Microchip) Studio 7 i zaprogramowany w ATTINY2313 przy użyciu OLIMEX AVR_ISP (klon?). Otwórz (main.c) w pliku zip poniżej, jeśli chcesz postępować zgodnie z opisem tutaj.

INICJALIZACJA

Najpierw ATTINY2313 został ustawiony na użycie zewnętrznego kryształu, ponieważ wewnętrzny oscylator RC jest bezużyteczny do pomiaru czegokolwiek. Używam kryształu 10 MHz, który dostrajam do właściwej częstotliwości 10 000 000 Hz za pomocą małego zmiennego kondensatora. Inicjalizacja zajmuje się ustawieniem portów na wejścia i wyjścia, konfiguracją timerów oraz włączaniem przerwań i inicjalizacją MAX7219. TIMER0 jest skonfigurowany do liczenia zegara zewnętrznego, TIMER1 zegara wewnętrznego, a także do przechwytywania wartości licznika na zboczu narastającym ICP, pochodzącego z D-flipflopa.

Główny program omówię na końcu, więc następne są procedury przerwań.

TIMER0_OVF

Ponieważ TIMER0 liczy do 255 (8 bitów), a następnie przechodzi do 0, potrzebujemy przerwania, aby zliczyć liczbę przepełnień. To wszystko, co robi TIMER0_OVF, po prostu policz liczbę przepełnień. Później ta liczba jest łączona z wartością samego licznika.

TIMER1_OVF

TIMER1 może liczyć do 65536 (16 bitów), więc przerwanie TIMER1_OVF również zlicza liczbę przepełnień. Ale robi więcej. Zmniejsza również od 152 do 0, co zajmuje około 1 sekundy, a następnie ustawia pin wyjściowy, przechodząc do wejścia D przerzutnika. A ostatnią rzeczą, jaką robi się w tej procedurze przerwania, jest zmniejszanie licznika czasu oczekiwania z 765 do 0, co zajmuje około 5 sekund.

TIMER1_CAPT

Jest to przerwanie TIMER1_CAPT, które jest wyzwalane za każdym razem, gdy przerzutnik D wysyła mu sygnał, na zboczu narastającym sygnału wejściowego (jak wyjaśniono powyżej). Logika przechwytywania dba o zapisanie wartości licznika TIMER1 w momencie przechwytywania, jest ona zapisywana wraz z licznikiem przepełnienia. Niestety TIMER0 nie posiada funkcji przechwytywania wejścia więc tutaj odczytywana jest jego aktualna wartość oraz aktualna wartość licznika przepełnienia. Zmienna komunikatu jest ustawiana na jeden, aby główny program powiedział, że są to nowe dane.

Dalej są dwie funkcje do sterowania MAX7219

SPI

Chociaż w chipie jest dostępny uniwersalny interfejs szeregowy (USI), postanowiłem go nie używać. Wyświetlacz MAX7219 musi być sterowany przez SPI i jest to możliwe dzięki USI. Ale bitbanging SPI jest tak prosty, że nie poświęciłem czasu na zrobienie tego z USI.

MAX7219

Protokół konfiguracji MAX7219 jest również dość prosty po przeczytaniu jego instrukcji. Potrzebuje 16-bitowej wartości dla każdej cyfry, która składa się z 8 bitów dla numeru cyfry (od 1 do 8), po którym następuje 8 bitów dla liczby, którą ma wyświetlić.

PROG GŁÓWNY

Ostatnią rzeczą jest wyjaśnienie głównego programu. Działa w nieskończonej pętli (while(1)), ale faktycznie robi coś tylko wtedy, gdy jest komunikat (1) z procedury przerwania lub gdy licznik limitu czasu zbliża się do zera (brak sygnału wejściowego).

Pierwszą rzeczą do zrobienia, gdy zmienna wiadomość jest ustawiona na jeden, jest zresetowanie licznika czasu oczekiwania, w końcu wiemy, że jest obecny sygnał. D-flipflop jest resetowany, aby był gotowy na następny wyzwalacz, który nastąpi po czasie pomiaru (czekaj sekundę).

Liczby zarejestrowane w przerwaniu przechwytywania są dodawane w celu uzyskania licznika odniesienia i licznika częstotliwości wejściowej. (musimy upewnić się, że odniesienie nigdy nie może wynosić zero, ponieważ później przez to będziemy dzielić)

Dalej jest obliczenie rzeczywistej częstotliwości. Z pewnością nie chcę używać liczb zmiennoprzecinkowych na mikrokontrolerze z zaledwie 2kbajtami pamięci flash i tylko 128 bajtami pamięci RAM, używam liczb całkowitych. Ale częstotliwości mogą być jak 314,159 Hz, z kilkoma miejscami po przecinku. Dlatego mnożę częstotliwość wejściową nie tylko przez częstotliwość odniesienia, ale także przez mnożnik, a następnie dodaję liczbę do miejsca, w którym powinien znajdować się przecinek dziesiętny. Te liczby staną się bardzo duże, gdy to zrobisz. Np. z wejściem 500 kHz, odniesieniem 10 MHz i mnożnikiem 100, daje to 5 x 10^14, to naprawdę ogromne! Nie będą pasować do 32-bitowej liczby, więc używam 64-bitowych liczb, które pójdą aż do 1,8 x 10^19 (to działa dobrze na ATTINY2313)

Ostatnią rzeczą do zrobienia jest przesłanie wyniku na wyświetlacz MAX7219.

Kod kompiluje się do około 1600 bajtów, więc pasuje do 2048 bajtowego flasha dostępnego w ATTINY2313.

Rejestry bezpieczników powinny brzmieć tak:

ROZSZERZONY 0xFF

WYSOKI 0xDF

NISKI 0xBF

Krok 5: Dokładność i precyzja

Dokładność i precyzja
Dokładność i precyzja
Dokładność i precyzja
Dokładność i precyzja
Dokładność i precyzja
Dokładność i precyzja

Dokładność i precyzja to dwie odrębne bestie. Dokładność wynosi tutaj siedem cyfr, a rzeczywista precyzja zależy od sprzętu i kalibracji. Skalibrowałem 10 MHz (5 MHz na punkcie testowym) z innym licznikiem częstotliwości, który ma zdyscyplinowany oscylator GPS.

I działa całkiem nieźle, najniższa częstotliwość jaką wypróbowałem to 0,2 Hz, najwyższa 2 MHz. To jest na miejscu. Powyżej 2 MHz kontroler zaczyna tracić przerwania, nic dziwnego, gdy wiadomo, że przy 2 MHz sygnał wejściowy TIMER0 generuje ponad 7800 przerwań na sekundę. A ATTINY2313 musi robić też inne rzeczy, przerwania z TIMER1, przy kolejnych 150 przerwaniach na sekundę i oczywiście wykonywać obliczenia, kontrolując wyświetlacz i D-flipflop. Kiedy spojrzysz na rzeczywiste urządzenie, zobaczysz, że używam tylko siedmiu z ośmiu cyfr wyświetlacza. Robię to z kilku powodów.

Po pierwsze, obliczanie częstotliwości wejściowej jest dzieleniem, prawie zawsze będzie miała resztę, której nie widzisz, ponieważ jest to dzielenie całkowite. Po drugie, oscylator kwarcowy nie jest stabilizowany temperaturowo.

Kondensatory dostrajające go do właściwych 10 MHz są ceramiczne, bardzo wrażliwe na zmiany temperatury. Jest też fakt, że TIMER0 nie ma wbudowanej logiki przechwytywania, a wszystkie funkcje przerwań potrzebują trochę czasu, aby wykonać swoją pracę. Myślę, że siedem cyfr i tak wystarczy.

Zalecana: