Hallo Zusammen,
ich möchte meinen ATMega328p in den Schlafmodus versetzen. Durch den
Timer2 soll dieser wieder aufwachen.
dazu verwende ich folgenden Code:
meiner Meinung nach müsste der MCU dann für ca. 16 s im Schlafmodus
bleiben:
256*1024*1000/16000000 (Der MCU läuft mit 16 MHz Takt)
Es zeigt sich jedoch, dass die LED genauso lang an, wie aus ist. Also
etwa 1 Sekunde.
Wo ist mein Fehler?
Zeig mal den vollständigen Code.
Power-Save geht nur mit T2 im asynchronen Mode, d.h. am 32kHz Quarz.
Und dann muß vor dem Sleep gewartet werden, bis der Zugriff beendet
wurde (Löschen des Interruptflags ist ein Zugriff), d.h. die nächste
32kHz Flanke erfolgte.
Ansonsten laufen die Timer nur bei Idle weiter.
> Power-Save geht nur mit T2 im asynchronen Mode, d.h. am 32kHz Quarz.
Das lese ich im Datenblatt anders.
Das Programm, zumindest was von ihm zu sehen ist, sollte funktionieren.
Unklar ist mir der Sinn von
> TCNT2 &= 0; //Timer resetten
Und
> TIMSK2 |= (1<<TOIE0)
klappt nur dank etwas Glück.
S. Landolt schrieb:>> Power-Save geht nur mit T2 im asynchronen Mode, d.h. am 32kHz Quarz.> Das lese ich im Datenblatt anders.
2. If Timer/Counter2 is running in asynchronous mode.
Die Fußnote DB bezieht sich auf den Timer Oszillator. Der einzige Takt,
der im Power Save aktiv ist und somit, neben dem Watchdog Timer, die
einzige Möglichkeit des Controllers, sich selbst aufzuwecken.
Nachzulesen im DB unter Sleep Modes.
S. Landolt schrieb:> Unklar ist mir der Sinn von
Mir auch.
S. Landolt schrieb:> klappt nur dank etwas Glück.
Warum braucht man dazu Glück?
Vielen Dank für eure Antworten!
S. Landolt schrieb:> Unklar ist mir der Sinn von>> TCNT2 &= 0; //Timer resetten>
hier setze ich den Timer zurück, damit er bei 0 zu zählen anfängt. Da
war ich mich auch nicht sicher, ob das nötig ist. Aber der Timer läuft
ja schon vorher oder? Das heißt, es könnte sein, dass er bei einem
höheren Wert anfängt.
>> Und>> TIMSK2 |= (1<<TOIE0)> klappt nur dank etwas Glück.
Könntest du das bitte etwas genauer erklären! Warum klappt das nicht
immer?
Hier noch der volle Code:
Peter D. schrieb:> Z.B. beim ATmega8 sind TOIE0 und TOIE2 nicht die gleiche Bitnummer.
Ja, gesehen. Klappt nur zufällig.
Ich dachte das bezog sich, wie in diesen Fällen üblich, auf die
Zuweisung mit "|=".
Peter D. schrieb:> Z.B. beim ATmega8 sind TOIE0 und TOIE2 nicht die gleiche Bitnummer
Da hast du Vollkommen Recht. Danke!
Aber zurück zu meiner eigentlichen Frage. Warum ist der Sleep-Mode so
kurz?
Multi _. schrieb:> Aber zurück zu meiner eigentlichen Frage. Warum ist der Sleep-Mode so> kurz?
Weil das, was du da versuchst, nicht funktioniert. Nicht funktionieren
kann:
Peter D. schrieb:> Power-Save geht nur mit T2 im asynchronen Mode, d.h. am 32kHz Quarz.
Warum er trotzdem noch irgendwas macht? Keine Ahnung. Arduino?
S. Landolt schrieb:> Das lese ich im Datenblatt anders.
Stimmt, beim ATmega8 ging Power-save nur im asynchron Mode.
Der synchrone Mode dürfte vom Stromverbrauch her ähnlich dem Idle sein.
> genauso lang an, wie aus ist. Also etwa 1 Sekunde.
Bei einer Schleife mit 1000 Durchläufen.
Und irgendwo stand mal, "In Arduino, Timer0 is already set up to
generate a millisecond interrupt to update the millisecond counter for
millis()" oder so ähnlich.
So würde also das sleep-cpu nach jeweils 1 ms unterbrochen werden
zusätzlich zu den berechneten 16.384 ms = 256*1024/16000000 ms von
Timer2.
S. Landolt schrieb:> zusätzlich zu den berechneten 16.384 ms = 256*1024/16000000 ms von> Timer2.
Da er T2 nach jedem Sleep rücksetzt, würde der nie ablaufen. Es sind
also ausschließlich die T0 Interrupts.
Peter D. schrieb:> S. Landolt schrieb:>> zusätzlich zu den berechneten 16.384 ms = 256*1024/16000000 ms von>> Timer2.>> Da er T2 nach jedem Sleep rücksetzt, würde der nie ablaufen. Es sind> also ausschließlich die T0 Interrupts.
In "PowerSave" läuft der Timer0 aber gar nicht!
Atmel dazu: "2.If Timer/Counter2 is running in asynchronous mode"
Vermutlich schläft der auch nicht "PowerSave", weil die Arduino-RT den
Wert von der Initialisierung nicht stehen läst. Die möchte nämlich
Timer0 sehen.
Dann paßt auch das Verhalten:
LED an, 1000x1ms Schlafen,
LED aus, 1s delay
Ich kenne sleep eher als:
Set sleep mode
Enable sleep
Sleep
Disable sleep
Carl D. schrieb:> In "PowerSave" läuft der Timer0 aber gar nicht!
Wie ja schon festgestellt wurde, kann im Gegensatz zum ATmega8 beim
ATmega328 der T2 im Power-Save auch synchron laufen.
Das impliziert, daß der CPU-Taktgeber und CPU-Prescaler aktiv bleiben
müssen.
Grob gesagt mutiert das Power-Save bei synchronem T2 zum Idle.
Das Datenblatt schweigt sich allerdings zu Details aus. Und probiert hat
das warscheinlich auch noch niemand.
Vergessen zu schreiben:
Wie Carl Drexler betonte, läuft Timer0 in power-save tatsächlich nicht.
Bleibt also die Frage, was Arduino aus dem Ganzen macht.
S. Landolt schrieb:> Wie erklärt sich dann aber das eingangs beschriebene Verhalten?
Wie sich das erklärt?
KA!
Interessiert mich auch nicht wirklich.
Natürlich löst Timer0, in der Arduino Welt, dauernd Interrupts aus.
Den Timer sollte man in den leichten Schlafmodi schon stilllegen.
Ansonsten, kann ich nur sagen, dass meine Arduinos nicht einfach so
aufwachen.
Von der Arduino IDE werden typischer weise folgende ISR etabliert:
1. Timer0 (wenn setup() und loop() vorhanden)
2. UART (wenn setup() und loop() vorhanden)
3. I2C (wenn Wire genutzt wird)
Solange noch SendeDaten in der UART FIFO stecken ....(kann man sich ja
denken)
Der Code im Eingangspost ist unvollständig. Und damit untestbar.
Irgendwie macht sowas auf mich immer den Eindruck, als wolle man gar
nicht, das man das Problem findet und löst.
Vermutlich wurde mal wieder vergessen das Wichtigste zu zeigen...
Wenn ich sowas lese, dann blättere ich einfach weiter:
> TIMSK2 |= (1<<TOIE0);
OK, mag sein, dass das funktioniert, aber falsch ist es trotzdem.
Der Code von Multi __ macht sei(); . Das ist flüssiger, als Wasser,
überflüssig. Den Rest habe ich mir dann gar nicht mehr angesehen.
Peter Dannegger vergisst den Clear des SE Bit nach dem sleep.
Habe ich noch nicht getestet, ob das dann funktioniert.
Meine Erinnerung sagt aber, dass man das unbedingt tun sollte.
Das Gcc Manual sagt, dass es so auszusehen hat: