Mätning av frekvens, kul grej
Postat: 6 juni 2008, 14:21:44
Har ett projekt där jag ska mäta 3 olika signaler med frekvenser på mellan 50Hz och 50kHz, dessa ska sedan visas på ett textbaserat LCD.
Jag använder en Renesas M16C29 StarterKit till prototypen och det är kul. Den har 3 st Timer B... som kan programmeras att räkna tid mellan flanker på inkommande pulser.
Då de "bara" är på 16 bit kan det ju bli overflow vid låga frekvenser men dessa overflow ger en interrupt också, då med en flagga satt.
Jag har nu testat lite och med en mättid på 0,1 sek har jag en felvisning vid 48086Hz på 0,0208%! Det är jag ganska nöjd med faktisk.
Och hur gör jag då?
Varje stigande flank på insignalen överför Timerns värde till ett register varefter timern nollställs automatisk. Samtidig utlösas en interrupt och då tar jag och summerar den mätte tid i en 32-bit variabel, jag räknar "antal pulser"-räknaren upp med 1 också. Vid overflow på räknaren ökar jag högsta WORD i denna summeringsvariabel med 1, detta ger att jag kan mäta låga frekvenser med samma noggrannhet.
Alltså:
Tm = mätt tid
Ap = antal pulser.
Sum = Summeringsvariabeln (32 bit unsigned)
Varje interrupt ger alltså:
Sum = Sum + Tm
Ap = Ap + 1
När den summerade tiden då är uppe på måttiden (timer-motsvarighet till 0,1 sek) eller mer överförar jag de värden till en buffer och nollar dom för att starta om igen.
Värden i buffern räknar jag sedan ut till vilken frekvens det är och skriver ut detta på LCD'n.
Det "kluriga" i detta sätt är att jag dels mätar kort tid men mätar BÅDA antalet pulser OCH tiden, detta betyder att min uträkning som är uteslutande heltalsberäkning (via en 64-bitars variabel) blir så pass noga som den är fastän mätningen är så kortvarig.
Antalet pulser den räknar över varierar alltså kraftigt, från 1 vid lägsta frekvensen till ... en massa... vid högsta frekvensen.
Bäst hade dock varit om man kunde starta en prescaler som delar ner inkommande pulser, detta ville ge mindre belastning på CPU'n vid högre frekvenser men det kan ju byggas på externt om det behövs.
Jag har i testsyfte startat en Timer A som pulsgenerator, kopplat ihop med ett potentiometer på AD-ingången så att jag kan variera frekvensen med detta potentiometer, allt sitter i mitt StarterKit som jag har.
Jag har testat med olika mättider och jag har samma noggrannhet oavsett om jag kör med 1,0 sek mättid eller 0,1 sek.
Självklart kan jag köra med 1,0 sek mättid och bara räkna antal pulser, då ville jag få bra noggrannhet också men nu läser jag ut 10x snabbare med klart godkänd noggrannhet.
Jag använder en Renesas M16C29 StarterKit till prototypen och det är kul. Den har 3 st Timer B... som kan programmeras att räkna tid mellan flanker på inkommande pulser.
Då de "bara" är på 16 bit kan det ju bli overflow vid låga frekvenser men dessa overflow ger en interrupt också, då med en flagga satt.
Jag har nu testat lite och med en mättid på 0,1 sek har jag en felvisning vid 48086Hz på 0,0208%! Det är jag ganska nöjd med faktisk.
Och hur gör jag då?
Varje stigande flank på insignalen överför Timerns värde till ett register varefter timern nollställs automatisk. Samtidig utlösas en interrupt och då tar jag och summerar den mätte tid i en 32-bit variabel, jag räknar "antal pulser"-räknaren upp med 1 också. Vid overflow på räknaren ökar jag högsta WORD i denna summeringsvariabel med 1, detta ger att jag kan mäta låga frekvenser med samma noggrannhet.
Alltså:
Tm = mätt tid
Ap = antal pulser.
Sum = Summeringsvariabeln (32 bit unsigned)
Varje interrupt ger alltså:
Sum = Sum + Tm
Ap = Ap + 1
När den summerade tiden då är uppe på måttiden (timer-motsvarighet till 0,1 sek) eller mer överförar jag de värden till en buffer och nollar dom för att starta om igen.
Värden i buffern räknar jag sedan ut till vilken frekvens det är och skriver ut detta på LCD'n.
Det "kluriga" i detta sätt är att jag dels mätar kort tid men mätar BÅDA antalet pulser OCH tiden, detta betyder att min uträkning som är uteslutande heltalsberäkning (via en 64-bitars variabel) blir så pass noga som den är fastän mätningen är så kortvarig.
Antalet pulser den räknar över varierar alltså kraftigt, från 1 vid lägsta frekvensen till ... en massa... vid högsta frekvensen.
Bäst hade dock varit om man kunde starta en prescaler som delar ner inkommande pulser, detta ville ge mindre belastning på CPU'n vid högre frekvenser men det kan ju byggas på externt om det behövs.
Jag har i testsyfte startat en Timer A som pulsgenerator, kopplat ihop med ett potentiometer på AD-ingången så att jag kan variera frekvensen med detta potentiometer, allt sitter i mitt StarterKit som jag har.
Jag har testat med olika mättider och jag har samma noggrannhet oavsett om jag kör med 1,0 sek mättid eller 0,1 sek.
Självklart kan jag köra med 1,0 sek mättid och bara räkna antal pulser, då ville jag få bra noggrannhet också men nu läser jag ut 10x snabbare med klart godkänd noggrannhet.