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
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.
>Zusätzliche Info:
Auch wenn es überhaupt nicht am Code liegen kann (es liegt NIE am Code),
zeig ihn trotzdem.
Oliver
Hallo nochmals Hier noch den Code... Gruss und Danke nochmals! Hans-Jörg
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
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
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.
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
>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
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.
Ob es wirklich an der Temperatur liegt, sollte mit Kältespry o.ä. leicht rauszufinden sein. Oliver
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?
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.
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
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.
>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.
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.
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.
@ 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?
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.
@ 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 | }
|
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.
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
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.
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.
Habe nur eine Sache aufs Mal verändert. Poste nur das Resumé. Das mit dem Geni ist eine gute Idee. Bin schon dabei...
>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?
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."
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.
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.
Hi Die Stabilität des Taktes lässt sich auch am Clockausgang bestimmen. CKOUT-Fuse setzen und messen. MfG Spess
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.
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
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.
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.