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.