ATTiny44: Timer-Frequenz ändert in Abhänigkeit des Main-Programms

#1292168
Lesenswert?

Hallo zusammen

Ich benutze einen ATTiny44. Mit dem Timer1 (OC1A) erzeuge ich ein 
Rechtecksignal, toggle bei compare (0xFFFF). Ich messe diesen Rechteck. 
Die Pulsdauer ist zwischen 63-65ms. Hier liegt das Problem, je nach dem 
was für Code im Main ist, ändert sich die Pulsdauer. Wieso? Irgendwelche 
Ideen?


Zusätzliche Info:
-Interner RC-Oscillator
-fclk: 8MHz
-Prescaler fclk/8
-Int.: keine (Selbes Problem wenn der Ausgang in der ISR getoggelt wird)
-OSCAL verändert sich nicht. (Nicht Codeabhängig)
-AVR-Studio + GNU GCC Compiler
-Versorgungsspannung ist stabil


Vielen Dank für eure Hilfe!!!
Gruss
Hans-Jörg
#1292417
Lesenswert?

Meine These:
Thermische Änderungen auf dem 'Die' (also der Silizium-Pille). Der 
RC-Oszillator reagiert recht sensibel auf Temperaturänderungen, weswegen 
man ihn auch nicht für Anwendungen nehmen sollte, die ein präzises 
Timing erfordern. Ein wenig wundern tue ich mich allerdings über das 
Ausmaß der Änderung. Wenn der Timer tatsächlich kalibriert wäre, so 
sollte die Frequenz innerhalb von ±1% bleiben - 63ms...65ms sind aber 
etwa ±1,6%.
Das was die Frequenz (mehr oder weniger) stark beeinflußt ist a) die 
Betriebsspannung und b) die Temperatur. Schau mal im Datenblatt zum 
ATTiny44 nach. Da ich gerade kein Datenblatt vom ATTiny44 bei mir 
vorliegen hatte, habe ich mal das vom ATmega16 genommen und konnte 
folgendes eruieren:
Von z.B. 20°C auf 60°C ändert sich die Frequenz um etwa -2,6% und bei 
einer Betriebsspannungsänderung von 5V auf 4,5V sinkt die Frequenz um 
etwa -1,3%. Wenn beides gleichzeitig auftritt kann man sich ja 
vorstellen wie stark dann die Frequenz abdriftet bzw. absackt.
Gast #1292453
Lesenswert?

>Wenn der Timer tatsächlich kalibriert wäre

wäre die absolute Frequenz genauer. Aber schwanken darf er kalibiert wie 
unkalibriert gleichviel.

Der Oszillator des Tiny44 scheint etwas unempfindlicher als der des 
Mega16 zu sein, vor allem gegen Schwankungen von VCC, aber bei großem 
Temperaturhub (und viel Pech) kommen da schon 2ms zusammen. Bleibt nur 
die Frage, warum der Prozessor mit mehr Code in der main-loop soviel 
wärmer werden sollte. Läuft der vielleicht mit mehr als 5,5V?

Oliver
#1292459
Lesenswert?

Auf dem 'Die' kann das mit den Temperaturänderungen durchaus passieren. 
Es hängt davon ab wo genau der RC-Oszillator lokalisiert ist und wo sich 
irgendwelche Rechenwerke, Register, etc. in unmittelbarer Nachbarschaft 
befinden. Bei PC-CPUs mit ihren recht großen 'Die's ist das 'thermal 
managment' auf 'Die'-Ebene bereits sehr wichtig, um sogenannte hot-spots 
zu vermeiden. Bei den vergleichsweise kleinen ATTiny's, ATmega's, usw. 
ist dieses Problem noch nicht so kritisch aber auftreten tut es auch bei 
ihnen. Das Siliziumm wird partiell an der einen Stelle heißer als an 
anderer Stelle. Und das hängt tatsächlich davon ab, was auf der CPU 
läuft oder besser gesagt welche Befehle in welcher Reihenfolge 
drankommen.
#1292532
Lesenswert?

Die Spannung ist genau 5.0V.

Mit Kältespray wird sich die Frequenz ziemlich sicher änder. Aber ich 
habe ja keine Temperaturänderungen von aussen. Oder wenigstens nicht so 
schnell, dass ich zwei verschiedene Codes runterladen und ausführen 
kann.

Hmmm, so wie es aussieht müsste man das ganze Quarzstabilisiert machen. 
Oder was meint ihr? Keine andere alternative mit dem internen 
RC-Oszillator?
Gast #1292559
Lesenswert?

Hallo zusammen,

mal nebenbei, obwohl die Diskussion über das Temperaturverhalten von ICs 
auch ganz interessant ist, folgendes:

Vielleicht liegt es doch am Programm?! Ich habe mal in einem Projekt, in 
dem es auf ganau gleichmäßige tzeitliche Verteilung von Ereignissen 
ankam, festgestellt, dass if-then-else-Anweisungen (im vorliegenden 
Programm meine ich damit den Konstrukt in der Timerroutine) je nach 
Zutreffen der Bedingung zeitlich gesehen ungleichmäßig angearbeitet 
werden. Wenn der if-Zweig zutrifft, ist die Verarbeitungsdauer kürzer, 
trifft erst der else-Zweig zu, dauert es länger. Wenn man darüber 
nachdenkt warum, ist das auch logisch.

Ich bin bei meinem konkreten Fall dann auf switch ungestiegen, weil hier 
mit absoluten und damit zeitlich immer konstanten Zeitverhalten 
gearbeitet wird. Was dann auch zum gewünschten Erfolg geführt hat.

Grüße Uwe
Gast #1292570
Lesenswert?

>Keine andere alternative mit dem internen RC-Oszillator?

Die kurzzeitigen Schwankungen des RC-Oszillators sind, entgegen der 
üblichen Annahmen, auch bei stabiler Umgebungstemperatur, trotzdem 
instabil. Ein Grund ist sicherlich die schon erwähnte Die-Temperatur 
die, je nach Auslastung der Teilfunktionen des uc sicherlich schwanken 
wird. Ein anderer die daraus folgenden Schwankungen der Spannung auf dem 
Chip.

Ich hatte schon mehrere Projekte, wo ich z.B. RS232-Kommunikation nicht 
mit dem RC-Oszillator stabil hinbekommen habe.

Eine Möglichkeit wäre, den Oszillator anhand irgendeines anderen 
Eingangssignals, das definitiv stabil und genau ist, zu kalibrieren. 
Z.B. die Eingangs-RS232-Signale nehmen, auf Flanken warten und ein Bit 
abmessen. Geht natürlich nur wenn die Datenrate ok ist. Aber ein PC z.B. 
sollte deutlich besser sein da seine UART-Rate von einem Quarz erzeugt 
wird. (Der Schwerpunkt liegt hier auf der stabilen RS232-Kommunikation). 
Das gleiche sollte mit irgendeinem anderen stabilen und genauen Signal 
gehen, das Du vielleicht sowieso bekommst.
#1292589
Lesenswert?

Nez schrieb:
> Ich meine ich hätte hier auch schon ein Beispiel für die Kalibrierung
> des RC-Oszillators anhand eines RS232-Eingangssignales gesehen. Am
> besten mal nach Kalibrierung bzw. OSCCAL (das ist das Register) suchen.

Das Problem, so wie ich das verstanden habe, ist ja nicht der Zahlenwert 
an sich, sondern dass er unmotiviert schwankt je nachdem was die CPU 
gerade zu tun hat.
Gast #1292598
Lesenswert?

@ Karl heinz Buchegger

>Das Problem, so wie ich das verstanden habe, ist ja nicht der Zahlenwert
>an sich, sondern dass er unmotiviert schwankt je nachdem was die CPU
>gerade zu tun hat.

Kann sein, das ich was anders verstanden habe als Du.
Das der Code die Pulsbreite verändert wurde verworfen, weil die Pulse 
ausschliesslich in Hardware erzeugt werden. Die These, das der 
RC-Oszillator nicht stabil ist, steht noch im Raum.

Du selbst hast geschrieben (OK. Ein berühmter Mann meinte mal: Was 
kümmert mich mein Geschwätz von gestern, aber ich zitiere Dich trotzdem 
mal):
>Das Signal wird von der Hardware eigenständig generiert. Die Genauigkeit
>hängt einzig und alleine davon ab, wie gleichmässig der Timer hochzählt.
>Und das wiederrum hängt nur von einer gleichmässigen Taktversorgung ab.

Ich kann nicht ganz folgen, was Du mit dem "Zahlenwert" meinst. 
Vielleicht habe ich das was nicht richtig verstanden. Meinst Du den 
Ladewert für das Register das die Pulsbreite bestimmt?
#1292610
Lesenswert?

Nez schrieb:

> Ich kann nicht ganz folgen, was Du mit dem "Zahlenwert" meinst.
> Vielleicht habe ich das was nicht richtig verstanden. Meinst Du den
> Ladewert für das Register das die Pulsbreite bestimmt?

Nein.
Beispiel:

Lässt er diese Programm laufen
1
main (void)
2
{
3
  //Initialisierung f�r Counter1
4
  TCCR1B |= (1<<CS11);      //Timer on, prescaler 8
5
  TCCR1A |= (1<<COM1A0);      //Toggle OC1A on compare Timer1
6
  OCR1A = 0xFFFF;
7
  
8
  DDRA |= (1<<DDA6);      //Set PA6/OC1A as output
9
  DDRA |= (1<<DDA5);      //Set PA5/OC1B as output
10
    
11
  for (;;)
12
  {  
13
  }
14
  return (0);
15
}

Dann erhält er am OC1A Pin ein Rechteck mit 63ms Pulsbreite.

Lässt er hingegen dieses Programm laufen
1
main (void)
2
{
3
  //Initialisierung f�r Counter1
4
  TCCR1B |= (1<<CS11);      //Timer on, prescaler 8
5
  TCCR1A |= (1<<COM1A0);      //Toggle OC1A on compare Timer1
6
  OCR1A = 0xFFFF;
7
  
8
  DDRA |= (1<<DDA6);      //Set PA6/OC1A as output
9
  DDRA |= (1<<DDA5);      //Set PA5/OC1B as output
10
    
11
  for (;;)
12
  {  
13
    if (PINA & (1<<PINA2))
14
    {
15
      PORTA |= (1<<PORTA2);
16
    }
17
    else
18
    {
19
      PORTA &= ~(1<<PORTA2);
20
  }
21
  return (0);
22
}

Dann ist sein Rechteckpuls plötzlich 65ms breit. Innerhalb der Mainloop 
gibt es keinen Grund dafür. In beiden Programmen werkelt der Timer 
eigenständig vor sich hin und generiert die Pulse. In beiden Programmen 
wird der Timer identisch initialisiert und macht dasselbe. Und doch ist 
die erzeugte Frequenz in beiden Programmen unterschiedlich.
Gast #1292634
Lesenswert?

@  Karl heinz Buchegger

Uups. Dann habe ich tatsächlich was nicht verstanden. Zumindest habe ich 
gemeint, das der Effekt, entgegen der Annahme des Thread-Eröffners doch 
an der Ozs.-Stabilität liegt. Aber wenn das, tatsächlich so ist, wie Du 
oben schilderst: Verblüffend.

Was ich mir noch denken könnte, ist das die Tatsache, das OC1X auf dem 
selben Port liegt, der auch in der main-Schleife manipuliert wird. Der 
Theorie nach dürfte das nichts machen. (So ganz grob geschätzt).
Aber ich wäre doch mal neugierig, was passiert, wenn man in der 
main-loop nicht PortA manipuliert sondern PortB (oder falls das nicht 
geht, irgendein Arbeitsregister).

Also so:
1
main (void)
2
{
3
  //Initialisierung f�r Counter1
4
  TCCR1B |= (1<<CS11);      //Timer on, prescaler 8
5
  TCCR1A |= (1<<COM1A0);      //Toggle OC1A on compare Timer1
6
  OCR1A = 0xFFFF;
7
  
8
  DDRA |= (1<<DDA6);      //Set PA6/OC1A as output
9
  DDRA |= (1<<DDA5);      //Set PA5/OC1B as output
10
    
11
  for (;;)
12
  {  
13
    if (PINB & (1<<PINB2))
14
    {
15
      PORTB |= (1<<PORTB2);
16
    }
17
    else
18
    {
19
      PORTB &= ~(1<<PORTB2);
20
  }
21
  return (0);
22
}
#1292640
Lesenswert?

Nez schrieb:
> @  Karl heinz Buchegger
>
> Uups. Dann habe ich tatsächlich was nicht verstanden. Zumindest habe ich
> gemeint, das der Effekt, entgegen der Annahme des Thread-Eröffners doch
> an der Ozs.-Stabilität liegt. Aber wenn das, tatsächlich so ist, wie Du
> oben schilderst: Verblüffend.

So hab ich die Problembeschreibung verstanden.
Ich dachte auch zunächst, er toggelt den Port selber in der 
main-Schleife, darum hab ich um Code gebeten.
#1292648
Lesenswert?

Hallo Zusammen

Also, ich habe da nochmals ein bisschen rumexperimentiert... (neuer 
code!)

-Ich manipuliere nun PortB
-Es wird zur Lauft wischen zwei unterschiedliche "Belastungen" 
umgeschaltet
    -sleep() => ca. 66.4ms
    -Port-Manipulation => 63.1ms

Jetzt müsste vermutlich doch noch ein Quarz hin. Habe jedoch keinen zur 
Hand zur Zeit. :-(

Gruss
Hans-Jörg
Angehängte Dateien:
Gast #1292650
Lesenswert?

An der Doku könnte man evtl. etwas zweifeln wie die Operation nun 
wirklich geht. Nach Seite 57 wird die normale Funktion des Ports völlig 
umgangen, wenn die alternative Funktion benutzt wird. Nach Seite 93 ist 
der Port aber in einem Register zusammengefasst und nur der OCxyz pin 
wird über einen Multiplexer umgeschaltet. Hmm. Das muss ich mal 
ausprobieren. Habe nur leider keinen Tiny da, nur Megas. Das wäre ja 
eine Art Bug. Zumindest inkonsistentes Verhalten.
Gast #1292684
Lesenswert?

Hmmm. D.h. wenn Du zur Laufzeit zwischen Sleep und port Manipulation 
umschaltest, dann ändert sich die Pulsweite. Na gut. Aber da kommt 
glaube ich noch eine Startup-Zeit dazu. Das ist glaube ich nicht 
aussagekräftig.
Die Startup-Time kommt im schlimmsten Fall auch noch dazu.
Seite 13: "If an interrupt occurs when the MCU is in sleep mode, the 
interrupt execution response time is increased by four clock cycles."
#1292726
Lesenswert?

Vielleicht ist mein Gedanke ja Blödsinn, aber der Tiny44 hat doch einen 
internen Temperatursensor auf dem Die. Da hier im Raum steht, dass sich 
der interne Takt aufgrund unterschiedlicher Die-Temperaturen, 
hervorgerufen durch unterschiedliche Befehlssequenzen ändert, könnte man 
das eventuell mit diesem Temp.sensor verifizieren. Nur so ein Gedanke.
#1292816
Lesenswert?

Thomas S. schrieb:
> Vielleicht ist mein Gedanke ja Blödsinn, aber der Tiny44 hat doch einen
> internen Temperatursensor auf dem Die. Da hier im Raum steht, dass sich
> der interne Takt aufgrund unterschiedlicher Die-Temperaturen,
> hervorgerufen durch unterschiedliche Befehlssequenzen ändert, könnte man
> das eventuell mit diesem Temp.sensor verifizieren. Nur so ein Gedanke.

Das einfachste ist, an den Prozessor einen stabilen externen Takt 
anzuhängen und nachzusehen, obs dann immer noch variiert.

Da das dann die einzige Veränderung im Gesamtsystem ist, kann es dann 
nur noch an der Taktversorgung liegen.
#1292829
Lesenswert?

Karl heinz Buchegger schrieb:
> Das einfachste ist, an den Prozessor einen stabilen externen Takt
> anzuhängen und nachzusehen, obs dann immer noch variiert.

Sorry, da hatte ich mich wohl falsch ausgedrückt. Meine Idee ging 
eigentlich eher in die Richtung "überprüfen, ob die Die-Temperatur sich 
entsprechend stark ändert oder nicht" und war nicht als Lösung des 
Problems gedacht.
#1293532
Lesenswert?

Hans-jörg Hasler schrieb:
> Hallo Zusammen
>
> Habe da ein paar neue Erkenntnisse:
> -Bei einem externen Clock läuft das Ding super stabil
> -CKOUT: -Stabil im Sleep-Mode
>         -extrem starker Jitter beim Programm (Portmanipulation)
>
> Werde daraus die Konsequenz ziehen müssen.

Naja, was sein kann ist ein kurzes Einbrechen der Spannungsversorgung 
beim Pin Togglen, durch die kurzzeitig hohen Ströme beim Umschalten der 
Transistoren. Das kann den Oszillator schon ordentlich jittern lassen. 
Also externen Quarz nehmen und Vcc ordentlich abblocken.
Gast #1293610
Lesenswert?

Hallo zusammen:
zum Thema Jitter steht auch was bei elm-chan:
http://elm-chan.org/docs/avr/jitter.html

Ist leider auf Japanisch, und wieweit die autoübersetzung taugt mag ich 
nicht abschätzen. ;-)
Aber es sieht so aus als ob es deutliche Unterschiede im Jitter für 
verschiedene in AVRs eingesetzte Oszilatoren gibt.

Jitter allein ändert aber an der Taktfrequenz nichts wenn ich das 
rcihtig verstehe.


Grüße
 kaffeetas

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren