Hallo zusammen, wie oben schon geschrieben habe ich Probleme mit dem Watchdog bei meinem Arduino UNO. Ich google und probiere jetzt schon eine ganze Weile, finde den bug aber nicht. Vielleicht kann einer helfen? Ich möchte meinen Arduino UNO für 20 sek. in den PWR_DOWN Mode schicken. Bei meinem Sketch scheinen es aber nur 2 sek zu sein. Und startet immer mit dem Setup neu :-(. Gruß poertner void setup() { Serial.begin(57600); // Set console baud rate Serial.println ("Setup... "); wdt_enable(WDTO_2S); // WDT 2s set_sleep_mode(SLEEP_MODE_PWR_DOWN); // den tiefsten Schlaf auswählen PWR_DOWN Serial.println ("Setup wird beendet."); } void loop() { Serial.println ("Hauptschleife wird durchlaufen "); for (int i = 0; i < 10; i++) { Serial.println ("enter sleep-Funktion "); Serial.println (i); delay(1000); //delay, für serial monitor sleep_enable(); // sleep mode einschalten sleep_mode(); // in den sleep mode gehen sleep_disable(); // hier nach dem sleep weiter machen } Serial.println ("nach der Schalfdauer???"); wdt_disable(); }
Hej, zum ersten Problem: was verlangt denn der Code wdt_enable(WDTO_2S); // WDT 2s vom Arduino? Gruß
Ich glaube (weiss aber nicht genau), dass mit dem Watchdog so lange Zeiten wie 20s wg. inermem Zählerüberlauf garnicht machbar sind. Bereits 2s sind für einen Mikrocontroller quasi Äonen ... Lösung (so ungefähr): Immer mal kurz aufwachen und zusätzlichen Zähler hochsetzen. Wenn Soll-Zählerstand noch nicht erreicht, wieder schlafen legen.
poertner schrieb: > Und startet immer > mit dem Setup neu :-(. Ich sehe keine ISR für den WDT! Und dann geht es zwangsläufig nach 2S über Los
WDT auf 4 Sec einstellen, und 5x sleep in einem Loop durchlaufen. Beispiel: void sleep(unsigned int times) { // wdt init wdt_reset(); MCUSR &= ~(1<<WDRF); WDTCSR &= ~(1<<WDIE); // Disable watchdog timer. WDTCSR |= (1<<WDIF); // disable interrupt flag WDTCSR |= (1<<WDCE) | (1<<WDE) | 8; wdt_reset(); do { digitalWrite(13, LOW); WDTCSR |= (1<<WDIE); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // den tiefsten Schlaf auswählen sleep_enable(); // sleep mode einschalten sleep_mode(); // in den sleep mode gehen sleep_disable(); // hier nach dem sleep weiter machen digitalWrite(13, HIGH); } while(--times); } ISR(WDT_vect) // Watchdog timer ISR { WDTCSR &= ~(1<<WDIE); // Disable watchdog timer. }
Hier die bessere Version, times ist jetzt in Sekunden. void sleep(unsigned int times) { unsigned char t=6; if(!(times&1)) { times>>=1; t++; } if(!(times&1)) { times>>=1; t++; } if(!(times&1)) { times>>=1; t++; } // wdt init wdt_reset(); MCUSR &= ~(1<<WDRF); WDTCSR &= ~(1<<WDIE); // Disable watchdog timer. WDTCSR |= (1<<WDIF); // disable interrupt flag WDTCSR |= (1<<WDCE) | (1<<WDE) | t; wdt_reset(); do { digitalWrite(13, LOW); WDTCSR |= (1<<WDIE); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // den tiefsten Schlaf auswählen sleep_enable(); // sleep mode einschalten sleep_mode(); // in den sleep mode gehen sleep_disable(); // hier nach dem sleep weiter machen digitalWrite(13, HIGH); } while(--times); } ISR(WDT_vect) // Watchdog timer ISR { WDTCSR &= ~(1<<WDIE); // Disable watchdog timer. }
@arduino-fan wdt_enable(WDTO_2S); // WDT 2s aktiviert meinem Verständis nach den Watchdog mit 2 sekunden-Zeit. @Frank Esselbach Der Controller auf dem Arduino UNO kann bis 8s. Darüber hinaus schwebt mir eine Lösung wie von dir vorgeschlagen vor. Habe ich mit der for - Schleife versucht zu realisieren.
poertner schrieb: > Habe ich mit der for - Schleife versucht zu realisieren. Kann man tun.... Du hast vergessen die WDT Interrupts zu aktivieren und keine ISR im Programm. Daran solltest du vermutlich noch etwas arbeiten. Zusätzlich könnte man noch die millis() Zählvariable um die entsprechende Sekunden Anzahl hoch setzen. Wird nicht sonderlich genau, aber vielleicht reichts ja...
@chris Danke für den Code-Vorschlag, der leider auch immer in der Setup-Funktion startet. Für mein besseres Verständnis habe ich den Code kommentiert. Und meine Fragen in fett eingefügt. Hier der komplette Code: // libraries #include <avr/sleep.h> #include <avr/power.h> #include <avr/wdt.h> void setup() { Serial.begin(57600); // Set console baud rate Serial.println ("Setup... "); delay(1000); } void loop() { Serial.println ("Hauptschleife wird durchlaufen "); delay(500); sleep(20); /Aufrufen der sleep-Funktion - Wert in Sekunden eintragen Serial.println ("20 sec gewartet???"); } void sleep(unsigned int times) { unsigned char t=6; // Umbau von Sekunden in WDP2 WDP1 WDP0 (timer prescaler bits) if(!(times&1)) { times>>=1; t++; } if(!(times&1)) { times>>=1; t++; } if(!(times&1)) { times>>=1; t++; } // wdt init wdt_reset(); MCUSR &= ~(1<<WDRF); //reset flag leeren WDTCSR &= ~(1<<WDIE); // Disable watchdog timer. WDTCSR |= (1<<WDIF); // disable interrupt flag WDTCSR |= (1<<WDCE) | (1<<WDE) | t; //WDCE um prescaler setzen zu können 4 takte! wdt_reset(); do { digitalWrite(13, LOW); WDTCSR |= (1<<WDIE); // Enable the WD interrupt (note no reset) set_sleep_mode(SLEEP_MODE_PWR_DOWN); // den tiefsten Schlaf auswählen sleep_enable(); // sleep mode einschalten sleep_mode(); // in den sleep mode gehen sleep_disable(); // hier nach dem sleep weiter machen digitalWrite(13, HIGH); } while(--times); // *???* } //Sleep Funktion Ende ISR(WDT_vect) // Watchdog timer ISR { WDTCSR &= ~(1<<WDIE); // Disable watchdog timer. // *Warum steht diese Zeile nicht in der sleep Funktion?* }
Aus meiner Wühlkiste, leicht für dich modifiziert:
1 | #include <avr/wdt.h> |
2 | #include <avr/sleep.h> |
3 | |
4 | extern volatile unsigned long timer0_millis; |
5 | const byte LED = 13; |
6 | |
7 | |
8 | void sleep(uint16_t seconds) |
9 | {
|
10 | wdt_enable(WDTO_1S); |
11 | WDTCSR |= _BV(WDIE); |
12 | while(seconds--) |
13 | {
|
14 | set_sleep_mode(SLEEP_MODE_PWR_DOWN);// SLEEP_MODE_PWR_SAVE |
15 | sleep_enable(); |
16 | sleep_mode(); |
17 | // sleeping
|
18 | sleep_disable(); |
19 | WDTCSR |= _BV(WDIE); |
20 | }
|
21 | wdt_disable(); |
22 | }
|
23 | |
24 | |
25 | void setup() |
26 | {
|
27 | pinMode(LED,OUTPUT); |
28 | }
|
29 | |
30 | void loop() |
31 | {
|
32 | sleep(3); |
33 | digitalWrite(LED,!digitalRead(LED)); |
34 | }
|
35 | |
36 | |
37 | |
38 | ISR(WDT_vect) // Watchdog timer ISR |
39 | {
|
40 | timer0_millis += 1000; // atomic |
41 | }
|
@Ulrich F. Danke Danke. Mit dem Code läuft es, ohne das der Arduino regelmäßig in den Reset geht. :-) Ich werde morgen mal probieren den Code in mein Programm zu implementieren.
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.