Guten Morgen!
Habe auf meinen At90CAN128 folgendes Problem.
Der Timer driftet ab und ich verstehe nicht warum.
Wenn ich die Zeit Messe vom Interrupt dann habe ich eine Zeit von 10ms
Das Runled ist aber nicht 1000ms sondern 1003ms.
Warum habe ich so einen großen Fehler?
Lg
1
OCR0A=(uint8_t)(int16_t)(F_CPU/1024*10e-3+0.5);// preload for 10ms
2
TCCR0A|=(1<<WGM01)|(1<<CS02)|(1<<CS00);// divide by 1024
3
TIMSK0|=(1<<OCIE0A);// enable timer Compare A Interrupt
Hallo,
F_CPU hast Du ja nicht angegeben, aber warum erwartest Du, daß bei F_CPU
/ (1,024 + 0,5) was rauskommt, was genau 10,00ms ergibtund nicht 10,03ms
wie offenbar in Deinem Fall?
Wieviel ergibt bei Dir F_CPU/1024 ?
Gruß aus Berlin
Michael
Michael U. schrieb:> Wieviel ergibt bei Dir F_CPU/1024 ?
Das ergiebt 15.625!
F_CPU ist 16000000.
Verstehe nicht was du meinst:-\
Danke Grüße aus München
@am grundsätzlichstem (Gast)
>Warum habe ich so einen großen Fehler?>OCR0A = (uint8_t)(int16_t)(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms
Die Zeile läßßt allein durch die 2 casts nichts Gutes verheißen.
Man kann nicht mit jedem CPU-Takt exakt 100ms erreichen, erst recht
nicht mit einem 1024er Vorteiler!!! Der macht das eher schlimmer! Mach
es
- ohne Vorteiler
- nur mit Ganzzahlen
Dann hat man deutlich bessere Chancen. Dabei muss allerdings die
ISR-Frequenz hoch genug sein, damit OCR1A nicht größer als 65535 wird
Was verwendest du denn als Taktquelle? Den R/C Oszillator? Oder einen
Keramik-Resonator? Oder einen Quarz, und wenn ja, welche Bauart? Und ist
der Oszillator kalibiriert? Sind Versorgungsspannung und Temperatur
stabil?
@am grundsätzlichstem (Gast)
>> Wieviel ergibt bei Dir F_CPU/1024 ?>Das ergiebt 15.625!>F_CPU ist 16000000.
Schön daß wir das jetzt wissen. Dann wollen wir mal Compiler spielen und
die Rechnung nachvollziehen.
#define F_CPU 16000000
OCR0A = (uint8_t)(int16_t)(F_CPU / 1024 * 10e-3 + 0.5); // preload for
10ms
F_CPU / 1024 = 15625 normale Ganzzahldiviiosn ohne Rest
* 10e-3 = 156,25 Fließkommarechnung
+ 0,5 = 156,75 Fließkommarechnung
Zuweisung an OCR1A = 156 (Nachkommastellen werden abgeschnitten).
Und was ergibt das als ISR-Frequenz?
16 MHz 1024 (156+1) = 99,522292993630573248407643312102 Hz
Softwareteiler / 10 macht daraus 9,9522292993630573248407643312102 Hz
Das sind -0,47% Fehler.
Michael U. schrieb:> Wieviel ergibt bei Dir F_CPU/1024 ?
Das ergibt 15.625!
F_CPU ist 16000000.
Verstehe nicht was du meinst:-\
Danke Grüße aus München
Falk B. schrieb:> #define F_CPU 8000000> #define F_TIMER 200> #define ORCxRELOAD ((F_CPU / F_TIMER) - 1)>> #if ORCxRELOAD > 65535> #error Timer overflow. F_TIMER too low!> #endif>> OCR0A = ORCxRELOAD;
Das -1 in deiner Formel ist das richtig beim timer Compare Interrupt?
Stefan U. schrieb:> Was verwendest du denn als Taktquelle? Den R/C Oszillator? Oder einen> Keramik-Resonator? Oder einen Quarz, und wenn ja, welche Bauart? Und ist> der Oszillator kalibiriert? Sind Versorgungsspannung und Temperatur> stabil?
Verwende ein SMD Quarz den Oszillator habe ich nicht kalibriert! Ist das
bei so langen Zeiten nötig?
Lg
Zweifler schrieb:> F_CPU=> 16.000.000 / 1024 * 10e-3 + 0.5 = 16,125 sagt mein> Taschenrechner
16000000/1024 = 15625
wo soll da die 15,125 herkommen?
Verkaufe den Taschenrechner...
@am grundsätzlichstem (Gast)
> #define ORCxRELOAD ((F_CPU / F_TIMER) - 1)>Das -1 in deiner Formel ist das richtig beim timer Compare Interrupt?
Ja, siehe Datenblatt. Denn der Timer zählt von 0-OCR1A, das sind OCR1A +
1 Takte.
>Verwende ein SMD Quarz den Oszillator habe ich nicht kalibriert!
Muss man auch nicht, der ist selbst mit vergurkten Lastkapazitäten auf
100-200ppm genau, das sind 0,02%
> Ist das bei so langen Zeiten nötig?
Der Stefan meinte den internen RC-Oszillator, denn muss man ggf.
kalibieren.
Falk B. schrieb:> Softwareteiler / 10 macht daraus 9,9522292993630573248407643312102 Hz>> Das sind -0,47% Fehler.
Oh nicht gut !!!
Was macht man da Sinnvolles?
Danke das du mir das so aufgezeigt hast.
Hallo,
am grundsätzlichstem schrieb:> Michael U. schrieb:>> Wieviel ergibt bei Dir F_CPU/1024 ?>> Das ergiebt 15.625!> F_CPU ist 16000000.> Verstehe nicht was du meinst:-\
Also einen Takt für den Counter mit 64µs Zykluszeit.
Für 10ms müßtest Du also durch 156,25 teilen.
Geteilt wird also wohl durch 157 wegen Deiner Rundung.
Macht dann also 10,048ms für einen Zyklus.
Passt doch ganz gut, die 16MHz sind ja auch nicht ohne Toleranz.
Vorteiler 256 und Count 256 - bei einem 16Bit-Counter dürfte die erste
Kombi sein, die genau 100Hz (10ms) ergibt.
Bei 8Bit-Counter wären es wohl Vorteiler 128, Counter 125 - 1 für 1ms
und dann eben in der ISR bis 10 zählen für 10ms.
Die Formelrechnerei macht nur Sinn, wenn man es nur ungefähr braucht...
Gruß aus Berlin
Michael
am grundsätzlichstem schrieb:> Der Timer driftet ab und ich verstehe nicht warum.
Du hast den Hauptsatz der Meßtechnik nicht verstanden:
"Alle Konstanten sind variabel"
am grundsätzlichstem schrieb:> Verwende ein SMD Quarz den Oszillator habe ich nicht kalibriert!
Wenn du einen Quarz verwendest gibt's nix zu kalibrieren.
Du hast also einem Quarz angelötet. Verwendest du ihn auch? Wie sind die
Fuses eingestellt?
> Ist das bei so langen Zeiten nötig?
Prozentuale Abweichungen sind unabhängig von der absoluten Dauer. Es ist
eher so, dass 1% Verlängerung einer Stunde viel länger ist, als 1% einer
Sekunde ...
am grundsätzlichstem schrieb:> (F_CPU / 1024 * 10e-3 + 0.5)Huh schrieb:> 16000000/1024 = 15625>> wo soll da die 15,125 herkommen?
Erklärst Du mir, wie Du mit 10e-3 und 0,5 aus der obigen Formel weiter
verfährst?
Unter der äußerst verwegenen Annahme, dass 10e-3 = 0,001 oder 1/1000
bedeutet?
@ Lothar Miller (lkmiller) (Moderator) Benutzerseite
>> Ist das bei so langen Zeiten nötig?>Prozentuale Abweichungen sind unabhängig von der absoluten Dauer. Es ist>eher so, dass 1% Verlängerung einer Stunde viel länger ist, als 1% einer>Sekunde ...
Das ist ABSOLUT richtig ;-)
@ Zweifler (Gast)
>Erklärst Du mir, wie Du mit 10e-3 und 0,5 aus der obigen Formel weiter>verfährst?
Sthet oben.
>Unter der äußerst verwegenen Annahme, dass 10e-3 = 0,001 oder 1/1000>bedeutet?
Das ist nicht nur verwegen sondern sogar richtig!
https://de.wikipedia.org/wiki/Gleitkommazahl#Exponentialschreibweise
Hallo,
Zeit ist relativ: wie lang 5 Minuten sind, hängt davon ab, auf welcher
Seite der Klo-Tür man ist...
Sein Problem ist doch aber: der Timer hat Binärzähler mit wenigen festen
Vorteilern. Da kann ich mit Kommastellen und Rundungen rechnen, wie ich
will, am Ende wird binär ganzzahlig geteilt.
Damit dürfen auch mit dem Taschenrechner nur ganzzahlige Ergebnisse
rauskommen, sonst passt es nicht.
Damit kann man für 10ms (100Hz) auch nur Vorteiler nehmen, wo das
Ergebnis hinten auf 2 Nullen endet, sonst gibt es keinen ganzzahligen
Teiler / 100 für das Count-Register.
Gruß aus Berlin
Michael
Falk B. schrieb:> Sthet oben.
Du meinst das hier:
Falk B. schrieb:> F_CPU / 1024 = 15625 normale Ganzzahldiviiosn ohne Rest>> * 10e-3 = 156,25 Fließkommarechnung
ok.
Falk B. schrieb:>>Unter der äußerst verwegenen Annahme, dass 10e-3 = 0,001 oder 1/1000>>bedeutet?>> Das ist nicht nur verwegen sondern sogar richtig!
15625 * 0,001 (oder *1/1000) ist demnach 156,25? Ahaaaa.
@ Zweifler (Gast)
>>>Unter der äußerst verwegenen Annahme, dass 10e-3 = 0,001 oder 1/1000>>>bedeutet?>>> Das ist nicht nur verwegen sondern sogar richtig!>15625 * 0,001 (oder *1/1000) ist demnach 156,25? Ahaaaa.
Natürlich nicht. 10e-3 = 10 * 10^-3 = 0,01 = 1/100
Falk B. schrieb:> @ Zweifler (Gast)>>>>>Unter der äußerst verwegenen Annahme, dass 10e-3 = 0,001 oder 1/1000>>>>bedeutet?>>>>> Das ist nicht nur verwegen sondern sogar richtig!>>>15625 * 0,001 (oder *1/1000) ist demnach 156,25? Ahaaaa.>> Natürlich nicht. 10e-3 = 10 * 10^-3 = 0,01 = 1/100
Ok, ich gebs auf. Gegen solch höhere Mathematik kommt man nicht an.
Ich akzeptiere: 10e-3 ist sowohl 0,001 als auch 0,01, je nachdem, wie Du
das brauchst.
Zweifler schrieb:> Ich akzeptiere: 10e-3 ist sowohl 0,001 als auch 0,01, je nachdem, wie Du> das brauchst.
Noch mal ganz langsam:
e-3 kann man auch schreiben als 1 x 10^-3. Das ist 1/1000
Also ist 10e-3 das zehnfache davon, also 10 x 10^-3, ergo 1/100.
;-)
Wie dem auch sei, ein Lösungsansatz wäre: Du rechnest aus, wie viel
Abweichung pro Timerinterrupt entsteht.
In der ISR erhöhst du bei jedem Interrupt eine float Variable um diesen
Wert.
Sobald die aufaddierten Fehler gleich (oder mehr) als ein Timer-Takt
sind, machst du
a) ändert du OCR0A einmal so dass das nächste Intervall genau einen Takt
kürzer als normal wird.
b) Die Variable wird um die Dauer eines Timertaktes verringert.
Beim nächsten Interrupt muss OCR0A wieder auf den "normalen" Wert zurück
gestellt werden.
Dadurch erreichst du, dass ab und zu ein Timer-Takt ausgelasen wird. Die
Interrupts werden ein kleines bisschen unregelmäßig aber dafür kommst du
insgesamt im Durchschnitt auf die gewünschten 10ms.
Im Prinzip entspricht das den Schaltjahren. Der Februar wird jedes
vierte Jahr ausnahmsweise um einen Tag verlängert, weil der Kalender zu
schnell ist.
Du musst aber ab und zu ein Timer-Intervall um einen Takt verkürzen,
weil dein Timer zu langsam läuft.
Stefan U. schrieb:> In der ISR erhöhst du bei jedem Interrupt eine float Variable um diesen> Wert.
... so so, in der ISR eine Floating Point Operation .....
Michael U. schrieb:> Hallo,>> am grundsätzlichstem schrieb:>> Michael U. schrieb:>>> Wieviel ergibt bei Dir F_CPU/1024 ?>> Das ergiebt 15.625!>> F_CPU ist 16000000.>> Verstehe nicht was du meinst:-\>> Vorteiler 256 und Count 256 - bei einem 16Bit-Counter dürfte die erste> Kombi sein, die genau 100Hz (10ms) ergibt.> Bei 8Bit-Counter wären es wohl Vorteiler 128, Counter 125 - 1 für 1ms> und dann eben in der ISR bis 10 zählen für 10ms.>> Die Formelrechnerei macht nur Sinn, wenn man es nur ungefähr braucht...>> Gruß aus Berlin> Michael
Dieser Ansatz hat mich jetzt auf eine sehr akzeptable Zeit basis
gebracht!!
Danke an alle für die Hilfe!