Hallo Leute,
Ich hab ein kleines Problem mit dem Watchdog.
Ich würde gerne meinen Atmel 5 Stunden lang schlafen lassen.
Ich hab mir die WDT Tuts schon durchgelesen und es funktioniert auch
fast alles bis auf, dass er immer zu Früh nach 5 Minuten oder so oder
noch früher aufwacht.
Der WDT Interrupt läuft wie folgt:
ISR(WDT_vect)
{
Sleepsekunden++;
wdt_reset();
if (Sleepsekunden >= 4500){
WDT_off();
sleep_disable();
for (uint8_t i=0;i<15;i++)
{
millisekunden = 0;
Sleepsekunden=0;
}
WDT_RESET();
uart_init();
sei();
}
else {
Sleep();
}
}
Die Unter-Programme Dazu:
void WDT_Init(void)
{
//disable interrupts
cli();
//reset watchdog
wdt_reset();
//set up WDT interrupt
WDTCSR = (1<<WDCE)|(1<<WDE);
//Start watchdog timer with 4s prescaller
WDTCSR = (1<<WDIE)|(1<<WDE)|(1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(0<<WDP0);
//Enable global interrupts
sei();
}
void WDT_RESET(void)
{
//disable interrupts
cli();
//reset watchdog
wdt_reset();
//set up WDT interrupt
WDTCSR = (1<<WDCE)|(1<<WDE);
//Start watchdog timer with 4s prescaller
WDTCSR = (0<<WDIE)|(1<<WDE)|(0<<WDP3) |(1<<WDP2)|(1<<WDP1);
//Enable global interrupts
sei();
}
Ich komm gerade nicht ganz mit.
Der Watchdog beim AVR kann soweit ich weis nur 2048 und 4096mS.
Watchdog ist dafür da, dass dein Programm so und so lange brauchen darf
um den WDC_Reset auszuführen. Dauert es zu lange, weil z.B.: der uC in
einer Loop hängt, so kommt der Watchdog und resetet ihn.
Danke,
Aber ich würde Ihn gern missbrauchen und den UC nach 5 Stunden Reset-en.
Ich erhöhe ja immer ein Incrementenzäher also bis er das erreicht soll
er immer wieder Schlafen gehen.
Programmtechnisch sollte es passen aber er tut es nicht wirklich :-)
T.A. schrieb:> Ich würde gerne meinen Atmel 5 Stunden lang schlafen lassen.
Der Watchdog ist dafür da, wenn etwas nicht so funktioniert, wie
vorgesehen.
Um den Controller absichtlich aus dem Schlaf aufzuwecken ist er das
falsche Tool. Dafür benutzt man Timer.
Gruß
Jobst
Erst mal fehlt hier eine ganze Menge:
- welcher Prozessor
- keine Definition der verwendeten Variablen
- kein Hauptprogramm
- unklar, was die 5h sollen, die einzige Abfrage die ich sehe, beziehen
sich auf 4500s und das wären 1.25h
- die ganze WD-Bearbeitung sieht sehr komplex und umständlich aus.
Außerdem:
bei den mir bekannten Tinys ist die maximale Watchdogperiode 8s, danach
wacht er auf jeden Fall erst mal wieder auf.
Hänge mal ein funktionsfähiges Programm an, das deine Wünsche nicht
erfüllt und nenne diese Wünsche auch genau.
Code als Anhang oder eingebunden in die
Bitte keine Files mit TABs drin posten. Sieht scheisse aus.
Deine ISR sieht aber auch sonst höchst seltsam aus. sei() in dort meist
falsch. Was soll die Schleife bewirken? Sleep() in der ISR sieht
verdächtig nach Stacküberlauf aus, weil ISR von ISR unterbrochen wird,
dir von einer ISR unterbochen wird, usw.
Jobst M. schrieb:> Um den Controller absichtlich aus dem Schlaf aufzuwecken ist er das> falsche Tool. Dafür benutzt man Timer.
Der Watchdog-Interrupt ist dafür durchaus geeignet, wenn es auf
Genauigkeit nicht ankommt. Ein Timer braucht mehr Strom, oder einen
unabhängigen Takt.
ATMEGA324PA
Ich glaub auch, dass ich hier etwas falsch mache :-) sonst würde es ja
gehen.
Du hast recht ein sei(); in ISR ist nicht gut :-)
Die Idee dahinter ist es den INterrupt des WDT so einzustellen, dass er
alle 4 Sekunden ausgelöst wird.
In diesem Interrupthandler dann eine Variable Hochzählen zu lassen und
dann wenn die Variable einen bestimmten Wert hat den UC zu reset-en.
T.A. schrieb:> Die Idee dahinter ist es den INterrupt des WDT so einzustellen, dass er> alle 4 Sekunden ausgelöst wird.
Der Hauptfehler ist, dann in der ISR auf den nächsten Interrupt zu
warten. Damit stapeln sich die Interrupts auf dem Stack und irgendwann
läuft der über.
Das muss im Hauptprogramm passieren, nicht in der ISR. Die ISR zählt
bloss die Zeit hoch. Das Hauptprogramm pennt so lange immer wieder ein,
bis die Stunden rum sind.
T.A. schrieb:> Die Idee dahinter ist es den INterrupt des WDT so einzustellen, dass er> alle 4 Sekunden ausgelöst wird..
Ok
> In diesem Interrupthandler dann eine Variable Hochzählen zu lassen
Ok
> und dann wenn die Variable einen bestimmten Wert hat den UC zu reset-en.
Warum willst du dann ein Reset machen? Ein Sprung nach 0x0000 würde es
auch tun. Ansonsten musst den den WDT am Ende wieder so konfigurieren
das beim nächsten Durchlauf der Reset ausgelöst wird.
In der ISR brauchst du eigentlich nur die Variable hochzählen.
In der Hauptschleife prüfst du ob die 4500 Durchläufe um sind, wenn
nicht dann wieder Sleep.
Sascha
T.A. schrieb:> Wird die Hauptschleife überhaupt durchgelaufen wenn ich den MCU auf> Power_Down Schlafen lasse?
Der Watchdog-Interrupt weckt den Prozessor auf und der läuft dann so
lange weiter, bis du ihn wieder schlafen legst. Er beendet also ganz
normal die ISR, landet dann im Hauptprogramm und macht dort direkt nach
dem Sleep weiter.
> Ich würde gerne meinen Atmel 5 Stunden lang schlafen lassen.
Geht es um den Lerneffekt oder um eine konkrekte Anwendung?
Bei Letzterem wäre vielleicht Timer2 mit 32 KiHz-Quarz die
stromsparendere Lösung, vorausgesetzt, der Systemtakt muss nicht
quarzgenau sein.
Würde auch noch gehen, ist aber trickreich & aufwändig, und lohnte sich
wohl nur, wenn es auf das letzte uA ankommt: OSCCAL per 32 KiHz-Quarz
justieren.
A. K. schrieb:> Jobst M. schrieb:>> Um den Controller absichtlich aus dem Schlaf aufzuwecken ist er das>> falsche Tool. Dafür benutzt man Timer.>> Der Watchdog-Interrupt ist dafür durchaus geeignet, wenn es auf> Genauigkeit nicht ankommt. Ein Timer braucht mehr Strom, oder einen> unabhängigen Takt.
Hätte Jobst jetzt zu 100% zugestimmt. Immer wieder interessant auch mal
andere Ansätze zu lesen.
Danke für deinen Einwurf dieser Art!
Zum Stromverbrauch:
Timer 2 oder WDT Timer unterscheiden sich im uA Bereich.
Ich glaube es kommt darauf an ob man den WDT noch für Programmsicherheit
benötigt oder nicht.
T.A. schrieb:> Timer 2 oder WDT Timer unterscheiden sich im uA Bereich.> Ich glaube es kommt darauf an ob man den WDT noch für Programmsicherheit> benötigt oder nicht.
Der WDT ist nicht verbrannt, wenn man den "Interrupt and System Reset
Mode" verwendet. Denn der WDT-Interrupt schaltet sich automatisch bei
Ablauf ab. Wenn man den also nicht wieder einschaltet, dann gibts beim
zweiten Ablauf einen Reset.
Man muss also den WDT-Interrupt jedesmal neu einschalten. Wichtig ist
hier, dass man das nicht in der WDT-ISR macht, sondern in der Mainloop.
Wenn diese Mainloop nicht läuft, dann gibts trotz erfolgtem
WDT-Interrupt nach zweimaligem Ablauf einen Reset.
A. K. schrieb:> Wichtig ist> hier, dass man das nicht in der WDT-ISR macht, sondern in der Mainloop.
Steht ja in so ziemlich jedem Buch, wenn man anfängt µC zu
programmieren, dass man in der ISR nur das absolut Notwendige machen
sollte und dann wieder in die Hauptroutine springen soll.
T.A. schrieb:> Zum Stromverbrauch:
Der grössere Unterschied dürfte im Hauptoszillator liegen. Im Power Down
ist der abgeschaltet. Wenn das ein Quarzoszillator ist, dann dauert es
verdammt lang, bis der sauber läuft. In dieser Zeit frisst der µC
deutlich Strom. Und das macht der alle 4 Sekunden.
Wenn man als Hauptoszillator den internen R/C-Oszillator verwendet kann,
dann entfällt dieser Startup und die Gesamtlaufzeit des alle 4 Sekunden
auftretenden WDT-Interrupts ist viel kürzer.
Ein Kompromiss ist ein Keramikoszillator. Für UART reicht er und der
Startup ist viel schneller.
Das Optimum bei genauem Haupttakt ist der interne R/C-Oszillator als
Haupttaktquelle zusammen mit einem asynchronen quarzgenauen 32kHz Timer.
Um den Haupttakt hinreichend genau zu kriegen stellt man das
Kalibrier-Register des R/C-Oszillators anhand gemessener Takte für ein
paar Perioden des 32kHz Timers immer wieder neu ein. Das dürfte den
minimal möglichen Verbrauch ergeben. Den WDT-Interrupt braucht man dann
nicht und der 32kHz Osz ist sparsamer als der WDT.