Wenn ein ESP8266 im Batterie-Betrieb laufen soll oder durch eine Solar-Zelle versorgt werden soll, hängt die mögliche Betriebsdauer direkt von der Stromaufnahme des Geräts ab. Es gibt eine Reihe von Sites, die sich mit der Stromaufnahme des ESP8266 beschäftigen. Ich habe aber keine gefunden, die einmal sämtliche Zustände durchdekliniert. Das habe ich hier nachgeholt. Eine Zusammenfassung der Ergebnisse erfolgt direkt im Anschluss. Die Details finden sich im Abschnitt Einzelergebnisse.
Inhaltsverzeichnis
Board: | ESP-12 |
Chip ID: | 14165390 |
CPU Frequenz: | 80 MHz |
Flash Chip Type: | BG25Q32 |
Flash-Größe: | 4 MB |
Firmware: | Arduino Plugin ESP8266 core for Arduino Version 2.3.0 |
WiFi-Mode | Connection | Sleep-Mode | Stromaufnahme |
---|---|---|---|
Off | - | - | Ø 90mA ^ 90mA |
STA | none | - | Ø 90mA ^ 90mA |
connected | none | Ø 90mA ^ 370mA | |
modem | Ø 40mA ^ 370mA | ||
light | Ø 30mA ^ 370mA | ||
AP | - | - | Ø 90mA ^ 370mA |
AP_STA | - | - | Ø 90mA ^ 370mA |
(Werte wurden zur Sicherheit aufgerundet)
Board: | ESP-12 |
Chip ID: | 14165390 |
CPU Frequenz: | 80 MHz |
Flash Chip Type: | BG25Q32 |
Flash-Größe: | 4 MB |
Firmware: | Arduino Plugin ESP8266 core for Arduino Version 2.3.0 |
Ein FT232-Board dient der Stromversorgung und zur Kommunikation mit dem ESP. In die Masseleitung wurde ein 1Ω-Widerstand eingeschleift. Der Spannungsabfall an dem Widerstand wurde mit einem Oszilloskop aufgezeichnet (Kanal 1). 1mV entspricht dabei 1mA.
Die übrige Verschaltung entspricht dem Standard (s. Arduino: Was geht)).
Um feststellen zu können, wann der ESP erneut seine Arbeitsschleife beginnt, wird zu Beginn von loop() GPIO14 kurzeitig (1ms) auf HIGH gelegt (s.u. Testprogramm).
Hier eine typische Ausgabe des Oszilloskops:/p>
Im oberen Teil (gelber Graph) sieht man den zeitlichen Verlauf der Stromaufnahme des ESP-12. Auf dem unteren grünen Graph sind die Trigger-Pulse zu erkennen.
Das Testprogramm ist ein sehr einfach gehaltenes Arduino-Programm mit den Standard-Methoden setup() zur Initialisierung des Systems und der Arbeitsschleife loop(). In loop() erfolgt zunächst die Ausgabe eines 1ms dauernden Trigger-Pulses auf GPIO14. Danach wird die serielle Schnittstelle abgefragt, ob der Sleep-Modus gewechselt werden soll. Zuletzt erfolgt ein delay(1000). Die zusätzliche Stromsparfunktion beim Modus Light-Sleep erfolgt nur während des Delay.
Die Method printState() gibt den aktuellen Zustand über die serielle Schnittstelle aus. connectStation() stellt eine Verbindung zum Access-Point (Router) her.
#include <ESP8266WiFi.h>
#include "Helpers.h"
const char* ssid = "xxx";
const char* password = "xxx";
const char* hostName = "ESP-Current";
void setup() {
ESP.eraseConfig(); // Alte Konfiguration löschen
Serial.begin(115200);
Serial.println("\n----------------------------");
WiFi.mode(WIFI_OFF);
WiFi.setAutoConnect(false);
// Initialen Zustand ausgeben
printState();
pinMode(14, OUTPUT); // Pin für Trigger-Signal auf Output
}
void loop() {
// 1 ms Pulse an GPIO 14
digitalWrite(14, HIGH);
delay(1);
digitalWrite(14, LOW);
// Modi umschalten
if (Serial.available()) {
int c = Serial.read();
switch (c) {
case 'n': WiFi.setSleepMode(WIFI_NONE_SLEEP); break;
case 'l': WiFi.setSleepMode(WIFI_LIGHT_SLEEP); break;
case 'm': WiFi.setSleepMode(WIFI_MODEM_SLEEP); break;
case 'o': WiFi.mode(WIFI_OFF); break;
case 's': WiFi.mode(WIFI_STA); break;
case 'a': WiFi.mode(WIFI_AP); break;
case 'b': WiFi.mode(WIFI_AP_STA); break;
case 'c': connectStation(ssid, password, hostName); break; // WLAN Verbindung herstellen
case 'd': WiFi.disconnect(); break;
case 'w': WiFi.softAP(hostName, password); break;
}
while (Serial.available()) Serial.read(); // Eingabepuffer leer lesen
// Aktuellen Sleep-Mode ausgeben
printState();
}
delay(1000);
}
Hinzu kommen die Hilfsfunktionen printState() und connectStation().
#include "Helpers.h"
// Aktuellen Sleep-Mode als Text zurück liefern
String getSleepModeString() {
WiFiSleepType_t sm = WiFi.getSleepMode();
switch (sm) {
case WIFI_NONE_SLEEP: return "WIFI_NONE_SLEEP";
case WIFI_LIGHT_SLEEP: return "WIFI_LIGHT_SLEEP";
case WIFI_MODEM_SLEEP: return "WIFI_MODEM_SLEEP";
default: return "UNKNOWN";
}
}
// Aktuellen Modus als Text zurück liefern
String getModeString() {
WiFiMode_t m = WiFi.getMode();
switch (m) {
case WIFI_OFF: return "WIFI_OFF";
case WIFI_STA: return "WIFI_STA";
case WIFI_AP: return "WIFI_AP";
case WIFI_AP_STA: return "WIFI_AP_STA";
default: return "UNKNOWN";
}
}
// Gibt den aktuellen Zustand aus
void printState() {
Serial.print(" Mode: "); Serial.print(getModeString());
if (WiFi.isConnected())
Serial.println(", connected");
else
Serial.println(", offline");
Serial.print("Sleep Mode: "); Serial.println(getSleepModeString());
}
uint8_t connectStation(const char * ssid, const char * password, const char * hostName) {
uint8_t i = 0;
// hostName festlegen
if (hostName) {
if (*hostName != 0) { // ist nicht leer?
if (!WiFi.hostname(hostName)) {
Serial.print(F("***** Error: Could not set hostname: '"));
Serial.print(hostName);
Serial.println(F("'!"));
return 2;
}
} // if *hostName
} // if hostName
// Verbindung zum WLAN
Serial.print(F("Connecting to WiFi "));
Serial.print(ssid);
Serial.print(F(" as "));
Serial.print(WiFi.hostname());
Serial.print(' ');
WiFi.begin(ssid, password);
// Auf Verbindung warten (ca. 5 Sec)
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (i > 10) {
Serial.println(F("***** Error: WiFi connection failed!"));
return 3;
}
i++;
}
Serial.println();
Serial.print(F("Connected to "));
Serial.print(ssid);
Serial.print(F(", IP address: "));
Serial.println(WiFi.localIP());
return 0;
}
Hinweis zu den
Grafiken: Einige der Messungen wurden mit einem zusätzlichen Glättungskondensator
von 1000µF zwischen VCC und GND durchgeführt. Dadurch wurden die Stromspitzen von knapp 400mA auf
knapp 90mA reduziert. Die Befürchtung war, dass der Spannungsabfall am Messwiderstand sonst zu groß
würde. Außer der Abschwächung der Peaks zu Beginn und Ende einer Übertragung hat dies keinen Effekt.
Einige der Grafiken haben eine vertikale Auflösung von 50mV pro Skaleneinheit, andere 100mV.
Das Test-Programm entspricht vollständig dem vorher aufgeführten.
Der Stromverbrauch ist unabhängig vom Sleep-Modus. Er ist relativ konstant und beträgt durchschnittlich ca. 85mA.
WiFi.mode(WIFI_OFF);
wurde ersetzt durch WiFi.mode(WIFI_STA);
.
Eine Verbindung zu einem WLAN wurde nicht hergestellt.
Das Ergebnis entspricht dem vorhergehenden: Der Stromverbrauch ist unabhängig vom Sleep-Modus. Er ist relativ konstant und beträgt durchschnittlich ca. 85mA.
Die WLAN-Verbindung wird in setup() mit folgender Anweisung hergestellt:
...
// WiFi Verbindung herstellen
UrsWiFi.connectStation(ssid, password, hostName);
...
(Zu UrsWiFi.connectStation siehe ESP8266 UrsWiFi: Was man immer wieder macht)
Der Stromverbrauch ist relativ konstant und beträgt durchschnittlich ca. 85mA.. |
Der Stromverbrauch ist beträgt durchschnittlich knapp 40mA. Über die meiste Zeit, während der das Modem ausgeschaltet ist, beträgt die Stromaufnahme etwa 25mA. Es etwa alle 1,5s treten längere Bereiche (ca. 170ms) mit höherem Verbrauch (gut 85 mA) auf; etwa dem Verbrauch, wie er ohne Modem-Abschaltung vorliegt. Offensichtlich findet hier eine Datenübertragung statt. Diese ist nicht synchron mit dem Programm (grüne Trigger-Pulse). Es muss also eine externe Ursache vorliegen. Daneben treten etwa alle 100ms kurze Pulse auf, die DTIM-Signale. |
|
Während das Modem ausgeschaltet ist, beträgt die Stromaufnahme etwa 25mA. | |
Etwa alle 1,5s gibt es längere Bereiche (ca. 170ms) mit höherem Verbrauch (gut 85 mA). Diese treten meist regelmäßig auf, es gibt aber auch Zwischenereignisse. Zu Beginn und Ende gibt es kurze Pulse von ca. 370mA. Die Dauer dieser Pulse liegt bei etwa 0,1ms. | |
Etwa alle 100ms treten kurze Pulse auf, die DTIM-Signale. Hier steigt der Stromverbrauch auch wieder auf etwa 100mA. Der DTIM-Pulse hat eine Länge von etwa 5ms. |
Die Tatsache, dass die CPU immer für die Dauer eines DTIM-Intervalls aktiv wird, lässt vermuten, dass kleine Delay-Zeiten zusätzliche Stromspar-Effekte durch den Light-Sleep-Modus verhindern. Dies ist in der Tat der Fall. Das folgende Bild zeigt den Stromverbrauch im Light-Sleep-Modus bei einem Delay von nur 90ms. Der Stromverbrauch ist der selbe wie im Modem-Sleep-Modus (Ø 38mA). Die CPU wird nur für kurze Zeit ausgeschaltet (s. Markierung).
Im letzten Beispiel zu diesem Thema werden zu Begin jeder Arbeitsschleife fünf UDP-Pakete versandt. Deutlich kann man den erhöhten Stromverbrauch synchron zu den Trigger-Pulsen erkennen. Der durchschnittliche Stromverbrauch stiegt leicht an (ca. +1mA).
Im Access-Point-Modus beträgt der durchschnittliche Stromverbrauch knapp 90mA. Etwa alle 100ms
wird das DTIM-Signal
gesandt. Eine Veränderung des Sleep-Modus hat keine Auswirkung. Es spielt auch keine Rolle, ob der
Access-Point mit WiFi.softAP(hostName, password)
gestartet
wurde. Das gleiche Bild zeigt sich im Modus WIFI_AP_STA. Es gibt
keinen Unterschied zu WIFI_AP. Auch das Verbinden mit einem WLAN
ändert nichts am Stromverbrauch.
Hinweis: Sobald der AP-Modus aktiviert wird (WiFi.mode(WIFI_AP)
),
wird ein WLAN eingerichtet. Ohne WiFi.softAP(hostName, password)
ist besitzt dies einen internen Namen, z.B. ESP_D8258E, und kein Passwort. Die Methode
softAP() gibt den Netzwerk einen Namen und ein Passwort.
Die DTIM-Pulsdauer beträgt ca. 1,5ms und der Stromverbrauch steigt auf ca. 350mA.