mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik warum timer drift


Autor: am grundsätzlichstem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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


OCR0A = (uint8_t)(int16_t)(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
  TCCR0A |= (1<<WGM01)|(1<<CS02)|(1<<CS00);      // divide by 1024
  TIMSK0 |= (1<<OCIE0A);        // enable timer Compare A Interrupt


ISR(TIMER0_COMP_vect)  //_evry 10ms Interrupt
{
  static int run=100;
  if(--run==0)
  {
    run=10;
    PORTG ^=(1<<RUNLED);
  }
}

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: am grundsätzlichstem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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
#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;

Wenn das trotzdem nicht genau hinkommt, dann so.

AVR - Die genaue Sekunde / RTC

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Zweifler (Gast)
Datum:

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

Autor: Stefanus F. (stefanus)
Datum:

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

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: am grundsätzlichstem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Zweifler (Gast)

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

Dann sollte der nochmal nachsitzen ;-)

Autor: Huh (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: am grundsätzlichstem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Harald W. (wilhelms)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: am grundsätzlichstem (Gast)
Datum:

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

LOL :D

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 ...

Autor: Zweifler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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#Expon...

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zweifler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zweifler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Erwin D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

;-)

Autor: Harald W. (wilhelms)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ich lach mir nen Ast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 .....

Autor: am grundsätzlichstem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.