Forum: Mikrocontroller und Digitale Elektronik warum timer drift


von am grundsätzlichstem (Gast)


Lesenswert?

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
4
5
6
ISR(TIMER0_COMP_vect)  //_evry 10ms Interrupt
7
{
8
  static int run=100;
9
  if(--run==0)
10
  {
11
    run=10;
12
    PORTG ^=(1<<RUNLED);
13
  }
14
}

von Michael U. (amiga)


Lesenswert?

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

von am grundsätzlichstem (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@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
1
#define F_CPU 8000000
2
#define F_TIMER 200
3
#define ORCxRELOAD ((F_CPU / F_TIMER) - 1)
4
5
#if ORCxRELOAD > 65535
6
#error Timer overflow. F_TIMER too low!
7
#endif
8
 
9
OCR0A = ORCxRELOAD;

Wenn das trotzdem nicht genau hinkommt, dann so.

AVR - Die genaue Sekunde / RTC

von Stefan F. (Gast)


Lesenswert?

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?

von Zweifler (Gast)


Lesenswert?

F_CPU=> 16.000.000 / 1024 * 10e-3 + 0.5 = 16,125 sagt mein 
Taschenrechner

von Stefan F. (Gast)


Lesenswert?

Und wenn man das in ein Byte (uint8_t>) umwandelt erhält man einen 
Rundungsfehler.

von Falk B. (falk)


Lesenswert?

@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.

von am grundsätzlichstem (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@Zweifler (Gast)

>F_CPU=> 16.000.000 / 1024 * 10e-3 + 0.5 = 16,125 sagt mein
>Taschenrechner

Dann sollte der nochmal nachsitzen ;-)

von Huh (Gast)


Lesenswert?

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...

von Falk B. (falk)


Lesenswert?

@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.

von am grundsätzlichstem (Gast)


Lesenswert?

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.

von Michael U. (amiga)


Lesenswert?

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

von Harald W. (wilhelms)


Lesenswert?

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"

von am grundsätzlichstem (Gast)


Lesenswert?

Harald W. schrieb:
> Du hast den Hauptsatz der Meßtechnik nicht verstanden:
> "Alle Konstanten sind variabel"

LOL :D

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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 ...

von Zweifler (Gast)


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?

@ 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 ;-)

von Falk B. (falk)


Lesenswert?

@ 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

von Michael U. (amiga)


Lesenswert?

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

von Zweifler (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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

von Zweifler (Gast)


Lesenswert?

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.

von Erwin D. (Gast)


Lesenswert?

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.

;-)

von Harald W. (wilhelms)


Lesenswert?

Zweifler schrieb:

> 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.

Du hattest eben den falschen Mathelehrer, wie wärs mit diesem:
http://www.golyr.de/pippi-langstrumpf/songtext-hey-pippi-langstrumpf-352346.html

von Stefan F. (Gast)


Lesenswert?

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.

von Ich lach mir nen Ast (Gast)


Lesenswert?

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 .....

von am grundsätzlichstem (Gast)


Lesenswert?

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!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.