Forum: Mikrocontroller und Digitale Elektronik Atmega64 Sleep mit Watchdog nach Zeit wecken


von Thomas (Gast)


Lesenswert?

Hallo,

ich Programmiere gerade mit Arduino und möchte einen Atmega64L im 
Sleepmode mit dem Watchdog nach einer festgelegten Zeit zurückholen.

In Sleep geht er aber er kommt nicht mehr zurück.

Der Befehl ruft die goToSleep auf, in der SLEEP_TIME steht die Zahl 7
irgendwie funktioniert der Watchdog nicht und ich werd nicht so recht 
schlau aus dem Datenblatt. Nach 4 Std vergeblichem rumprobieren brauch 
ich jetzt hilfe, vielleicht hat das schon jemand gemacht.

Hier der Arduino Code mit der Sleep Funktion



goToSleep (0b100001, SLEEP_TIME);



void goToSleep(const byte interval, int time) {
 for (int i=0; i<time; i++) {

MCUSR = 0;
WDTCR |= (1<<WDCE) | (1<<WDE);
WDTCR =  0b01000000 | interval;        //hier muss der Fehler sein
 set_sleep_mode (SLEEP_MODE_PWR_DOWN);
 sleep_enable();
 sleep_cpu();

 }
}
ISR(WDT_vect)
 {

 WDTCR = 0x00;  //für Watchdog disablen laut Datenblatt Atmega64
 }

von Jim M. (turboj)


Lesenswert?

Power Down macht verdammt viele Taktgeber aus. Schau Dir mal an ob da 
überhaupt noch was läuft was den WDT antreiben kann.

von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

beim Power Down Mode sollte laut datenblatt der Watchdog funktionieren

Mit dem WDTCR Befehl komm ich irgendwie nicht richtig klar.
Verstehe nicht genau wie sich das zusammenhängt und wie man hier eine 
Zeit einstellen kann bis der Watchdog ausgeführt wird.

Komischerweise hat das ganze bei einem Atmega16 funktioniert...

Hier das Datenblatt dazu
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2490-8-bit-AVR-Microcontroller-ATmega64-L_datasheet.pdf

von Thomas E. (thomase)


Lesenswert?

Thomas schrieb:
> WDTCR |= (1<<WDCE) | (1<<WDE);
> WDTCR =  0b01000000 | interval;        //hier muss der Fehler sein

Das Schreiben auf das WDTCR muß in einer Timed Sequence erfolgen. Dafür 
hast du 4 Takte Zeit, in denen das erledigt sein muß. Dauert es länger, 
passiert gar nichts.


1
unsigned char temp = 0b01000000 | interval;
2
WDTCR |= (1 << WDCE) | (1 << WDE);
3
WDTCR = temp;

: Bearbeitet durch User
von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hab das mal ausprobiert aber leider gleiches verhalten.
Die 4 Takte schafft er nicht würd ich sagen.

Die Frage ist auch was bedeutet das 0b0100000 ?
Es ist das Timer Control Register WDTCR aber was macht hier das 0b ????
Ist das die Adresse und ist diese evtl falsch?

Das Bild zeigt den WDTCR beim Atmega64

von Thomas (Gast)


Lesenswert?

Thomas schrieb:
> Hab das mal ausprobiert aber leider gleiches verhalten.
> Die 4 Takte schafft er nicht würd ich sagen.
>
> Die Frage ist auch was bedeutet das 0b0100000 ?
> Es ist das Timer Control Register WDTCR aber was macht hier das 0b ????
> Ist das die Adresse und ist diese evtl falsch?
>
> Das Bild zeigt den WDTCR beim Atmega64


So hab mal geschafft das der Watchdog läuft
jedoch macht er nach ca 0,5 Sekunden einen Reset und fängt das komplette 
Programm von vorne an. hier sollte er eigentlich zurück kommen die for 
schleife durcharbeiten und sehen das i noch nicht 4 ist und dann wieder 
in den sleep gehen.
Woher weis er das er keinen Reset machen soll durch watchdog?
wie befüllt man die Intervall richtig?

ich checks nicht. :-(



interval = 0b00011111, time = 4

---------------------------------------


void goToSleep(const char interval, int time) {


 for (int i=0; i<time; i++) {


 WDTCR =  0b00011000 | interval;
 set_sleep_mode (SLEEP_MODE_PWR_DOWN);
 sleep_enable();
 sleep_cpu();
 wdt_reset();
 }
}
ISR(WDT_vect)
 {

 WDTCR = 0x00;  // Watchdog ausschalten
 }

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Thomas schrieb:
> was macht hier das 0b ????
Kennst du den Präfix 0x für Hexzahlen?  Das 0b ist dementsprechend der 
Präfix für Binärzahlen...

: Bearbeitet durch Moderator
von Thomas E. (thomase)


Lesenswert?

Thomas schrieb:
> ich checks nicht.

Schon mal einen Blick ins Datenblatt riskiert?

Der Code, den du irgendwo abgeschrieben hast, funktioniert auf dem 
Atmega64 nicht, da der die dafür notwendige Funktion, nämlich den WD als 
Timer zu nutzen, nicht hat.

von Thomas (Gast)


Lesenswert?

Ok das macht Sinn... Danke

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Laut
http://www.atmel.com/Images/Atmel-2490-8-bit-AVR-Microcontroller-ATmega64-L_datasheet.pdf
Seite 51 löst beim ATmega64(L) der Watchdog immer einen Reset aus.
Finde in dem PDF aber die möglichen ISR-Quellen nicht :/
Beim ATtiny kann man den WD nur einen Interrupt auslösen lassen, scheint 
es hier nicht zu geben.

Du kannst am Programm-Anfang da aber drauf reagieren, indem Du das WDRF 
(WatchDogResetFlag) auswertest und bei gesetztem Flag
- dieses auf Null setzt
- an die Programmstelle springen, wo Du nach dem WD weiter machen willst

Ohne dieses gesetzte Flag am Programmanfang 'ganz normal' 
Register/Ports/Variabeln setzen.


MfG

von Thomas E. (thomase)


Lesenswert?

Patrick J. schrieb:
> Ohne dieses gesetzte Flag am Programmanfang 'ganz normal'
> Register/Ports/Variabeln setzen.

Ein WD-Reset ist kein jump 0, sondern ein richtiger Reset mit allen 
Konsequenzen. Ohne sich den Status nach dem Aufruf des Sleep Mode im 
EEPROM zu sichern, wird das nichts. Da nützt allein die Kenntnis , daß 
es der WD war, der den Reset ausgelöst hat, wenig.

Nun ist allerdings ein WD-Reset die denkbar schlechteste Möglichkeit, 
den Sleep selbsttätig zu beenden.

Entweder lässt man einen beliebigen Timer im Sleep Idle laufen oder den 
Timer2 im Asynchron Mode mit Uhrenquarz im Sleep Power Safe . Oder man 
nimmt einen pinkompatiblen Atmega644 oder einen einen seiner Brüder. Der 
kann das mit WD als Timer von Haus aus.

von spess53 (Gast)


Lesenswert?

Hi

>Du kannst am Programm-Anfang da aber drauf reagieren, indem Du das WDRF
>(WatchDogResetFlag) auswertest und bei gesetztem Flag
>- dieses auf Null setzt
>- an die Programmstelle springen, wo Du nach dem WD weiter machen willst

Und nach dem WD-RESET ist auch die ganze Initialisierung weg.

MfG spess

von Thomas E. (thomase)


Lesenswert?

Thomas E. schrieb:
> Oder man
> nimmt einen pinkompatiblen Atmega644 oder einen einen seiner Brüder. Der
> kann das mit WD als Timer von Haus aus.

Ach Sch... vergiss es. Ich war beim 16/32er.

Aber  640/1280/2560 könnte was sein. Den 2560 gibt es auch als Arduino.

: Bearbeitet durch User
von Thomas (Gast)


Lesenswert?

Danke Jungs.

Dann lass ich das mit dem Watchdog...

Ich werde dann einen Timer nehmen der im Sleep Idle weiterläuft und ihn 
danach automatisch wecken lassen. Mal schauen ob ich das so einfach 
hinbekomme.

Es geht hierbei um einen Batteriebetriebenes Gerät das mit möglichst 
wenig Strom auskommen soll. Die Spannung bekommt er von einer LIPO 
Zelle, somit zwischen 3 V und 4 Volt und deswegen auch der Atmega64L.
Das Teil soll alle 5min aufwachen was abarbeiten und wieder in den Sleep 
gehen. Die Zeitvariable soll über eine Taste und Display einstellbar 
sein, somit variabel.

von Peter D. (peda)


Lesenswert?

Bei den alten ATmegas kannst Du einen 32kHz Quarz an den asynchronen 
Timer anschließen und Dich damit aus Power-Save wecken lassen.

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
Noch kein Account? Hier anmelden.