Forum: Mikrocontroller und Digitale Elektronik Ungenaue Sekunde bei Timer1 im CTC-Modus


von H. G. (ledi)


Lesenswert?

Hallo!

Meine Sekunde ist beim Timer1 im CTC-Modus keine genaue Sekunde! Nach 10 
Sekunden habe ich ca. eine Abweichung von 1 Sekunde. Ich verwende den 
ATtiny44.

Meine Frequenz beträgt 1MHz. Den Timer Compare Match habe ich auf 50000 
gesetzt. Also alle 20ms ein Timer-Interrupt.

Hier meine Initialisierung und die ISR:
1
void start_timer1(void)
2
{
3
  TIMSK1 |=  (1<<TOIE1);          // Timer1 overflow interrupt enable
4
  TIMSK1 |=  (1<<OCIE1A);        // Interrupt bei Timer Compare
5
  TCCR1B |=  (1<<CS10);          // Prescaler = 1 (f=1MHz)
6
  TCCR1B |=  (1<<WGM12);          // CTC-Mode (Clear Timer on Compare)
7
  OCR1A  =  50000;            // Set timer1 match to 50000
8
}
9
.
10
.
11
.
12
ISR (TIM1_COMPA_vect)
13
{
14
  if (overflow <= 20)        // count 20 timeroverflows ( 1 second )
15
    overflow ++;
16
17
  else
18
  {    
19
    PORTA |= (1<<PA5);
20
    overflow = 0;        // reset counter for timeroverflows
21
    sekunden ++;        // count seconds
22
23
    ADC_Wert = Read_ADC();    // ADC value (sense voltage) einlesen
24
    ADC_gesamt += ADC_Wert; 
25
    PORTA &= ~(1<<PA5);
26
  }
27
}

von Floh (Gast)


Lesenswert?

H. G. schrieb:
> if (overflow <= 20)        // count 20 timeroverflows ( 1 second )
>     overflow ++;

Wieviele Durchläufe gibt das?

von lex (Gast)


Lesenswert?

Diesen Denkfehler hatte ich letzte Woche auch mal :-)
Anstatt mit 50000 musst du das Compare Register mit 50000-1 laden, dann 
hast du den Überlauf wirklich nach 50000 Zählschritten.

Der Fehler summiert sich natürlich auf je länger deine Software läuft.

Viele Grüße,
lex

von Thomas E. (thomase)


Lesenswert?

H. G. schrieb:
> Meine Frequenz beträgt 1MHz.
Das sieht nach RC-Clock, intern  aus.
Die sind nicht 1MHz sondern ungefähr 1 MHz. 10% Abweichung ist natürlich 
eine Menge Holz aber nicht auszuschliessen. Für genaue Timings brauchst 
du einen Quarz.

mfg.

von Matthias (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Für genaue Timings brauchst du einen Quarz.

Für Quarzuhrgenauigkeit reicht das alleine noch nicht. Aber das läßt 
sich korrigieren:
Beitrag "Die genaue Sekunde / RTC"

von H. G. (ledi)


Lesenswert?

Floh schrieb:
> H. G. schrieb:
>> if (overflow <= 20)        // count 20 timeroverflows ( 1 second )
>>     overflow ++;
>
> Wieviele Durchläufe gibt das?

20

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

H. G. schrieb:

> Meine Frequenz beträgt 1MHz. Den Timer Compare Match habe ich auf 50000
> gesetzt. Also alle 20ms ein Timer-Interrupt.

Die Formel für den OCR-Wert im CTC-Mode ist:

(unsigned long) F_CPU / PRESCALE / IRQS -1

F_CPU    = 1000000
PRESCALE = 1
IRQS     = 1 / 20m = 50

--> OCR1A = 19999

von H. G. (ledi)


Lesenswert?

Johann L. schrieb:
> H. G. schrieb:
>
>> Meine Frequenz beträgt 1MHz. Den Timer Compare Match habe ich auf 50000
>> gesetzt. Also alle 20ms ein Timer-Interrupt.
>
> Die Formel für den OCR-Wert im CTC-Mode ist:
>
> (unsigned long) F_CPU / PRESCALE / IRQS -1
>
> F_CPU    = 1000000
> PRESCALE = 1
> IRQS     = 1 / 20m = 50
>
> --> OCR1A = 19999

Das verstehe ich jetzt nicht. warum 20000 bzw.19999?

Der Mikrocontroller wird mit 1 MHz betrieben. Bei einem Teiler von 1 
zählt der Timer also mit 1000000 / 1 = 1000000 Pulsen pro Sekunde.
Wenn ich den Timer nun mit 50000 vorlade, dann erhalte ich demnach 20 
Überläufe pro Sekunde. Also ist nach 20 Überläufen "genau" eine Sekunde 
vergangen.

von Falk B. (falk)


Lesenswert?

@H. G. (ledi)

>zählt der Timer also mit 1000000 / 1 = 1000000 Pulsen pro Sekunde.

Jao.

>Wenn ich den Timer nun mit 50000 vorlade,

Nix Vorladen, das ist der VERGLEICHSWERT, nachdem der Zähler wieder bei 
Null anfängt.

> dann erhalte ich demnach 20

Nö, einen Bruchteil weniger. Er zählt von 0-50000, damit einen Takt zu 
lange. 0-49999 sind 5000 Takte und damit exakt.

MFG
Falk

von H. G. (ledi)


Lesenswert?

Ja, natürlich Vergleichswert! Sorry!

von Peter II (Gast)


Lesenswert?

teste es doch einfach im Simulator, der zeigt genau an wie lange die 
sekunde ist. Dann kannst du wenigsten den Quarz( oder RC) als 
fehlerquelle ausschließen. Wenn die simulation schon nicht stimm, dann 
brauchst du es auch nicht auf der hardware laufen zu lassen.

von H. G. (ledi)


Lesenswert?

Danke für den Hinweis. Aber ich habs schon. Es liegt an der 
Ungenauigkeit der internen RC. Ich habe am Matchwert etwas geschraubt 
und im Test passt das nun ganz gut. Und da ich es nicht ganz genau 
brauche, reicht das für meine Anwendung.

von Karl H. (kbuchegg)


Lesenswert?

H. G. schrieb:
> Floh schrieb:
>> H. G. schrieb:
>>> if (overflow <= 20)        // count 20 timeroverflows ( 1 second )
>>>     overflow ++;
>>
>> Wieviele Durchläufe gibt das?
>
> 20

Nö. 21

Zähl nach. Angenommen da stünde nicht 20 sondern 5 (kleiner Zahl damit 
wir nicht s0 viel schreiben müssen). Wieviele Zählvogänge hast du bei 
...


  if( overflow <= 5)
    overflow++;
  else
    overflow = 0;

bis du von 0 einmal rundum wieder bei 0 bist

  0  -
  1  - 1 Zählvorgang
  2    2
  3    3
  4    4
  5    5
  0    6

zähl nach: nach 6 mal erhöhen bist du einmal rundum wieder bei 0 
angelangt.
(UNd genau aus dem gleichen Grund musst du auch das OCR Register um 1 
weniger laden)

In den allermeisten Fällen musst du sofort zusammenzucken, wenn du in C 
ein <= im Zusammenhang mit irgendwelchen Zählsachen siehst. Meistens ist 
es falsch. Aus genau dem gleichen Grund wird zb eine for Schleife 
meistens diese Gestalt haben

    for( i = 0; i < 5; i++ )

diese Schleife wird 5-mal durchlaufen.

von Karl H. (kbuchegg)


Lesenswert?

> Es liegt an der Ungenauigkeit der internen RC.

Auch. Aber das ist nicht alles. Du hast einen Denkfehler bei der 
Zählung.
Eigentlich hast du in deinem Programm 3 Fehler

* den internen RC
* den falschen Compare Wert
* du zählst nicht 20 sondern 21 Wiederholungen

Durch Anpassen des Compare Wertes kannst du alle zum Verschwinden 
bringen. Aber insbesondere der 20-21 Fehler ist dadurch ja immer noch im 
Programm.

von H. G. (ledi)


Lesenswert?

Ohhhhh jaaaaa, stimmt! Danke für den Hinweis!

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.