Arduino UNO Power Safe mit Watchdog

Gast #4415165
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();
}
(Firma: Q3) #4416100
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.
Gast #4416180
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.
  }
Gast #4416193
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.
  }
Gast #4416266
@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.
Gast #4416278
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...
Gast #4416293
@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?*
  }
Gast #4416461
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
}
Gast #4416554
@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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 10 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.