Forum: Mikrocontroller und Digitale Elektronik Attiny84 und die Sleep / Power Modes


von Christian J. (Gast)


Lesenswert?

Hallo,

ich bastle seit einiger Zeit mit dem Attiny84 (auf Arduino IDE) zunächst 
mal auf einem Steckbrett mit LEDs herum und habe einen Stromsparmode 
definiert, wo der WDT den Avr nach 1s aus dem Schlaf reisst. Die 
Zielanwendung soll locker 1 Jahr ohne Batteriewechsel auskommen.

void GotoSleep()
{
  wdt_enable(WDTO_1S);      // Watchdog auf 1S einstellen und Reset
  wdt_reset();
  MCUSR &= ~(1<<WDRF);      // Reset Flag löschen
  WDTCSR |= _BV(WDIE);      // Watchdog löst jetzt IRQ aus, keinen Reset

  set_sleep_mode(SLEEP_MODE_PWR_SAVE);  // Fast Tiefschlaf Mode 
bestimmen
  sleep_enable();           // Sleep aktivieren
  power_all_disable();      // Alles abschalten
  sleep_mode();             // Schlafen legen...chrrr....

  // Motor an und Aufwachen!
  sleep_disable();         // Sleep zuerst abschalten
  MCUSR &= ~(1<<WDRF);     // Reset Flag löschen
  wdt_disable();           // Watchdog auch aus
  power_timer0_enable();   // Nur millis(), delay(...) usw wieder ein
}

Aufwachen soll er mit einer fallenden Flanke am INT0. Klappt auch 
soweit, allerdings .... im Power Idle Mode tut er das sofort, also wenn 
ich mit dem Draht auch nur die Masse mal antippe. B<ei Power Down udn 
Power Save muss ich wirlich ca 100ms den INT0 Pin auf Masse ziehen. Auf 
Peaks reagiert er gar nicht.

Ist so ok so? Wäre nämlich nett wenn er aus Tiefschlaf auch sofort 
wieder rauskäme.

von Bastler (Gast)


Lesenswert?

DB sagt: aus PowerDown nur per INT0 im Level-Mode. Kurze Pulse wecken 
den Tiny zwar auf, aber INT0_vect wird nicht gerufen.
PinChange wäre die Alternative. Das geht immer.

von Bastler (Gast)


Lesenswert?

Zu den 100ms. Sind eher 64ms + Clock-Ungenauigkeit. Über SUT Fuses kann 
man diese aber auf wenige μs drücken

von Christian J. (Gast)


Lesenswert?

Bastler schrieb:
> aus PowerDown nur per INT0 im Level-Mode. Kurze Pulse wecken
> den Tiny zwar auf, aber INT0_vect wird nicht gerufen.

Yep, genau das war es.... diesen Satz habe ich auch erst viel später 
gefunden. Lüppt jetzt!

Frage: Muss man die WDT Zeit immer wieder neu setzen, zb kann man das 
auch in der ISR des WDT machen für den nächsten Interrrupt?

von Bastler (Gast)


Lesenswert?

Wichtig ist vor allem WDIE in der IST neu zu setzen, sonst kommt der 
nächste WDT-Interrupt als RESET daher (DB S.45 unten). Der 
WD-Prescale-Wert sollte erst nach einem echten Hardware-Reset 
zurückgesetzt werden.

von Christian J. (Gast)


Lesenswert?

Bastler schrieb:

> Wichtig ist vor allem WDIE in der IST neu zu setzen, sonst kommt der
> nächste WDT-Interrupt als RESET daher (DB S.45 unten). Der
> WD-Prescale-Wert sollte erst nach einem echten Hardware-Reset
> zurückgesetzt werden.

Wird nicht auch der Prescaler zurück gesetzt? Nach einem reset auf jeden 
Fall aber nach einem Interrupt durch den WDT?

von Thomas E. (thomase)


Lesenswert?

Christian J. schrieb:
> Wird nicht auch der Prescaler zurück gesetzt? Nach einem reset auf jeden
> Fall aber nach einem Interrupt durch den WDT?

Nein.

Deine ganze enable/disable Orgie ist auch vollkommen überflüssig.

Initialisiere den WDT einmal als Timer, nur als Timer. Dann liefert er 
in deinem Fall jede Sekunde einen Interrupt. Und du hast nichts weiter 
zu tun, als dich um diesen Interrupt zu kümmern.

Dass er auch noch Watchdog im eigentlichen Sinne könnte, davon weiss er 
dabei gar nichts. Er ist jetzt nichts anderes als ein asynchron 
angetriebener primitiver Timer.

mfg.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Deine ganze enable/disable Orgie ist auch vollkommen überflüssig.

Nochmal:

Ich brauche eigentlich nur einen SysTick wie beim stm32 und 
zwischendurch darf der avr schlafen. aber wie soll man den wdt als timer 
einstellen? das mache ich
doch oben, er löst einen int aus uns sprint in die vordefinierte isr 
rein. in der isr wird der gesamt ablauf des programm gesteuert, "aussen" 
liegt nichts mehr ausser einer endlos schleife mit sleep_mode. klommt er 
da raus gehts gleich wieder rein. siucherheitshalber wird jeden tag 1 
mal der wdt auf reset gestellt und bootet neu, da ich den bits nicht 
traue in langzeitanwendungen, dass die nicht mal kippen.

Die routine oben ist ganz weg, nur in der isr steht noch am ende:

wdt_enable(WDTO_1S);
MCUSR &= ~(1<<WDRF);      // Reset Flag löschen
WDTCSR |= _BV(WDIE);      // Watchdog löst jetzt IRQ aus, keinen Reset

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.