Hallo,
ich habe hier: https://www.gammon.com.au/timers ein Codebeispiel für
einen Frequenzzähler gefunden (erster Code-Block unter "Frequency
Counter sketch for Atmega328"). Diesen Code möchte ich nun für einen 8
MHz (intern) Atmega 328P adaptieren.
Frage 1:
Wenn ich den Code richtig verstehe, dann müssen nur die Werte von 124
auf 7999 für OCR2A sowie TCCR2B von bit (CS20) | bit (CS22); auf bit
(CS20); abgeändert werden, so dass der Prescaler deaktiviert ist.
Wenn ich den Code dann aber mit einer festen Frequenz (aus dem
Frequenzgenerator) teste, wächst der im seriellen Monitor angezeigte
Wert kontinuierlich an bis irgendwann ein Overflow erreicht wird und er
von vorne hochzählt. Lasse ich den Code unverändert, dann wird eine
konstante Frequenz angezeigt, die halt falsch ist, da ich keine 16 MHz
verwende.
Kann mir jemand sagen, was ich übersehen haben könnte?
Frage 2:
Im Code von Nick Gammon kommt folgende Passage vor:
1
// if just missed an overflow
2
if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 256)
3
overflowCopy++;
Kann mir jemand erklären, was genau hier gemacht wird und warum?
Besonders was es mit dem Wert 256 auf sich hat?
Vielen Dank!
Ted
Lass doch den ganzen Code unverändert, du musst ja nur die Ausgabe
entsprechend umrechnen. Da der Timer nun mit 500Hz läuft, werden doppelt
so viele Pulse gezählt, also lediglich die Ausgabe auf
derTed schrieb:> Wenn ich den Code richtig verstehe, dann müssen nur die Werte von 124> auf 7999 für OCR2A
Einen 16 Bit Wert in ein 8 Bit Register zu schreiben, ist keine
sinnvolle Lösung. Lass den Timer2 einfach 2 ms Intervalle erzeugen und
skaliere wie folgt:
timerPeriod = ms/2;
Mit dem internen Takt vom 328 wirst Du nur sehr grobe Schätzwerte
erhalten.
Für tiefe Frequenzen ist der beschriebene Zähler mit fester Torzeit
unbrauchbar. Ich gebe Dir ein Programmbeispiel und eine Anpassung für
eine genauere Referenzfrequenz für einen Arduino UNO:
http://www.mino-elektronik.de/fmeter/fm_software.htm#bsp7
Hi,
oh, ich habe tatsächlich total übersehen, dass es sich um ein 8 Bit
Register handelt, vielen Dank für den Hinweis.
Ich werde mir auch mal dein Codebeispiel angucken.
Kann mir trotzdem noch jemand Frage 2 beantworten, nur für mein
Verständnis?
Danke!
Wenn man mit einen Hardware-Timer (hier T1) Ereignisse zählt und diese
zu einem bestimmten Zeitpunkt auslesen möchte, muß man die Überläufe
korrekt auswerten. Probleme kann es geben, wenn der Lesezugriff
gleichzeitig mit einem Überlauf oder während gesperrter Interrupts
auftritt.
ISR (TIMER1_OVF_vect)
{
++overflowCount; // count number of Counter1 overflows
} // end of TIMER1_OVF_vect
wird dann zu spät ausgeführt, sodaß overflowCount noch nicht
aktualisiert wurde. Das Ergebnis ist daher um 65536 (0x10000) zu
niedrig.
Ist TOV1 gesetzt und der gelesene Wert von T1 noch klein, gibt es noch
einen nicht bewerteten Überlauf, der beim Auslesen berücksichtigt werden
muß.
Die andere Möglichkeit wäre, daß T1 0xffff liefert und TOV1 gesetzt ist.
Hier muß der Überlauf nach dem Auslesen aufgetreten sein oder man hat
mehr als 4,096 ms bei der Auswertung "vertüddelt".
Die Grenze 256 (16 µs @ 16 MHz) ist mir zu knapp bemessen, weshalb ich
lieber 0x8000 verwende und damit der Auswertung eine deutlich längere
Zeit gebe.
Hi,
ist leider etwas länger her (hatte keine Zeit mich mit dem Thema weiter
zu beschäftigen und den Thread dann vergessen, sorry :( )
m.n. schrieb:> Die andere Möglichkeit wäre, daß T1 0xffff liefert und TOV1 gesetzt ist.> Hier muß der Überlauf nach dem Auslesen aufgetreten sein [...].
Dazu noch drei Verständnisfragen:
1. Ich verstehe den Teil "Überlauf muss nach dem Auslesen aufgetreten
sein" nicht so ganz. Kannst du das vielleicht nochmal etwas
ausführlicher erklären?
2. Warum brauche ich eigentlich die zusätzliche Prüfung auf einen Wert
(hier 256 oder die vorgeschlagenen 0x8000) überhaupt? Wenn TOV1 gesetzt
ist, dann muss T1 doch nur kleiner 0xffff sein. Der Wert (256) begrenzt
ja nur die messbaren Frequenzen zusätzlich. Und sollte tatsächlich TOV1
gesetzt sein und T1 > 0xffff, dann ist die Frequenz, die ich messen
will, für den µC sowieso zu schnell. Damit müsste ich doch nur TOV1
prüfen, oder?
3. Angenommen Counter #1 läuft über und die zugehörige ISR_1 soll
aufgerufen werden. Geht aber gerade nicht, da bereits eine andere (z.B.
ISR_2) läuft. Da der Überlauf ja TOV1 gesetzt hat, kann ISR_1
abgearbeitet werden, sobald die zurzeit laufende ISR_2 abgeschlossen
ist. Wenn ISR_2 jetzt aus irgendeinem Grund/Fehler sehr lange läuft
(und/oder Counter #1 zu schnell hochzählt) und während TOV1 gesetzt ist,
läuft Counter #1 ein weiteres Mal über. Verstehe ich es richtig, dass
dieser zweite Überlauf dann "verpufft", da er nirgends
zwischengespeichert werden kann (TOV1 ist ja noch vom ersten Überlauf
gesetzt)?
m.n. schrieb:> Für tiefe Frequenzen ist der beschriebene Zähler mit fester Torzeit> unbrauchbar.
Weshalb?
Nochmal vielen Dank!
Ted
>8 MHz (intern)
Die Präzision des eingebauten RC-Oszillators ist für einen
Frequenzzähler nicht berauschend. Im verlinkten Quelltext ist die Rede
von 16 MHz, das ist der Arduino Quarzoszillator.
derTed schrieb:> Diesen Code möchte ich nun für einen 8> MHz (intern) Atmega 328P adaptieren.
Wozu soll das gut sein? Der interne Takt ist dermaßen ungenau, dass es
völliger Schwachsinn ist, damit irgendwas "messen" zu wollen.
derTed schrieb:> Und sollte tatsächlich TOV1> gesetzt sein und T1 > 0xffff,
Beachte bitte, daß T1 niemals > 0xffff sein kann. Und dann denke noch
einmal neu nach.
Nach der langen Zeit habe ich keine Lust, alles wieder neu zu lesen.
Oder mache es so, wie Du meinst. Dann merkst Du selbst, daß der Überlauf
einer speziellen Betrachtung bedarf.
m.n. schrieb:> derTed schrieb:>> Und sollte tatsächlich TOV1>> gesetzt sein und T1 > 0xffff,>> Beachte bitte, daß T1 niemals > 0xffff sein kann. Und dann denke noch> einmal neu nach.> Nach der langen Zeit habe ich keine Lust, alles wieder neu zu lesen.>> Oder mache es so, wie Du meinst. Dann merkst Du selbst, daß der Überlauf> einer speziellen Betrachtung bedarf.
Gut, dann T1 = 0xffff. Darum ging es mir gar nicht. Ich hatte nicht
verstanden, was du mit der von mir, oben zitierten Aussage meintest. Ich
glaube, dass ich mittlerweile drauf gekommen bin.
Mir ist schon klar, dass die Überläufe einer speziellen Betrachtung
bedürfen... darf ich denn nicht nachfragen, wenn ich etwas nicht
komplett verstehe? Was soll denn die "Mach wie ich sage oder lass mich
in Ruhe"-Mentalität?
So viel Text hat der Thread jetzt auch wieder nicht...
chris_ schrieb:> Hier gäb's noch einen Frequenzzähler:> Beitrag "Frequenzzähler Uno"
Danke, gucke ich mir an!
derTed schrieb:> So viel Text hat der Thread jetzt auch wieder nicht...
Aber Du hattest einen anderen Code verlinkt, auf den sich Deine Frage
bezog. Den müßte man auch wieder ansehen ...
> Ich glaube, dass ich mittlerweile drauf gekommen bin.
Dann ist doch gut.
derTed schrieb:> darf ich denn nicht nachfragen, wenn ich etwas nicht> komplett verstehe?
Doch, darfst du! Jedoch erwarte ich dann eine genaue Beschreibung, bis
wohin du was verstehst und dann was du nun nicht mehr verstehst. Das ist
deine Arbeit an der Problemlösung und du wirst merken, dass der Zwang,
dein Verständnis und dein Unverständnis genau zu beschreiben, dich sehr
oft schon auf die Lösung stößt!
Als ich vor etlichen Jahren den Sprung von Windoof zu Linux gemacht
habe, habe ich auch Python gelernt. Und nach ausgiebigem
(Anfänger)Fragen im Python-Forum bin ich genau auf diesen Trichter
gekommen. Ich kann es jedem nur empfehlen, so mit seinen
Verständnisfragen umzugehen. Ist schon erstaunlich, was sich da an
Unverständnis einfach in Luft auflösen kann :-)
Gruß Rainer
Rainer V. schrieb:> derTed schrieb:>> darf ich denn nicht nachfragen, wenn ich etwas nicht>> komplett verstehe?>> Doch, darfst du! Jedoch erwarte ich dann eine genaue Beschreibung, bis> wohin du was verstehst und dann was du nun nicht mehr verstehst. Das ist> deine Arbeit an der Problemlösung und du wirst merken, dass der Zwang,> dein Verständnis und dein Unverständnis genau zu beschreiben, dich sehr> oft schon auf die Lösung stößt!
Hinzu kommt, daß dieses Problem immer und immer wieder angesprochen
wird. Da fehlt dann der Nerv, das jedesmal wieder ausführlich zu
erklären.
Rainer V. schrieb:> Jedoch erwarte ich dann eine genaue Beschreibung, bis> wohin du was verstehst und dann was du nun nicht mehr verstehst.
Naja, ich bin eigentlich der Meinung, dass ich das gemacht habe. Frage
#1 ist ja nur die Bitte, etwas neu zu formulieren.
m.n. schrieb:> Hinzu kommt, daß dieses Problem immer und immer wieder angesprochen> wird.
Gut, ist bei Foren nun mal so...
Würdet ihr mir bitte noch die folgenden Fragen beantworten?
derTed schrieb:> m.n. schrieb:>> Für tiefe Frequenzen ist der beschriebene Zähler mit fester Torzeit>> unbrauchbar.>> Weshalb?derTed schrieb:> 3. Angenommen Counter #1 läuft über und die zugehörige ISR_1 soll> aufgerufen werden. Geht aber gerade nicht, da bereits eine andere (z.B.> ISR_2) läuft. Da der Überlauf ja TOV1 gesetzt hat, kann ISR_1> abgearbeitet werden, sobald die zurzeit laufende ISR_2 abgeschlossen> ist. Wenn ISR_2 jetzt aus irgendeinem Grund/Fehler sehr lange läuft> (und/oder Counter #1 zu schnell hochzählt) und während TOV1 gesetzt ist,> läuft Counter #1 ein weiteres Mal über. Verstehe ich es richtig, dass> dieser zweite Überlauf dann "verpufft", da er nirgends> zwischengespeichert werden kann (TOV1 ist ja noch vom ersten Überlauf> gesetzt)?
Bezüglich den Werten 256 oder 0x8000 (Frage zwei von oben):
Eigentlich muss ich ja vom "Ende" der maximalen Counterzahl (65535) so
"weit" weg bleiben, dass in der Zeit, die die CPU vom Zwischenspeichern
des aktuellen Zählerwerts bis zum Prüfen, ob TOV1 gesetzt ist, die
maximale Frequenz (die gezählt/gemessen werden soll) keinen Überlauf
erzeugen kann, oder?