Arduino Pro Mini Schlafmodus

Hallo allerseits,

ich habe ein Arduino Pro Mini mit einen Atmega168P und möchte den Schlafmodus nutzen.

Und zwar soll das Board alle 15 min. aufwachen und die loop einmal ausführen. Außerdem soll das Board aufwachen, wenn ein Digitaler Eingang (Pin D2) von seinem Normalzustand low durch einen Schalter auf high wechselt, und die loop einmal ausführen. Nach Ausführen der loop soll der Timer wieder bei 0 starten, egal ob der Schlafmodus nach den 15 min. oder durch den Digitalen Eingang beendet wurde.

Grund für den Schlafmodus ist ein Akkubetrieb, bei dem der Akku möglichst lange halten soll.

Ich konnte im Netz leider keine Variante finden, die beides ermöglicht und hoffe, das dies überhaupt möglich ist.

Wie müsste der Code hierfür aussehen?

Vielen Dank für eure Antworten!

Wie müsste der Code hierfür aussehen?

Erwartungshaltung leicht überzogen...?

Das zeitgesteuerte Wecken, kannst du per WDT oder über einen der Timer erledigen.
Aber 15 min?
Eher in Etappen.
Wenn es "genau" 15 Minuten sein sollen, wäre ein Impuls von Extern erforderlich. Oder von Resonator auf Uhren Quarz umrüsten.

Und zum Wecken, über positive Flanke, eignet sich der PCINT

Ich konnte im Netz leider keine Variante finden, die beides ermöglicht und hoffe, das dies überhaupt möglich ist.

Ja, ist möglich.

Danke erstmal.
Ich erwarte von euch natürlich keinen fertigen, funktionstüchtigen Code, sondern wollte lediglich einen möglichen Ablauf in Erfahrung bringen.

Ich hab mir jetzt folgendes überlegt:

Der WatchDog Timer löst einen Reset nach einer gewissen Zeitspanne (max. 8 sec) aus und der Sketch beginnt von vorne. Um 15 Minuten Schlafmodus umsetzen zu könne müsste ich also das Arduino mindestens 113 mal Schlafen lassen. Hierfür benötige ich einen Counter (=113), den ich vor jedem Schlafen um 1 erniedrige und im EEPROM abspeichere. Steht der Counter bei 0, führe ich meine loop ganz normal aus und setze den Counter auf 113.

Wäre das soweit eine gute Lösung?

Allerdings ist mir nicht ganz klar, wo der PCINT eingreifen müsste und was er genau bewirkt.

Da der EEPROM nur 100 000 Schreibzyklen garantiert, läuft Dein System 9,25 Tage mit Garantie.
8 Sekunden * 100 000 = 800 000 / 3600 = 222,22 Stunden / 24 = 9,25 Tage

Ich würde einen FRAM empfehlen.

Gruß Tommy

Edit: z.B. einen FM24C64B (ich gehe von 5V-Betrieb aus) den kannst Du über einen Pin versorgen (und abschalten, wenn Dich der Standbyverbrauch stört), der braucht nur 400µA im Betrieb und 10 µA in Standby

Lesestoff und vielleicht Inspiration:
http://gammon.com.au/power
spezielle folgende Kapitel:

  • Waking from sleep with a timer
  • Waking from sleep with a signal

Der WatchDog Timer löst einen Reset nach einer gewissen Zeitspanne

  1. du brauchst kein Reset. Der WDT kann auch einen Interrupt auslösen
  2. Es gibt eine RAM noinit Section. Das EEProm brauchst also auch nicht dafür.

Allerdings ist mir nicht ganz klar, wo der PCINT eingreifen müsste und was er genau bewirkt.

Flankengetriggerter Interrupt für alle Pins.
Entspricht also exakt deiner Anforderung.

Was haltet ihr von folgenden Code:

#include <avr/sleep.h>
#include <avr/wdt.h>
 
int wakePin = 2;                                   // pin used for waking up
int count = 0;                                       // counter
int dauerSchlaf = ((15 *60) + (0)) / 8;   // (min * 60) + (sec) 
 
void wakeUpNow() {
    wdt_reset();
    wdt_disable();
    count = 0;
}
 
void setup()
{
  pinMode(wakePin, INPUT);
  //Hier wird später der Wert aus dem FRam gelesen
  Serial.begin(9600);
  attachInterrupt(0, wakeUpNow, HIGH);
}
 
void sleepNow()
{
    wdt_enable(WDTO_8S);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    attachInterrupt(0,wakeUpNow, HIGH);
    sleep_mode();
    sleep_disable();
    detachInterrupt(0); 
    wdt_disable();
}
 
void loop()
{
  count--;
  if(count <= 0) {
    Serial.println("Schlaf beendet");
    //Do something
    count = dauerSchlaf;
  }
  //Hier wird später der Wert ins den FRAM geschrieben
  Serial.println("Gehe schlafen ...");
  sleepNow();
}

combie:

  1. du brauchst kein Reset. Der WDT kann auch einen Interrupt auslösen
  2. Es gibt eine RAM noinit Section.

Wie löse ich mit WDT einen Interrupt aus?
Wie kann ich auf die RAM noinit Section zugreifen?