Съдържание:
- Стъпка 1: Преброяване на честотата в старото училище
- Стъпка 2: Реципрочният начин
- Стъпка 3: Хардуер и неговата схема
- Стъпка 4: Кодът
- Стъпка 5: Точност и прецизност
Видео: Честотен брояч с висока резолюция: 5 стъпки (със снимки)
2024 Автор: John Day | [email protected]. Последно модифициран: 2024-01-30 07:49
Тази инструкция показва реципрочен брояч на честоти, способен да измерва честоти бързо и с разумна точност. Изработен е със стандартни компоненти и може да бъде направен през уикенда (отне ми малко повече време:-))
EDIT: Кодът вече е достъпен в GitLab:
gitlab.com/WilkoL/high-resolution-frequency-counter
Стъпка 1: Преброяване на честотата в старото училище
Старият начин за измерване на честотата на сигнала е да се използва логически И-порта, да се подаде сигналът, който трябва да се измери в един порт, и сигнал с точно 1 секунда високо време към другия порт и да се преброи изхода. Това работи доста добре за сигнали от няколко kHz добре в GHz. Но какво, ако искате да измерите нискочестотен сигнал с добра разделителна способност? Кажете, че искате да измерите честотата на мрежата (тук 50 Hz). С метода на старата школа ще видите постоянни 50 на дисплея си, ако имате късмет, но по -вероятно ще видите превключвателя на дисплея от 49 на 50 или 50 на 51. Резолюцията е 1 Hz и това е всичко. Никога няма да видите 50.002 Hz, освен ако не желаете да увеличите времето за порта до 1000 секунди. Това е повече от 16 минути за едно измерване!
По -добър начин за измерване на нискочестотни сигнали е да се измери периодът му. Като отново вземем за пример електрическата мрежа, има период от 20 милисекунди. Вземете същата логика AND-gate, подайте я с, да речем 10 MHz (0,1 us импулса) и сигналът ви от другия порт и излезе 200000 импулса, така че периодът от време е 20000.0 uS и това се превежда обратно в 50Hz. Когато измервате само 199650 импулса, честотата е 50.087 Hz, това е много по -добре и е само за една секунда от времето за измерване. За съжаление това не работи добре с по -високи честоти. Вземете например, сега искаме да измерваме 40 kHz. Със същата входна честота 10 MHz като референтната сега измерваме само 250 импулса. Когато броим само 249 импулса, изчислението дава 40161 Hz, а с 251 резултатът е 39840 Hz. Това не е приемливо решение. Разбира се, увеличаването на референтната честота подобрява резултатите, но има ограничение за това, което можете да използвате в микроконтролер.
Стъпка 2: Реципрочният начин
Решение, което работи както за ниски, така и за по -високи честоти, е реципрочен брояч на честоти. Ще се опитам да обясня принципа му. Започвате с време за измерване, което е приблизително 1 секунда, не е задължително да е много прецизно, но е разумно време за измерване. Подайте този 1 Hz сигнал в D-тригер на D-входа. Все още нищо не се случва на изхода (ите). Свържете сигнала, който искате да измерите, към входа CLOCK на D-тригера.
Веднага след като този сигнал премине от LOW към HIGH, изходът на D-тригера прехвърля състоянието на D-входа към изхода (Q). Този RISING сигнал се използва за започване на преброяване на входния сигнал, както и на сигнала за еталонния часовник.
Така че броите ДВА сигнала точно по едно и също време, сигнала, който искате да измервате, и еталонния часовник. Този референтен часовник трябва да има точна стойност и да е стабилен, нормален кристален осцилатор е добре. Стойността не е много важна, стига да е с висока честота и нейната стойност да е добре известна.
След известно време, да речем няколко милисекунди, отново правите D-входа на D-тригера нисък. При следващия вход CLOCK изходът Q следва състоянието на входа, но нищо друго не се случва, защото микроконтролерът е настроен да реагира само на RISING сигнал. След това, след като времето за измерване приключи (приблизително 1 секунда), вие правите D-вход HIGH.
Отново при следващия CLOCK вход Q изходът следва и този RISING сигнал задейства микроконтролера, този път за прекратяване на броенето на двата брояча.
Резултатът е две числа. Първото число е броят на импулсите, преброени от еталона. Тъй като знаем референтната честота, знаем и времето, необходимо за преброяване на тези импулси.
Второто число е броят на импулсите от входния сигнал, който измерваме. Тъй като започнахме точно от RISING ръбовете на този сигнал, ние сме много уверени в броя на импулсите на този входен сигнал.
Сега е само изчисление за определяне на честотата на входния сигнал.
Например, да кажем, че имаме тези сигнали и искаме да измерим f-вход. Референтната стойност е 10 MHz, генерирана от кварцов кристален осцилатор. f_input = 31.416 Hz f_reference = 10000000 Hz (10 MHz), времето за измерване е прибл. 1 секунда
За това време преброихме 32 импулса. Сега, един период от този сигнал отнема 1 / 31.416 = 31830.9 uS. Така че 32 периода ни отнеха 1.0185892 секунди, което е малко над 1 секунда.
В тази 1.0186 секунда също ще сме преброили 10185892 импулса на референтния сигнал.
Това ни дава следната информация: input_count = 32 reference_count = 10185892 f_reference = 10000000 Hz
Формулата за изчисляване на получената честота е следната: freq = (input_count * f_reference) / ref_count
В нашия пример това е: f-input = (32 * 10000000) / 10185892 = 31.416 Hz
И това работи добре както за ниски честоти, така и за високи честоти, само когато входният сигнал се доближи (или дори по -висок от) до референтната честота е по -добре да се използва стандартният "затворен" начин на измерване. Но тогава бихме могли просто да добавим честотен делител към входния сигнал, тъй като този реципрочен метод има същата разделителна способност за всяка честота (отново до референтната). Така че независимо дали измервате 100 kHz директно разделено на външен разделител 1000x, разделителната способност е същата.
Стъпка 3: Хардуер и неговата схема
Направих няколко от този тип честотни броячи. Преди много време направих такъв с ATMEGA328 (същия контролер, какъвто има в Arduino), по -късно с ARM микроконтролери от ST. Последният е направен със STM32F407 с тактова честота 168 MHz. Но сега се чудех какво, ако направя същото с * много * по -малък. Избрах ATTINY2313, който има само 2kbyte FLASH памет и 128 байта RAM. Дисплеят, който имам, е MAX7219 с 8 седем сегментни дисплея, тези дисплеи се предлагат в Ebay само за 2 евро. ATTINY2313 може да се купи за около 1,5 евро, останалите части, които използвах, струват само центове на парче. Вероятно най -скъпа беше пластмасовата кутия за проекти. По-късно реших да го накарам да работи на литиево-йонна батерия, така че трябваше да добавя (LDO) 3.3V стабилизатор на напрежението, модул за зареждане на батерията и самата батерия. Това донякъде увеличава цената, но предполагам, че може да бъде построена за по -малко от 20 евро.
Стъпка 4: Кодът
Кодът е написан на C с Atmel (Microchip) Studio 7 и програмиран в ATTINY2313 с помощта на OLIMEX AVR_ISP (клониране?). Отворете (main.c) в zip файла по -долу, ако искате да следвате описанието тук.
ИНИЦИАЛИЗАЦИЯ
Първо ATTINY2313 беше настроен да използва външен кристал, тъй като вътрешният RC-осцилатор е безполезен за измерване на каквото и да било. Използвам 10 MHz кристал, който настройвам на правилната честота от 10 000 000 Hz с малък променлив кондензатор. Инициализацията се грижи за настройка на портове към входове и изходи, настройка на таймери и активиране на прекъсвания и инициализация на MAX7219. TIMER0 е настроен да отчита външен часовник, TIMER1 вътрешния часовник и също така да улавя стойността на брояча на нарастващия ръб на ICP, идващ от D-тригера.
Ще обсъдя последната основна програма, така че следващите са рутините за прекъсване.
TIMER0_OVF
Тъй като TIMER0 брои до 255 (8 бита) и след това се прехвърля към 0, се нуждаем от прекъсване, за да преброим броя на преливанията. Това е всичко, което TIMER0_OVF прави, просто пребройте броя на преливането. По -късно това число се комбинира със стойността на самия брояч.
TIMER1_OVF
TIMER1 може да брои до 65536 (16 бита), така че прекъсването TIMER1_OVF отчита и броя на препълненията. Но прави повече. Той също така намалява от 152 на 0, което отнема около 1 секунда и след това задава изходен щифт, отивайки към D-входа на тригер. И последното нещо, което се прави в тази рутина за прекъсване, е да се намали броячът на изчакване, преминавайки от 765 на 0, което отнема около 5 секунди.
TIMER1_CAPT
Това е прекъсването TIMER1_CAPT, което се задейства всеки път, когато D-тригерът му изпраща сигнал, при нарастващия ръб на входния сигнал (както е обяснено по-горе). Логиката за улавяне се грижи за запазването на стойността на брояча TIMER1 в момента на улавяне, тя се запазва, както и на брояча за препълване. За съжаление TIMER0 няма функция за улавяне на вход, така че тук се чете текущата му стойност и текущата стойност на брояча за препълване. Променлива на съобщението е зададена на единица, за да може основната програма да й каже, че това са нови данни.
Следват две функции за управление на MAX7219
SPI
Въпреки че в чипа има универсален сериен интерфейс (USI), аз избрах да не го използвам. Дисплеят MAX7219 трябва да се управлява чрез SPI и това е възможно с USI. Но bitbanging SPI е толкова прост, че не отделих време да го направя с USI.
MAX7219
Протоколът за настройка на MAX7219 също е доста прост, след като прочетете ръководството за него. Тя се нуждае от 16 -битова стойност за всяка цифра, която се състои от 8 бита за номера на цифрата (1 до 8), последвана от 8 бита за номера, който трябва да покаже.
ОСНОВНА ПРОГРАМА
Последното нещо е да обясним основната програма. Той работи в безкраен цикъл (while (1)), но всъщност прави нещо само когато има съобщение (1) от рутината за прекъсване или когато броячът на таймаут е спаднал до нула (няма входен сигнал).
Първото нещо, което трябва да направите, когато съобщението на променливата е настроено на единица, е да нулирате брояча на изчакване, в края на краищата знаем, че има сигнал. D-тригерът се нулира, за да бъде готов за следващото задействане, което ще дойде след времето за измерване (изчакайте секунда).
Номерата, регистрирани в прекъсването на улавяне, се добавят, за да се даде референтният брой и броят на входната честота. (трябва да се уверим, че препратката никога не може да бъде нула, тъй като по -късно ще я разделим)
Следва изчисление на действителната честота. Със сигурност не искам да използвам плаващи числа на микроконтролер само с 2kbytes флаш и само 128 байта RAM използвам цели числа. Но честотите могат да бъдат като 314.159 Hz, с няколко десетични знака. Затова умножавам входната честота не само с референтната честота, но и с умножител и след това добавям число към мястото, където трябва да отиде десетичната запетая. Тези цифри ще станат много много големи, когато направите това. Напр. с вход 500 kHz, референция от 10 MHz и множител 100, това дава 5 x 10^14, това е наистина огромно! Те няма да се впишат в 32 -битово число, така че използвам 64 -битови числа, които ще стигнат чак до 1,8 x 10^19 (това работи добре на ATTINY2313)
И последното нещо, което трябва да направите, е да изпратите резултата на дисплея MAX7219.
Кодът се компилира в около 1600 байта, така че се вписва във флаш от 2048 байта, наличен в ATTINY2313.
Регистрите на предпазителите трябва да четат така:
РАЗШИРЕН 0xFF
ВИСОК 0xDF
НИСКИ 0xBF
Стъпка 5: Точност и прецизност
Точността и прецизността са два отделни звяра. Точността тук е седем цифри, каква е действителната точност зависи от хардуера и калибрирането. Калибрирах 10 MHz (5 MHz на тестовата точка) с друг честотен брояч, който има GPS дисциплиниран осцилатор.
И работи доста добре, най -ниската честота, която опитах е 0,2 Hz, най -високата 2 MHz. Точно на място. Над 2 MHz контролерът започва да губи прекъсвания, което всъщност не е изненадващо, когато знаете, че при 2 MHz входен сигнал TIMER0 генерира над 7800 прекъсвания в секунда. А ATTINY2313 трябва да прави и други неща, прекъсванията от TIMER1, при още 150 прекъсвания в секунда и разбира се да правят изчисленията, като контролират дисплея и D-тригера. Когато погледнете действителното устройство, ще видите, че използвам само седем от осемте цифри на дисплея. Правя това по няколко причини.
Първото е, че изчислението на входната честота е деление, почти винаги ще има остатък, който не виждате, тъй като е цяло число. Второ е, че кварцовият кристален осцилатор не е стабилизиран при температура.
Кондензаторите, които го настройват на правилните 10 MHz, са керамични, много чувствителни към температурни промени. След това има фактът, че TIMER0 няма вградена логика за улавяне и всички функции за прекъсване отнемат известно време, за да свършат работата си. Все пак мисля, че седем цифри са достатъчно добри.
Препоръчано:
Прост честотен брояч, използващ Arduino: 6 стъпки
Прост честотен брояч с помощта на Arduino: В този урок ще научим как да направим прост честотен брояч с помощта на Arduino. Гледайте видеото
Честотен брояч с Arduino: 8 стъпки (със снимки)
Честотен брояч с Arduino: Това е прост и евтин честотен брояч, базиран на arduino, струва по -малко от 4 $, беше много полезно да се измерват малки вериги
Уеб камера с висока резолюция: 9 стъпки (със снимки)
Уеб камера с висока резолюция: В продължение на няколко години използвах уеб камера базирана на RPi (с модула PiCam). Произведените изображения бяха наред, но тогава имаше момент, в който вече не бях доволен от качеството. Реших да направя уеб камера с висока резолюция. Следните части ще
[3D печат] 30W ръчен фенер с висока мощност: 15 стъпки (със снимки)
[3D печат] 30W ръчен фенер с висока мощност: Ако четете това, вероятно сте виждали един от онези видеоклипове в Youtube, показващи DIY изключително мощни източници на светлина с огромни радиатори и батерии. Вероятно дори наричат това „фенери“, но винаги съм имал различна концепция за лант
Как да направите честотен аудио визуализатор за костюм (проект Arduino): 8 стъпки (със снимки)
Как да си направим честотен аудио визуализатор за костюм (проект Arduino): В този Instuctable ще дам съвети, планове и кодове, за да направя вълнуващ аудио визуализатор, вграден в костюм от пяна от фибростъкло. По пътя ще споделя полезни стъпки и допълнителни кодове, които някои, които искат да внедрят arduino FFT библиотеки в