Innholdsfortegnelse:
- Trinn 1: Old School Frequency Counting
- Trinn 2: Den gjensidige måten
- Trinn 3: Maskinvare og skjematisk
- Trinn 4: Koden
- Trinn 5: Nøyaktighet og presisjon
Video: Høy oppløsning frekvens teller: 5 trinn (med bilder)
2024 Forfatter: John Day | [email protected]. Sist endret: 2024-01-30 11:20
Denne instruerbare viser en gjensidig frekvensmåler som er i stand til å måle frekvenser raskt og med rimelig presisjon. Den er laget med standardkomponenter og kan lages på en helg (det tok meg litt lengre tid:-))
EDIT: Koden er nå tilgjengelig på GitLab:
gitlab.com/WilkoL/high-resolution-frequency-counter
Trinn 1: Old School Frequency Counting
Den gamle skolemåten for å måle frekvensen til et signal er å bruke en logisk AND-gate, mate signalet som skal måles til en port og et signal med nøyaktig 1 sekund høy tid til den andre porten og telle utgangen. Dette fungerer ganske bra for signaler på noen få kHz godt inn i GHz. Men hva om du vil måle et lavfrekvent signal med god oppløsning? Si at du vil måle frekvensen for strømnettet (her 50 Hz). Med den gamle skolemetoden vil du se en konstant 50 på skjermen hvis du er heldig, men mer sannsynlig vil du se skjermbryteren fra 49 til 50 eller 50 til 51. Oppløsningen er 1 Hz, og det er det. Du vil aldri se 50,002 Hz med mindre du er villig til å øke porttiden til 1000 sekunder. Det er mer enn 16 minutter, for en enkelt måling!
En bedre måte å måle lavfrekvente signaler på er å måle perioden. Å ta strømnettet som et eksempel igjen, har en periode på 20 millisekunder. Ta den samme logikken OG-porten, mat den med, si 10 MHz (0,1 us pulser) og signalet ditt på den andre porten og ut kommer 200000 pulser, så periodetiden er 20000,0 uS og det oversetter tilbake til 50Hz. Når du måler bare 199650 pulser, er frekvensen 50.087 Hz, det er mye bedre, og den er på bare ett sekund målingstid. Dessverre fungerer dette ikke bra med høyere frekvenser. Ta for eksempel, vi vil nå måle 40 kHz. Med den samme 10 MHz inngangsfrekvensen som referansen måler vi nå bare 250 pulser. Når vi teller bare 249 pulser gir beregningen 40161 Hz og med 251 er resultatet 39840 Hz. Det er ikke en akseptabel løsning. Selvfølgelig forbedrer referansefrekvensen resultatene, men det er en grense for hva du kan bruke i en mikrokontroller.
Trinn 2: Den gjensidige måten
En løsning som fungerer for både lave og høyere frekvenser er en gjensidig frekvensmåler. Jeg skal prøve å forklare prinsippet. Du starter med en måltid som er omtrent 1 sekund. Det trenger ikke å være veldig presist, men det er en rimelig tid for en måling. Mat dette 1 Hz-signalet inn i en D-flipflop på D-inngangen. Ingenting skjer ennå på utgangen (e). Koble signalet du vil måle til CLOCK-inngangen på D-flip-floppen.
Så snart dette signalet går fra LOW til HIGH, overfører utgangen fra D-flipflop tilstanden til D-inngangen til utgangen (Q). Dette RISING -signalet som går, brukes til å begynne å telle inngangssignalet, så vel som et referanseklocksignal.
Så du teller TO signaler på nøyaktig samme tid, signalet du vil måle og en referanseklokke. Denne referanseklokken må ha en presis verdi og være stabil, en normal krystalloscillator er fin. Verdien er ikke veldig viktig så lenge det er en høy frekvens og verdien er godt kjent.
Etter en stund, si noen millisekunder, gjør du D-inngangen til D-flipfloppen lav igjen. Ved neste CLOCK-inngang følger utgangen Q tilstanden til inngangen, men ingenting annet skjer fordi mikrokontrolleren er satt til å reagere bare på et RISING-signal. Etter at måletiden er over (ca. 1 sekund) gjør du D-inngangen HØY.
Igjen ved neste CLOCK-inngang følger Q-utgangen, og dette RISING-signalet utløser mikrokontrolleren, denne gangen for å avslutte tellingen av begge tellere.
Resultatet er to tall. Det første tallet er antall pulser talt fra referansen. Som vi kjenner referansefrekvensen, vet vi også tiden det tok å telle disse pulser.
Den andre tallet er antallet pulser fra inngangssignalet vi måler. Da vi startet nøyaktig på RISING -kantene til dette signalet, er vi veldig sikre på antall pulser av dette inngangssignalet.
Nå er det bare en beregning for å bestemme frekvensen til inngangssignalet.
Et eksempel kan si at vi har disse signalene, og vi vil måle f-input. Referansen er 10 MHz, generert av en kvartskrystalloscillator. f_input = 31.416 Hz f_reference = 10000000 Hz (10 MHz), måltiden er ca. 1 sekund
På denne tiden telte vi 32 pulser. Nå tar en periode av dette signalet 1 / 31.416 = 31830.9 uS. Så 32 perioder tok oss 1.0185892 sekunder, som er litt over 1 sekund.
I dette 1.0186 sekundet vil vi også ha talt 10185892 pulser av referansesignalet.
Dette gir oss følgende informasjon: input_count = 32 reference_count = 10185892 f_reference = 10000000 Hz
Formelen for å beregne den resulterende frekvensen er denne: freq = (input_count * f_reference) / ref_count
I vårt eksempel er det: f-input = (32 * 10000000) / 10185892 = 31,416 Hz
Og dette fungerer bra for både lave og høye frekvenser, bare når inngangssignalet kommer nær (eller enda høyere enn) referansefrekvensen, er det bedre å bruke standard "gated" måling. Men så kunne vi også ganske enkelt legge til en frekvensdeler til inngangssignalet, da denne gjensidige metoden har samme oppløsning for enhver frekvens (opp til referansen igjen). Så om du måler 100 kHz direkte dividert med en ekstern 1000x divider, er oppløsningen den samme.
Trinn 3: Maskinvare og skjematisk
Jeg har laget noen få av denne typen frekvens tellere. For lenge siden laget jeg en med en ATMEGA328 (den samme kontrolleren som det er i en Arduino), senere med ARM mikrokontroller fra ST. Den siste ble laget med en STM32F407 klokket til 168 MHz. Men nå lurte jeg på hva om jeg gjør det samme med en * mye * mindre. Jeg valgte en ATTINY2313, som bare har 2 kbyte FLASH -minne og 128 byte RAM. Skjermen jeg har er en MAX7219 med 8 syv segmentdisplayer på den. Disse skjermene er tilgjengelige på Ebay for bare 2 euro. En ATTINY2313 kan kjøpes for rundt 1,5 euro. Resten av delene jeg brukte koster bare cent per stykk. Dyrest var sannsynligvis prosjektboks av plast. Senere bestemte jeg meg for å få det til å kjøre på et litiumionbatteri, så jeg trengte å legge til en (LDO) 3.3V spenningsstabilisator, en batterilademodul og selve batteriet. Dette øker prisen noe, men jeg antar at den kan bygges for under 20 euro.
Trinn 4: Koden
Koden ble skrevet i C med Atmel (Microchip) Studio 7 og programmert inn i ATTINY2313 ved hjelp av en OLIMEX AVR_ISP (klon?). Åpne (main.c) i zip -filen nedenfor hvis du vil følge beskrivelsen her.
INITIALISERING
Først ble ATTINY2313 satt til å bruke en ekstern krystall, ettersom den interne RC-oscillatoren er ubrukelig for å måle noe. Jeg bruker en 10 MHz krystall som jeg stiller inn på riktig 10 000 000 Hz frekvens med en liten variabel kondensator. Initialiseringen tar seg av å sette porter til innganger og utganger, sette opp tidtakere og muliggjøre avbrudd og initialisering av MAX7219. TIMER0 er konfigurert for å telle en ekstern klokke, TIMER1 den interne klokken og også for å fange verdien av telleren ved stigende kant av ICP, som kommer fra D-flipflop.
Jeg diskuterer hovedprogrammet sist, så neste er avbruddsrutinene.
TIMER0_OVF
Ettersom TIMER0 teller opptil 255 (8 bits) og deretter ruller over til 0, trenger vi en avbrudd for å telle antall overløp. Det er alt TIMER0_OVF gjør, bare tell antall overløp. Senere blir dette tallet kombinert med verdien av selve telleren.
TIMER1_OVF
TIMER1 kan telle opptil 65536 (16 bits), så avbruddet TIMER1_OVF teller også antall overløp. Men det gjør mer. Det reduseres også fra 152 til 0 som tar omtrent 1 sekund og deretter angir en utgangspinne, som går til D-inngangen til flipfloppen. Og det siste som gjøres i denne avbruddsrutinen er å redusere timeout-telleren, gå fra 765 til 0, som tar omtrent 5 sekunder.
TIMER1_CAPT
Dette er TIMER1_CAPT-avbruddet som utløses hver gang D-flipfloppen sender et signal til den stigende kanten av inngangssignalet (som forklart ovenfor). Capture -logikken tar seg av å lagre verdien av TIMER1 -telleren i øyeblikket for fangst, den lagres så vel som overløpstelleren. Dessverre har TIMER0 ikke en input -opptaksfunksjon, så her leses nåværende verdi og nåværende verdi for overløpstelleren. En meldingsvariabel er satt til en for hovedprogrammet for å fortelle at dette er nye data.
Neste er to funksjoner for å kontrollere MAX7219
SPI
Selv om det er et Universal Serial Interface (USI) tilgjengelig i brikken, valgte jeg å ikke bruke den. MAX7219 -skjermen må kontrolleres via SPI, og det er mulig med USI. Men bitbanging SPI er så enkelt at jeg ikke tok meg tid til å gjøre det med USI.
MAX7219
Protokollen for å sette opp MAX7219 er også ganske enkel når du har lest håndboken for den. Den trenger en 16 bits verdi for hvert siffer som består av 8 bits for siffernummeret (1 til 8) etterfulgt av 8 bits for tallet det trenger å vise.
HOVED-PROG
Det siste er å forklare hovedprogrammet. Den kjører i en uendelig sløyfe (mens (1)), men gjør faktisk bare noe når det er en melding (1) fra avbruddsrutinen eller når timeout -telleren har kjørt ned til null (ingen inngangssignal).
Det første du må gjøre når den variable meldingen er satt til en, er å tilbakestille timeout -telleren. Tross alt vet vi at det er et signal tilstede. D-flip-floppen tilbakestilles for å gjøre den klar for neste trigger som kommer etter måltiden (vent et sekund).
Tallene som er registrert i fangstavbruddet blir lagt til for å gi referansetall og inngangsfrekvenstelling. (vi må sørge for at referansen aldri kan være null, da vi vil dele med den senere)
Deretter er en beregning av den faktiske frekvensen. Jeg vil absolutt ikke bruke flytende tall på en mikrokontroller med bare 2 kbyte flash og bare 128 byte med ram jeg bruker heltall. Men frekvenser kan være som 314,159 Hz, med flere desimaler. Derfor multipliserer jeg inngangsfrekvensen ikke bare med referansefrekvensen, men også med en multiplikator, og legger deretter til et tall der desimaltegnet skal gå. Disse tallene blir veldig veldig store når du gjør det. F.eks. med en inngang på 500 kHz, en referanse på 10 MHz og en multiplikator på 100, gir dette 5 x 10^14, det er virkelig stort! De vil ikke lenger passe inn i et 32 biters tall, så jeg bruker 64 bit tall som vil gå helt opp til 1,8 x 10^19 (som fungerer fint på en ATTINY2313)
Og det siste du må gjøre er å sende resultatet til MAX7219 -skjermen.
Koden kompileres til rundt 1600 byte, så den passer inn i 2048 byte -blitsen som er tilgjengelig i ATTINY2313.
Sikringsregistrene skal se slik ut:
UTVIDET 0xFF
HØY 0xDF
LAV 0xBF
Trinn 5: Nøyaktighet og presisjon
Nøyaktighet og presisjon er to separate dyr. Presisjonen her er syv sifre, hva den faktiske presisjonen er, avhenger av maskinvaren og kalibreringen. Jeg kalibrerte 10 MHz (5 MHz på testpunktet) med en annen frekvensmåler som har en GPS -disiplinert oscillator.
Og det fungerer ganske bra, den laveste frekvensen jeg prøvde er 0,2 Hz, den høyeste 2 MHz. Det er spot on. Over 2 MHz begynner kontrolleren å miste avbrudd, egentlig ikke overraskende når du vet at ved 2 MHz inngangssignal genererer TIMER0 over 7800 avbrudd per sekund. Og ATTINY2313 må gjøre andre ting også, avbruddene fra TIMER1, med ytterligere 150 avbrudd per sekund og selvfølgelig gjøre beregningene, kontrollere displayet og D-flipflop. Når du ser på den faktiske enheten, ser du at jeg bruker bare syv av de åtte sifrene i displayet. Jeg gjør dette av flere grunner.
Det første er at beregningen av inngangsfrekvensen er en divisjon, den vil nesten alltid ha en rest, som du ikke ser da det er en heltalls divisjon. For det andre er at kvartskrystalloscillatoren ikke er temperaturstabilisert.
Kondensatorene som stiller den til riktig 10 MHz er keramiske, veldig følsomme for temperaturendringer. Så er det det faktum at TIMER0 ikke har innebygd logikk for fangst, og avbruddsfunksjonene tar litt tid å gjøre jobben sin. Jeg synes sju sifre er bra nok uansett.
Anbefalt:
Denne høy-spennings-klikk-klakk-lekestenen !: 11 trinn (med bilder)
This High Voltage Click-Clack Toy Rocks !: Her er to elektrostatiske versjoner av en retro Click-Clack-leketøy som var populære på videregående skoler tilbake på 70-tallet. Versjon 1.0 er superbudsjettmodellen. Deler (unntatt strømforsyningen) utgjør nesten ingenting. En beskrivelse av det dyrere
Fokuser Pi -kameraet av høy kvalitet med Lego og en servo: 4 trinn (med bilder)
Fokuser Pi -kameraet av høy kvalitet med Lego og en servo: Med et litt hacket Lego -stykke, en kontinuerlig servo og litt Python -kode kan du fokusere ditt Raspberry Pi -kamera av høy kvalitet fra hvor som helst i verden! Pi HQ -kameraet er et fantastisk stykke sett, men som jeg fant mens jeg jobbet med den siste Merlin
Hvordan lage LED -frontlykter med høy effekt for sykkel: 4 trinn (med bilder)
Hvordan lage LED -frontlykter med høy effekt for sykkel: Det er alltid praktisk å ha et sterkt lys mens du sykler om natten for tydelig syn og sikkerhet. Det advarer også andre på mørke steder og unngår ulykker. Så i denne instruksen vil jeg demonstrere hvordan du bygger og installerer en 100 watt LED p
Hvordan lage en frekvens lydvisualiserer for et kostyme (Arduino Project): 8 trinn (med bilder)
Hvordan lage en frekvenslydvisualiserer for et kostyme (Arduino -prosjekt): I denne Instuctable vil jeg gi tips, planer og koder for å lage en spennende lydvisualiserende innebygd i en glassfiberskumdrakt. Underveis vil jeg dele nyttige trinn og ekstra koder som noen ønsker å implementere arduino FFT -biblioteker i
Hvordan få bilder med høy oppløsning ut av instruksjoner: 4 trinn
Hvordan få bilder med høy oppløsning ut av instruksjoner: Likte du virkelig det instruerbare bildet og ønsket å lagre en kopi av det i høy oppløsning? Denne flotte lille funksjonen blir lett oversett