Watchdog und sleep mode

#2682467
Lesenswert?

Hallo,

ich habe ein kleines Projekt auf einem AtTiny45. Ich möchte ein paar 
Daten auslesen, den Tiny in den power down schicken und nach vier 
Sekunden über den watchdog wieder aufwecken damit das Spielchen von 
vorne losgehen kann. Ich bin mir allerdings nicht sicher, ob ich alles 
richtig gemacht habe.

Ich wäre dankbar, wenn sich jemand meinen Code anschauen könnten und 
evtl. Vorschläge zur Verbesserung macht. Vielen Dank im voraus.
1
#include <avr/power.h>
2
#include <avr/wdt.h>
3
#include <avr/sleep.h>
4
#include <avr/interrupt.h>
5

6
#define MASK_SENSOR  (1<<PB4)
7
#define MASK_LED     (1<<PB3)
8
#define TOTAL_INPUTS  3
9

10
void wdt_init() {
11
    cli();
12
    wdt_reset();
13
    WDTCR = (1<<WDE) | (1<<WDCE);   // Enable watchdog
14
    WDTCR = (1<<WDIE) | WDTO_4S;    // Watchdog interrupt instead of reset with 4s timeout
15
    sei();
16
}
17

18
void sleep_now() {
19
    power_all_disable();
20
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
21
    sleep_enable();
22
    sleep_mode();
23
    sleep_disable();
24
    wdt_init();
25
}
26

27
int main(void) {
28
    int i;
29

30
    // SETUP
31
    DDRB |= MASK_BUZZER | MASK_LED;                     // Set buzzer and led pin to output
32
    for(i=0; i<TOTAL_INPUTS; ++i) calibrate_sensors(i); // Set sensor pins and calibrate them (all digital inputs with enabled pull-ups)
33

34
    wdt_init();
35

36
    // MAIN LOOP
37
    while( 1 ) {
38
        get_sensor_data(); // full of wdt_resets()
39
        sleep_now();
40
    }
41

42
    return 0;
43
}
Gast #2683627
Lesenswert?

Zum Aufwachen aus dem Schlaf kann man je nach Modus jeden Interrupt 
benutzen, z.B. auch einen normalen Timer-Overflow-Int. - Scheint mir der 
saubere Weg zu sein, anstatt den Watchdog für sowas zu missbrauchen.

Grüße
 Hanno
#2683698
Lesenswert?

Hanno schrieb:
> Zum Aufwachen aus dem Schlaf kann man je nach Modus jeden Interrupt
> benutzen, z.B. auch einen normalen Timer-Overflow-Int.
Nein. Kann man nicht.

Hanno schrieb:
> anstatt den Watchdog für sowas zu missbrauchen.
Blödsinn.

Christoph -. schrieb:
> Mit diesem Code scheint der Chip einen reset zu machen,
Wo ist deine "ISR(WDT_vect)"? Die brauchst du natürlich, sonst springt 
er beim Interrupt auf den Reset-Vektor.

mfg.
Gast #2683877
Lesenswert?

Nee, ohne ISR macht der normalerweise einfach gar keinen ISR, weckt aber 
trotzdem. Mag je nach Compiler anders sein.
Und der WDT ist toll für sowas, da geb' ich Thomas recht.
Ist bei den Fuses der Watchdog aktiviert? Wenn ja: Abschalten.
#2683896
Lesenswert?

Watchdog schrieb:
> Nee, ohne ISR macht der normalerweise einfach gar keinen ISR, weckt aber
> trotzdem. Mag je nach Compiler anders sein.
So einfach ist das nicht.
Wird ein Interrupt ausgelöst, egal welcher, wird der Program Counter des 
Controllers auf den Interrupt-Vektor gesetzt. Dann wird der Befehl 
ausgeführt, der da steht. Da kann der Compiler gar nichts gegen machen. 
Das ist reine Hardware.
Üblicherweise steht dort ein Jump auf die ISR.
Ist keine ISR angelegt, wird ein Bad Interrupt ausgeführt, der wiederum 
einen Jump auf 0 enthält. Sozusagen ein Warmstart. AVR-GCC.
Vielleicht machen das andere Compiler anders. Keine Ahnung. 
Assemblerporgrammierer würden in diesem Falle einfach ein reti auf den 
Interrupvektor schreiben.

mfg.
Gast #2683969
Lesenswert?

Oops... Hast recht, gerade nochmal ausprobiert. Ich dachte ich hätte das 
schonmal gemacht, aber da hat mich meine Erinnerung getrogen. Sorry!


Christoph: Ergänze irgendwo

ISR(WDT_vect) { }  //WatchDogTimer interrupt
#2685295
Lesenswert?

Vielen Dank euch allen! Werde es morgen mal probieren. Habe mir schon 
gedacht, dass ich etwas offensichtliches vergessen hab.

@Hanno: Aus den anderen sleep modi reicht je nach Chip meistens jeder 
interrupt. Bei power_dwn ist allerdings der watchdog gefragt, besonders, 
weil der seinen eigenen Timer mitbringt.

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