Forum: Mikrocontroller und Digitale Elektronik ATTiny44: Timer-Frequenz ändert in Abhänigkeit des Main-Programms


von Hans-jörg H. (hjhasler)


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

von Karl H. (kbuchegg)


Lesenswert?

Hans-jörg Hasler schrieb:

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

Der Fehler wird, so wie eigentlich immer, in Codezeile 42 liegen.

von Oliver (Gast)


Lesenswert?

>Zusätzliche Info:

Auch wenn es überhaupt nicht am Code liegen kann (es liegt NIE am Code), 
zeig ihn trotzdem.

Oliver

von Hans-jörg H. (hjhasler)


Angehängte Dateien:

Lesenswert?

Hallo nochmals

Hier noch den Code...

Gruss und Danke nochmals!
Hans-Jörg

von Oliver (Gast)


Lesenswert?

Nun ja, an den paar Zeilen scheint das wirklich nicht zu liegen. Die 
Reihenfolge der Timer-Initialisierung ist zwar ungünstig, vermutlich 
wird da direkt nach sei() ein Interrupt ausgelöst, aber das passiert nur 
einmal zu Anfang.

Wie misst du denn die Periodendauer?

Oliver

von Hans-jörg H. (hjhasler)


Lesenswert?

Hi Oliver

Die Periodendauer wird mit einem KO gemessen. (LeCroy 6030A)

Hast du sonst irgendwelche Ideen an was es liegen könnte?

Gruss
Hans-Jörg

von Raimund R. (corvuscorax)


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.

von Hans-jörg H. (hjhasler)


Lesenswert?

Hi Raimund

Danke für deine Antwort!

Die Spannung und die Temperatur bleiben konstant. (Liegt auf meinem 
Bürotisch)
Ich denke nicht, dass die Temperatur gross ändert, wenn ich den Code 
verändere. Oder doch?

Gruss
Hans-Jörg

von Oliver (Gast)


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

von Raimund R. (corvuscorax)


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.

von Oliver (Gast)


Lesenswert?

Ob es wirklich an der Temperatur liegt, sollte mit Kältespry o.ä. leicht 
rauszufinden sein.

Oliver

von Hans-jörg H. (hjhasler)


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?

von Gast (Gast)


Lesenswert?

Wohl eher nicht, die Temperaturabhängigkeit ist eifnach viel zu groß. 
Denn internen Ringoszilator sollte man auch nie verwenden wenn es um 
Timings jeglicher Art geht.

von switcher (Gast)


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

von Karl H. (kbuchegg)


Lesenswert?

switcher schrieb:
> Vielleicht liegt es doch am Programm?!

In seinem Fall nicht.
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.

von Nez (Gast)


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.

von Nez (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


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.

von Nez (Gast)


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?

von Karl H. (kbuchegg)


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.

von Nez (Gast)


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
}

von Karl H. (kbuchegg)


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.

von Hans-jörg H. (hjhasler)


Angehängte Dateien:

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

von Nez (Gast)


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.

von Nez (Gast)


Lesenswert?

Huch? Sleep-Mode? Am besten nur eine Sache verändern, sonst weiss man 
nachher nicht, was nun eigentlich der Knackpunkt ist.
Was ist der Unterschied zwischen Port A manipulieren und Port B 
manipulieren? Ohne Sleep-Modus.

Hast Du einen Generator da? Dann könntest Du den Takt extern einspeisen.

von Hans-jörg H. (hjhasler)


Lesenswert?

Habe nur eine Sache aufs Mal verändert. Poste nur das Resumé.

Das mit dem Geni ist eine gute Idee. Bin schon dabei...

von Nez (Gast)


Lesenswert?

>Poste nur das Resumé.
Ja schon. Aber ich kann nicht erkennen, was nun der Unterschied zwischen 
Port A manipulieren und Port B manipulieren ist. Oder liegt das an mir?

von Nez (Gast)


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

von Thomas ☻. (0x0000)


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.

von Karl H. (kbuchegg)


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.

von spess53 (Gast)


Lesenswert?

Hi

Die Stabilität des Taktes lässt sich auch am Clockausgang bestimmen. 
CKOUT-Fuse setzen und messen.

MfG Spess

von Thomas ☻. (0x0000)


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.

von Hans-jörg H. (hjhasler)


Lesenswert?

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.

Vielen Dank euch allen für eure Hilfe!

Gruss
Hans-Jörg

von Christian R. (supachris)


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.

von Peter D. (peda)


Lesenswert?

Hans-jörg Hasler schrieb:
>         -extrem starker Jitter beim Programm (Portmanipulation)

Hast Du die VCC direkt am AVR auch ordentlich abgeblockt?

Hängen an den Output-Pins irgendwelche Lasten oder Kapazitäten (lange 
Leitung)?


Peter

von kaffeetas (Gast)


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

von Hans-jörg H. (hjhasler)


Lesenswert?

Hallo Zusammen

Habe die Speisung nun besser abgeblockt.  => :-) Jetzt habe ich "nur" 
noch ca. 0.4ms differenz. Ich denke auf dem fertigen Print (Layout) wird 
es sicher nochmals besser werden.

Vielen vielen Dank an euch alle!

Gruss
Hans-Jörg

von Christian R. (supachris)


Lesenswert?

Das schöne an unserem Job ist, dass alles irgendwo physikalisch 
erklärbar ist. Manchmal muss man nur länger suchen :)

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.