Arduino UNO Power Safe mit Watchdog

Gast #4415165
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

@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
Lesenswert?

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
Lesenswert?

@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
Lesenswert?

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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren