Den Arduino in den Schlaf Modus setzen und wieder aufwecken.

Mein Arduino Uno soll für eine stromsparende Anwendung in den SLEEP_MODE_PWR_DOWN Modus gesetzt werden um Strom aus dem Akku zu sparen und so eine möglichst lange Akkulaufzeit zu bekommen.

In einer normale loop() Schleife mit delay() liegt der Stromverbrauch bei gemessenen 54mA.
Im Schlaf Modus geht er auf 38mA zurück. Das ist immer noch erstaunlich viel Verbrauch, liegt aber an den zusätzlichen Elementen auf der Uno Platine. Die Power LED nimmt gut 10 mA und die USB Schnittstelle nimmt auch einiges auf.

Um wirklich Strom zu sparen macht es Sinn den Microcontroller einzeln auf einer Platine zu haben mit einer minimalen Beschaltung. Im Sleep Modus geht er dann auf unter 0,1 mA Stromaufnahme. Zum Testen nehme ich aber vorerst die Uno Platine.

Hier die minimale Beschaltung

Als erstes werden ein paar nicht benötigte Funktionen des Controllers abgeschaltet, das bringt gut 1mA Ersparniss im normalen Betrieb.

  ADCSRA = ADCSRA & B01111111; // ADC abschalten, ADEN bit7 zu 0
  ACSR = B10000000; // Analogen Comparator abschalten, ACD bit7 zu 1
  DIDR0 = DIDR0 | B00111111; // Digitale Eingangspuffer ausschalten, analoge Eingangs Pins 0-5 auf 1

Dann wird der Watchdog Timer auf eine Sekunde eingestellt. Das WDTSCR Register wird mit dem Prescaler Wert 128k für 1 Sekunde gesetzt.

Register

Register

Prescaler

Prescaler

void watchdogOn() {
  MCUSR = MCUSR & B11110111; // Reset flag ausschalten, WDRF bit3 vom MCUSR.
  WDTCSR = WDTCSR | B00011000; // Bit 3+4 um danach den Prescaler setzen zu können
  WDTCSR = B00000110; // Watchdog Prescaler auf 128k setzen > ergibt ca. 1 Sekunde
  WDTCSR = WDTCSR | B01000000; // Watchdog Interrupt einschalten
  MCUSR = MCUSR & B11110111;
}

Für den Power Down Modus gibt es noch die Funktion zum schlafen legen für mehrere Sekunden.

void pwrDown(int sekunden) {
  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // den tiefsten Schlaf auswählen PWR_DOWN
  for(int i=0; i < sekunden; i++) {
    sleep_enable(); // sleep mode einschalten
    sleep_mode(); // in den sleep mode gehen
    sleep_disable(); // sleep mode ausschalten nach dem Erwachen
  }
}

Und hier das komplette Programm.
Im Hauptprogramm wird die LED 13 für 1 Sekunde eingeschaltet, der Zähler k wird seriell ausgegeben und dann geht der Uno 10 Sekunden schlafen.

// Arduino Uno runter fahren und wieder aufwecken.
//
// Matthias Busse 7.9.2014 Version 1.0

#include < avr/sleep.h> 

volatile int sleepcounter = 0; // Schlafzyklen mitzählen
int k=0, led=13;

void setup() {
  Serial.begin(115200);
  pinMode(led, OUTPUT);
  watchdogOn(); // Watchdog timer einschalten.
  ADCSRA = ADCSRA & B01111111; // ADC abschalten, ADEN bit7 zu 0
  ACSR = B10000000; // Analogen Comparator abschalten, ACD bit7 zu 1
  DIDR0 = DIDR0 | B00111111; // Digitale Eingangspuffer ausschalten, analoge Eingangs Pins 0-5 auf 1
}

void loop(){
  digitalWrite(led, HIGH);
  delay(100); // delay für serielle Ausgabe
  Serial.println(k);  
  k++;
  delay(900); // delay für serielle Ausgabe beenden
  digitalWrite(led, LOW);
  pwrDown(10); // ATmega328 fährt runter für 10 Sekunden;
}

void pwrDown(int sekunden) {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // den tiefsten Schlaf auswählen PWR_DOWN
  for(int i=0; i < sekunden; i++) {
    sleep_enable(); // sleep mode einschalten
    sleep_mode(); // in den sleep mode gehen
    sleep_disable(); // sleep mode ausschalten nach dem Erwachen
  }
}

void watchdogOn() {
  MCUSR = MCUSR & B11110111; // Reset flag ausschalten, WDRF bit3 vom MCUSR.
  WDTCSR = WDTCSR | B00011000; // Bit 3+4 um danach den Prescaler setzen zu können
  WDTCSR = B00000110; // Watchdog Prescaler auf 128k setzen > ergibt ca. 1 Sekunde
  WDTCSR = WDTCSR | B01000000; // Watchdog Interrupt einschalten
  MCUSR = MCUSR & B11110111;
}

ISR(WDT_vect) {
  sleepcounter ++; // Schlafzyklen mitzählen
}

Hier gibt es ein paar Alternativen und Erläuterungen zum Thema.
Und hier eine Minimalbeschaltung des ATMEGA168.

von Matthias Busse

6 Gedanken zu „Den Arduino in den Schlaf Modus setzen und wieder aufwecken.

  1. Pingback: Vergleich der Stromaufnahme von Arduino Schaltungen, vom Uno bis zum IC im Schlafmodus auf dem Steckbrett | Shelvin – Elektronik ausprobiert und erläutert

  2. Roland

    Hallo, ich komme mit der avr/sleep Library nicht zurecht. Auf Github habe ich diese gefunden, aber wie kann ich diese downloaden bzw. installieren?
    Vielen Dank im voraus!

    Antworten
  3. Sebastian

    Hallo,
    bei mir bleibt nach der Programmierung wie oben beschrieben der Arduino Uno in der void Setup () hängen. Was mache ich denn hier bitte falsch?

    Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.