In diesem Tutorial lernst du, wie du den Ladezustand von LiPo-Akkus mit dem MAX1704X überwachen kannst. Die Hardware- und Codebeispiele sind für einen ESP32, funktionieren aber genauso mit einem ESP8266 oder Arduino.
LiPo-Akkus sind ideal für batteriebetriebene Projekte und werden häufig für Outdoor- oder mobile Anwendungen wie Wetterüberwachung, Überwachung oder Robotik eingesetzt. Aber bei Batteriebetrieb musst du wissen, wann du aufladen musst.
Die Abschätzung des Ladezustands eines LiPo-Akkus und der verbleibenden Laufzeit ist jedoch überraschend schwierig. LiPo-Akkus haben stark nichtlineare Entladekurven mit einem sehr plötzlichen Abfall am Ende. Schau dir die folgende Entladekurve an.

Noch schlimmer ist, dass die Entladekurve von der Umgebungstemperatur und dem Strom abhängt, den du aus dem Akku ziehst. Das macht es sehr schwierig, gute Schätzungen über den relativen Ladezustand und die verbleibende Laufzeit eines LiPo-Akkus zu bekommen.
Der MAX17043 ist ein fortschrittlicher Batterieladezustandsmesser, der dieses Problem löst. In diesem Tutorial lernst du, wie du den MAX17043 benutzt, um die Spannung und den relativen Ladezustand eines LiPo-Akkus mit einem ESP32 zu messen. Ich zeige dir auch, wie du Niedrig-Akku-Warnungen konfigurierst und handhabst.
Aber fangen wir mit den benötigten Teilen an.
Benötigte Teile
Für dieses Tutorial verwende ich ein älteres ESP32-Board (ESP32 lite), das zwar veraltet ist, aber noch günstig erhältlich ist. Das ist das unten aufgeführte Board. Es gibt ein Nachfolgemodell mit verbesserten Spezifikationen, das du hier finden kannst.
Aber die meisten ESP8266 und andere ESP32-Boards sollten ebenfalls funktionieren. Ich mag das ESP32 lite wegen des niedrigen Preises und des Batterieanschlusses mit integrierter Ladefunktion. So kannst du den ESP32 mit Akku betreiben und den LiPo über den USB-Anschluss laden – sehr praktisch.
Wenn du einen Arduino verwenden möchtest, solltest du ein Board nehmen, das mit 3,3V läuft, wie z.B. das Arduino Pro Mini (ATmega328-3.3V), da wir hier eine einzelne LiPo-Batterie (3,7V) verwenden. Ich habe auch ein OLED aufgeführt, aber jedes Display, das I2C unterstützt und mit 3,3V läuft, ist geeignet.
Es gibt zwei Versionen des MAX1704X. Der MAX17043, der hier aufgeführt ist, ist für eine einzelne LiPo-Zelle, während der MAX17044 für zwei LiPo-Zellen (in Serie) gedacht ist. Allerdings konnte ich kein Breakout-Board für den MAX17044 finden, deshalb verwenden wir den MAX17043. Das bedeutet aber, dass du einen Mikrocontroller brauchst, der mit 3,3V läuft, oder einen Buck-Boost-Wandler, um höhere Spannungen zu erzeugen.

MAX17043 LiPo Fuel Gauge

ESP32 lite

USB-Datenkabel

Dupont-Kabelset

Breadboard

Widerstands- & LED-Kit

OLED-Display

Arduino IDE
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Spezifikationen des MAX1704X Fuel Gauge
Der MAX17043/MAX17044 ist ein ultrakompaktes Fuel-Gauge-System für Lithium-Ionen (Li+) Akkus. Der eigentliche IC ist winzig, und das Bild unten zeigt ein typisches Breakout-Board für den Chip, was den Anschluss deutlich erleichtert.

Es gibt zwei Versionen des Chips. Der MAX17043 ist für eine einzelne Lithium-Zelle konfiguriert, während der MAX17044 für ein Dual-Cell 2S-Pack ausgelegt ist. Der Chip verwendet ein LiPo-Akku-Modellierungsschema namens ModelGauge, um den relativen Ladezustand (SOC) kontinuierlich über ein stark variierendes Lade-/Entladeprofil zu verfolgen.
Hier sind die Spezifikationen laut Datenblatt des MAX17043/MAX17044:
- Batterietyp: 3,7V Li-Polymer/Li-Ionen Akku
- 1 Zelle (MAX17043) oder 2 Zellen (MAX17044)
- Präzise Spannungsmessung
- ±12,5mV Genauigkeit bei 5V (MAX17043)
- ±30mV Genauigkeit bei 10V (MAX17044)
- Genauer relativer Kapazitätswert (RSOC)
- Keine Offset-Akkumulation bei Messungen
- Kein Full-to-Empty Relearning des Akkus nötig
- Externer Alarm/Interrupt für Niedrig-Akku-Warnung
- I2C-Schnittstelle
- Betriebsstrom: 50 µA
- Eingangsspannung (VCC): 3,3V~6,0V
Pinbelegung
Wie oben erwähnt, ist der MAX1704X ein winziger IC, deshalb verwenden wir das im Abschnitt „Benötigte Teile“ aufgeführte Breakout-Board. Die Pinbelegung für dieses Board findest du unten:

Das Board hat einen 2-poligen JST-Anschluss zum Verbinden des LiPo-Akkus. Es gibt aber auch zwei Pins (BAT+ und BAT-), an denen du den Akku anschließen kannst. Der Eingangsspannungsbereich liegt zwischen 2,5V und 4,5V. Die Nennspannung einer einzelnen LiPo-Zelle liegt bei etwa 3,7V. Voll geladen liegt die Spannung bei ca. 4,2V. Eine einzelne LiPo-Zelle fällt also in den Eingangsspannungsbereich.
Die Stromversorgung des Boards erfolgt über die VCC- und GND-Pins. Die maximale VCC-Spannung beträgt 5,5V, empfohlen sind 3,3V. Beachte, dass es verschiedene Versionen des Boards mit unterschiedlichen Optionen gibt (Akku oder MCU) zur Versorgung von VCC. Ich empfehle, die 3,3V deines Mikrocontrollers zu verwenden.
Der ALT-Pin ist der Alarm-Pin. Dieser Pin ist normalerweise HIGH, wird aber LOW, wenn der relative Ladezustand des Akkus unter einen konfigurierbaren Schwellenwert fällt, z.B. 10%. Du kannst diesen Pin an einen Interrupt-Pin deines Mikrocontrollers anschließen, um auf niedrige Akkustände zu reagieren.
Der QST-Pin ist für den Quick-Start-Eingang. Er ermöglicht es, den MAX17043 per Hardware zurückzusetzen. Eine steigende Flanke an diesem Pin löst einen Hardware-Reset aus. Du kannst den Reset aber auch per Software durchführen, was wir hier machen werden.
I2C-Schnittstelle
SDA und SCL sind die Pins für die I2C-Schnittstelle. Die I2C-Adresse des MAX17043 ist 0x36. Das Breakout-Board hat zwei 2,2kΩ Pull-up-Widerstände an den SDA- und SCL-Leitungen, sodass du keine separaten Pull-ups brauchst.
Beachte, dass es am unteren Teil des Boards einen 3-poligen Jumper gibt. Du kannst die Jumper durchtrennen, um die Pull-up-Widerstände zu deaktivieren, falls du mehrere I2C-Geräte anschließt. Für mehr Details siehe max1704 Guide.

Das war’s zum MAX17043. Schauen wir uns als Nächstes die verfügbaren Bibliotheken an, um Daten vom MAX170X IC auszulesen.
MAX170X Bibliotheken
Es gibt viele Bibliotheken, um den MAX17043 mit ESP32/ESP8266 oder Arduino zu nutzen. Namentlich die Bibliotheken von Porrey, Lucadentella, Sparkfun, Adafruit und Nlamprian. Alle sind im Wesentlichen Wrapper um die Funktionen des MAX1704X Chips und sehr ähnlich.
Ich habe die Sparkfun-Bibliothek und die von Porrey ausprobiert. Beide funktionieren, aber in diesem Tutorial zeige ich dir ausschließlich Code basierend auf der Porrey-Bibliothek. Wenn du eine andere bevorzugst, ist der Austausch recht einfach.
Funktionen der MAX170X Bibliothek
Hier eine kurze Übersicht der Funktionen, die du in der MAX170X Bibliothek von Porrey findest:
| begin(TwoWire*) | Erstellt eine FuelGauge-Instanz. |
| uint8_t address(); | Gibt die I2C-Adresse des IC zurück. |
| float voltage(); | Gibt die Batteriespannung in Millivolt zurück. |
| float percent(); | Gibt den Ladezustand (SOC) in Prozent zurück. |
| uint16_t version(); | Gibt die Version des MAX170X IC zurück. |
| uint8_t compensation(); | Gibt einen Wert zurück, der zur Optimierung der IC-Leistung unter verschiedenen Betriebsbedingungen dient. |
| void compensation(uint8_t); | Setzt einen Wert zur Optimierung der IC-Leistung unter verschiedenen Betriebsbedingungen. |
| bool sleep(); | Versetzt den MAX170X IC in den Schlafmodus. Alle Operationen werden angehalten. |
| bool isSleeping(); | Gibt zurück, ob der MAX170X IC im Schlafmodus ist. |
| bool wake(); | Weckt den MAX170X IC aus dem Schlafmodus auf. |
| void reset(); | Setzt den MAX170X IC zurück. |
| void quickstart(); | Startet die Batterieladeberechnung neu. |
| bool alertIsActive(); | Gibt zurück, ob eine Niedrig-Akku-Warnung aktiv ist. |
| void clearAlert(); | Löscht die Niedrig-Akku-Warnung. |
| uint8_t threshold(); | Gibt den aktuellen Schwellenwert für die Warnung zurück, z.B. 20% |
| void threshold(uint8_t); | Setzt den Schwellenwert für die Warnung, z.B. 20% |
Installation der MAX170X Bibliothek
Um die MAX170X Bibliothek von Porrey zu installieren, öffne den Library Manager und gib „MAX1704X“ in das Suchfeld ein. Du findest die „MAX1704X by Daniel Porrey“. Siehe unten:

Drücke den INSTALL-Button und fertig. Wie im Screenshot oben zu sehen, habe ich die Bibliothek bereits installiert. Du kannst auch die anderen Bibliotheken, z.B. von Sparkfun oder Adafruit, installieren, wenn du möchtest. Sie verursachen keine Konflikte.
In den nächsten zwei Abschnitten zeige ich dir zuerst, wie du den MAX17043 mit deinem Mikrocontroller verbindest und dann, wie du die Bibliothek benutzt, um Batteriedaten auszulesen.
MAX17043 mit ESP32 verbinden
Das Verbinden des MAX17043 mit einem Mikrocontroller ist sehr einfach. Verbinde zuerst 3,3V und GND des Mikrocontrollers mit VCC und GND des MAX17043 (rote und blaue Kabel). Wenn du einen 5V Arduino hast, kannst du auch 5V an VCC anschließen.

Als Nächstes verbindest du die I2C-Schnittstelle (SCL, SDA). Die Standardpins für I2C beim ESP32 lite sind 23 (SDA) und 19 (SCL). Das ist oben dargestellt (grüne und gelbe Kabel). Beim Arduino verbindest du SDA -> A4 und SCL -> A5. Achte darauf, diese Verbindungen richtig zu machen, da sie leicht verwechselt werden können und das Board sonst nicht funktioniert.
Zum Schluss verbinden wir den LiPo-Akku. Plus und Minus des Akkus werden mit den entsprechenden Anschlüssen des ESP32 und des MAX17043 verbunden. Das Schöne am ESP32-Board ist, dass du es vom Akku betreiben und gleichzeitig über das USB-Kabel mit dem Computer verbinden kannst. Wenn es verbunden ist, wird der Akku geladen. Der MAX17043 kann während des Ladevorgangs angeschlossen bleiben und meldet weiterhin Spannungen und Ladezustände.
Beachte, dass es Berichte gibt, dass MAX17043-Boards von manchen Anbietern nicht funktionieren. Mein Board von AliExpress funktioniert einwandfrei, und das im Abschnitt „Benötigte Teile“ aufgeführte Board sollte ebenfalls funktionieren. Ich habe das spezifische Board aber nicht getestet.
Batterieladung vom MAX17043 auslesen
Das folgende einfache Codebeispiel zeigt dir, wie du die Batteriespannung und den relativen Ladezustand mit dem MAX17043 ausliest. Schau es dir zuerst kurz an, dann besprechen wir den Code genauer.
#include "Wire.h"
#include "MAX17043.h"
void setup() {
Serial.begin(115200);
Wire.begin(SDA, SCL);
if (!FuelGauge.begin(&Wire)) {
Serial.println("MAX17043 NOT found.\n");
while (true) {}
}
FuelGauge.reset();
delay(250);
FuelGauge.quickstart();
delay(125);
}
void loop() {
float volts = FuelGauge.voltage();
float pcnt = FuelGauge.percent();
Serial.printf("%.0fmV (%.1f%%)\n", volts, pcnt);
delay(3000);
}
Bibliotheken einbinden
Wir beginnen mit dem Einbinden der Wire und der MAX17043 Bibliothek. Die Wire-Bibliothek wird benötigt, um die I2C-Schnittstelle zu konfigurieren. Wenn du einen MAX17044 hast, würdest du MAX17044.h statt MAX17043.h einbinden. Die MAX170X-Bibliothek von Porrey enthält beide Header-Dateien.
Setup-Funktion
In der setup() Funktion initialisieren wir die serielle Kommunikation mit 115200 Baud. Dann starten wir die I2C-Kommunikation mit der Wire.begin(SDA, SCL) Funktion.
Ich definiere die Pins für I2C explizit mit Wire.begin(SDA, SCL). So kannst du andere Pins als die Standardpins für I2C verwenden und es unterdrückt eine „Wire.begin()"„-Meldung im Serial Monitor, die sonst von der Bibliothek erzeugt wird (siehe blog).
Als Nächstes initialisieren wir den MAX17043 mit FuelGauge.begin(&Wire). Wenn der FuelGauge-Sensor nicht gefunden wird, wird eine Meldung im Serial Monitor ausgegeben und das Programm geht in eine Endlosschleife.
Andernfalls setzen wir den FuelGauge zurück, warten 250 ms, machen einen Quickstart und warten weitere 125 ms. Diese Sequenz stammt aus dem Beispielcode der MAX17043-Bibliothek. Ich bin mir nicht sicher, ob die Verzögerungen nötig sind, habe sie aber drin gelassen.
void setup() {
Serial.begin(115200);
Wire.begin(SDA, SCL);
if (!FuelGauge.begin(&Wire)) {
Serial.println("MAX17043 NOT found.\n");
while (true) {}
}
FuelGauge.reset();
delay(250);
FuelGauge.quickstart();
delay(125);
}
Loop-Funktion
Die loop() Funktion liest kontinuierlich die Spannung und den Ladezustand des LiPo-Akkus aus. Die Werte werden dann mit Serial.printf() an den Serial Monitor ausgegeben, mit einer Pause von 3 Sekunden zwischen den Messungen.
void loop() {
float volts = FuelGauge.voltage();
float pcnt = FuelGauge.percent();
Serial.printf("%.0fmV (%.1f%%)\n", volts, pcnt);
delay(3000);
}
Wenn du diesen Code hochlädst und ausführst, solltest du folgende Ausgabe im Serial Monitor sehen:

Beachte, dass der Arduino im Gegensatz zum ESP32 die printf Funktion nicht unterstützt. Du musst stattdessen eine Folge von print() Anweisungen verwenden. Um das zu vermeiden, verwenden wir in den folgenden Codebeispielen die aprintf library. Für mehr Details siehe unser Tutorial How To Print To Serial Monitor On Arduino.
Mehr Daten mit aprintf ausgeben
Das folgende Codebeispiel gibt alle Informationen aus, die wir vom MAX17043-Chip bekommen können, auf dem Serial Monitor aus. Die Struktur des Codes ist wie oben, aber es gibt ein paar kleine Änderungen, die ich hervorheben möchte.
#include "Wire.h"
#include "aprintf.h"
#include "MAX1704X.h"
MAX1704X monitor = MAX1704X(MAX17043_mV);
void setup() {
Serial.begin(115200);
Wire.begin(SDA, SCL);
if (!monitor.begin(&Wire)) {
aprintf("MAX1704X NOT found.\n");
while (true) {}
}
monitor.reset();
delay(250);
monitor.quickstart();
delay(125);
}
void loop() {
aprintf("---------------------------------\n");
aprintf("Voltage %.0fmV\n", monitor.voltage());
aprintf("Percent %.1f%%\n", monitor.percent());
aprintf("Address 0x%02x\n", monitor.address());
aprintf("Version %d\n", monitor.version());
aprintf("ADC %d\n", monitor.adc());
aprintf("Alert %d\n", monitor.alertIsActive());
aprintf("Sleeping %d\n", monitor.isSleeping());
aprintf("Compensation 0x%02x\n", monitor.compensation());
delay(3000);
}
Erstens kannst du statt des vordefinierten FuelGauge-Objekts dein eigenes FuelMonitor-Objekt erstellen:
MAX1704X monitor = MAX1704X(MAX17043_mV);
Im Konstruktor kannst du angeben, ob du einen MAX17043 oder MAX17044 hast und dann im restlichen Code den Namen „monitor“ oder einen anderen verwenden.
Zweitens benutze ich die aprintf library Funktion, um die Daten auf dem Serial Monitor auszugeben. Die aprint() Funktion macht dasselbe wie Serial.printf(), funktioniert aber gleich auf Arduino, ESP32 und ESP8266. Sie ist auch praktisch für formatierte Ausgaben auf Displays – was du im nächsten Abschnitt sehen wirst.
Du musst allerdings die aprintf-Bibliothek aus einer ZIP-Datei installieren. Lade das zip-file herunter und installiere sie dann über Sketch -> Include Library -> Install .ZIP Library ... .

Für mehr Details zu aprintf und dem Serial Monitor siehe unser Tutorial How To Print To Serial Monitor On Arduino. Nach der Installation solltest du den Code ausführen können und folgende Ausgabe im Serial Monitor sehen:

Wie du aus der Ausgabe entnehmen kannst, wurde der LiPo gerade geladen (Spannung = 4120mV), da der ESP32 für den Serial Monitor per USB mit dem Computer verbunden sein muss. Beim ESP32 lite lädt das den angeschlossenen LiPo-Akku.
Im nächsten Abschnitt zeige ich dir, wie du ein OLED anschließt und die Batteriedaten dort anzeigst, statt im Serial Monitor.
Batterieladung auf OLED anzeigen
Die Anzeige des Batteriestands im Serial Monitor ist zum Testen okay, aber für ein batteriebetriebenes Projekt nicht sehr praktisch. Normalerweise will man den aktuellen Ladezustand direkt anzeigen, z.B. mit einer LED-Leiste oder einem LCD-Display. In diesem Beispiel verwende ich ein OLED, da es sehr klein ist und gut mit 3,3V funktioniert.
Verdrahtung für OLED
Das folgende Diagramm zeigt, wie du das OLED (zusätzlich zu den bereits vorhandenen Teilen) anschließt. Verbinde zuerst 3,3V und GND vom Mikrocontroller mit VCC und GND des OLED (rote und blaue Kabel).

Dann verbinden wir die I2C-Leitungen (SDA, SCL) parallel zum MAX17043 (gelbe und grüne Kabel). OLED und MAX17043 teilen sich denselben I2C-Bus und müssen unterschiedliche I2C-Adressen haben. Wenn du Probleme hast, überprüfe die I2C-Adressen. Mein OLED hat die Adresse 0x3C und der MAX17043 hat typischerweise die Adresse 0x36. Auch die Pull-up-Widerstände können Probleme machen. Denk an den 3-poligen Jumper am MAX17043, mit dem du die Pull-ups deaktivieren kannst.
Wenn du mehr Details zur Verwendung eines OLED-Displays brauchst, schau dir unser Tutorial zu How to Interface the SSD1306 I2C OLED Graphic Display With Arduino an.
Code für OLED
Der folgende Code zeigt Batteriespannung und relativen Ladezustand auf dem OLED an. Schau dir zuerst den kompletten Code an, bevor wir ihn genauer besprechen.
#include "Wire.h"
#include "aprintf.h"
#include "MAX17043.h"
#include "Adafruit_SSD1306.h"
Adafruit_SSD1306 disp(128, 64, &Wire, -1);
void setup() {
Serial.begin(115200);
Wire.begin(SDA, SCL);
if (!FuelGauge.begin(&Wire)) {
aprintf("MAX17043 NOT found.\n");
while (true) {}
}
FuelGauge.reset();
delay(250);
FuelGauge.quickstart();
delay(125);
FuelGauge.threshold(20);
FuelGauge.clearAlert();
disp.begin(SSD1306_SWITCHCAPVCC, 0x3C);
disp.setTextSize(2);
disp.setTextColor(WHITE);
}
void loop() {
float volts = FuelGauge.voltage() / 1000;
float pcnt = FuelGauge.percent();
bool alrt = FuelGauge.alertIsActive();
disp.clearDisplay();
disp.setCursor(20, 10);
disp.print(fmt("%.1f%% %c", pcnt, alrt ? '!' : ' '));
disp.setCursor(20, 30);
disp.print(fmt("%.3fV", volts));
disp.display();
delay(3000);
}
Bibliotheken und Display-Setup
Der Code bindet notwendige Bibliotheken wie Wire.h, aprintf.h, MAX17043.h und Adafruit_SSD1306.h ein. Dann wird eine Instanz der Adafruit_SSD1306 Klasse für ein OLED-Display mit bestimmten Abmessungen initialisiert. Ich verwende hier ein 128×64 OLED. Wenn dein OLED eine andere Größe hat, musst du die Werte anpassen.
Adafruit_SSD1306 disp(128, 64, &Wire, -1);
Setup-Funktion
In der setup() Funktion wird die serielle Kommunikation mit 115200 Baud gestartet. Die I2C-Kommunikation wird mit der Wire.begin(SDA, SCL) Funktion initiiert. Der Code prüft, ob der MAX17043 IC erkannt wird, und wenn nicht, wird eine Meldung ausgegeben und das Programm geht in eine Endlosschleife. Danach wird der Fuel Gauge zurückgesetzt und ein Quickstart durchgeführt.
Wir setzen auch einen Schwellenwert für die Niedrig-Akku-Warnung mit FuelGauge.threshold(20). Das bedeutet, der Schwellenwert für die Warnung ist auf 20% gesetzt. Der höchste Wert, den du setzen kannst, ist 32%, der niedrigste 1%. Danach löschen wir alle bestehenden Warnungen.
FuelGauge.threshold(20); FuelGauge.clearAlert();
Zum Schluss initialisieren wir das OLED-Display. Achte darauf, hier die I2C-Adresse deines OLED zu verwenden. Meins ist 0x3C und ich habe ein schwarz-weiß OLED, deshalb setze ich die Textfarbe auf WEISS.
disp.begin(SSD1306_SWITCHCAPVCC, 0x3C); disp.setTextSize(2); disp.setTextColor(WHITE);
Loop-Funktion
Die loop() Funktion liest kontinuierlich die Batteriespannung und den Ladezustand mit den Funktionen FuelGauge.voltage() und FuelGauge.percent() aus. Sie prüft auch, ob Warnungen aktiv sind, mit FuelGauge.alertIsActive().
float volts = FuelGauge.voltage() / 1000; float pcnt = FuelGauge.percent(); bool alrt = FuelGauge.alertIsActive();
Die Batteriedaten werden mit der fmt() Funktion aus der aprintf Bibliothek und der display()-Funktion der Adafruit_SSD1306 Bibliothek auf dem OLED ausgegeben.
Die fmt() Funktion arbeitet wie Serial.printf(), gibt aber in einen String-Puffer aus, der dann zurückgegeben wird. Die disp.print() Funktion des OLED nimmt diesen String-Puffer und zeigt den Inhalt auf dem OLED an.
disp.clearDisplay();
disp.setCursor(20, 10);
disp.print(fmt("%.1f%% %c", pcnt, alrt ? '!' : ' '));
disp.setCursor(20, 30);
disp.print(fmt("%.3fV", volts));
disp.display();
Mit der fmt() Funktion kannst du dieselbe Formatierung verwenden und bequem auf Geräte ausgeben, die keine printf()-ähnliche Funktion unterstützen. Für das OLED darfst du aber das disp.display() am Ende nicht vergessen, sonst wird nichts angezeigt.
Das OLED zeigt den Batterieprozentsatz, die Spannung und ein Warnsymbol (!) an, wenn eine Warnung aktiv ist. Wenn alles richtig angeschlossen und implementiert ist, solltest du folgende Ausgabe sehen:

In diesem Beispiel haben wir eine Niedrig-Akku-Warnung auf dem OLED angezeigt, indem wir alle 3 Sekunden den Zustand des Warnpins abgefragt haben. Alternativ können wir einen Interrupt-Handler verwenden, um sofort auf eine Niedrig-Akku-Warnung zu reagieren. Das ist Thema des nächsten Abschnitts.
Handhabung von Niedrig-Akku-Warnungen des MAX17043
Um die Handhabung eines Niedrig-Akku-Ereignisses zu demonstrieren, fügen wir dem Schaltkreis eine LED hinzu. Diese LED leuchtet, wenn der Ladezustand unter einen vordefinierten Schwellenwert fällt.
Wir verbinden die positive Seite (langer Pin) der LED mit GPIO 25 des ESP32. Du kannst jeden anderen GPIO nehmen – vergiss nur nicht, den Code unten entsprechend anzupassen. Die negative Seite der LED wird über einen 68Ω Vorwiderstand mit GND (G) verbunden.

Jetzt kommt der interessante Teil. Der MAX17043 erzeugt am ALT-Pin ein Signal, wenn der Ladezustand unter den Schwellenwert fällt. Genauer gesagt geht der ALT-Pin von HIGH auf LOW. Wir verbinden den ALT-Pin mit GPIO 32 des ESP32, und ein Interrupt-Handler wird aufgerufen, wenn sich der Zustand des ALT-Pins ändert.
Schauen wir uns an, wie das im Code gemacht wird!
Code für Interrupt-Handler bei Niedrig-Akku
Die meisten Mikrocontroller, einschließlich ESP32, erlauben es, eine Interrupt-Handler-Funktion an einen Pin zu hängen. Diese Funktion wird ausgeführt, wenn sich der Pin-Zustand ändert. Der Code unten ist derselbe wie oben, mit der Ergänzung einer Interrupt-Handler-Funktion lowBattery(). Es gibt auch eine zusätzliche Definition für ledPin und alrtPin, die wir brauchen, um eine Niedrig-Akku-Warnung anzuzeigen und zu erkennen.
Unten ist der komplette Code, den wir in den folgenden Abschnitten genauer besprechen:
#include "Wire.h"
#include "aprintf.h"
#include "MAX17043.h"
#include "Adafruit_SSD1306.h"
const int alrtPin = 32;
const int ledPin = 25;
Adafruit_SSD1306 disp(128, 64, &Wire, -1);
void lowBattery() {
digitalWrite(ledPin, HIGH);
}
void setup() {
Serial.begin(115200);
Wire.begin(SDA, SCL);
if (!FuelGauge.begin(&Wire)) {
aprintf("MAX17043 device was NOT found.\n");
while (true) {}
}
FuelGauge.reset();
delay(250);
FuelGauge.quickstart();
delay(125);
FuelGauge.threshold(20);
FuelGauge.clearAlert();
disp.begin(SSD1306_SWITCHCAPVCC, 0x3C);
disp.setTextSize(2);
disp.setTextColor(WHITE);
pinMode(ledPin, OUTPUT);
pinMode(alrtPin, INPUT_PULLUP);
digitalWrite(ledPin, LOW);
attachInterrupt(alrtPin, lowBattery, FALLING);
}
void loop() {
float volts = FuelGauge.voltage() / 1000;
float pcnt = FuelGauge.percent();
bool alrt = FuelGauge.alertIsActive();
disp.clearDisplay();
disp.setCursor(20, 10);
disp.print(fmt("%.1f%% %c", pcnt, alrt ? '!' : ' '));
disp.setCursor(20, 30);
disp.print(fmt("%.3fV", volts));
disp.display();
delay(3000);
}
Konstanten und Variablen
Wie oben erwähnt definieren wir zuerst zwei neue Konstanten, alrtPin und ledPin, die die Pins für das Warnsignal und die LED-Anzeige repräsentieren.
const int alrtPin = 32; const int ledPin = 25;
Niedrig-Akku-Funktion
Die lowBattery() Funktion wird aufgerufen, wenn der Ladezustand unter einen bestimmten Schwellenwert fällt. Sie schaltet einfach die LED an, die an ledPin angeschlossen ist. Beachte, dass die LED an bleibt, bis der ESP32 neu gestartet wird, auch wenn der Ladezustand wieder über den Schwellenwert steigt. Das Verhalten lässt sich aber leicht ändern, falls du etwas anderes brauchst.
void lowBattery() {
digitalWrite(ledPin, HIGH);
}
Setup-Funktion
In der setup() Funktion initialisiert der Code die serielle Kommunikation, den I2C-Bus, den MAX17043 Fuel Gauge, das OLED-Display und setzt die Pin-Modi für LED und Warnsignal.
Am wichtigsten ist, dass der Interrupt so konfiguriert wird, dass die lowBattery() Funktion bei einer fallenden Flanke ausgelöst wird. Das bedeutet, wenn der ALT-Pin des MAX17043 wegen niedrigem Ladezustand auf LOW geht, erkennen wir diese fallende Flanke am alrtPin und rufen die lowBattery() Funktion auf. Beachte, dass die lowBattery() Funktion unabhängig von der loop() Funktion aufgerufen wird.
void setup() {
...
attachInterrupt(alrtPin, lowBattery, FALLING);
}
Wenn du mehr über Interrupts lernen möchtest, schau dir unsere Tutorials Push-Button And Arduino und Build Arduino Tachometer Using A3144 Hall Effect Sensor an, die mehr Anwendungen und Details bieten.
Loop-Funktion
Die loop() Funktion ist wie zuvor. Sie liest kontinuierlich die Batteriespannung, den Ladezustand und den Warnstatus vom MAX17043 IC aus. Dann aktualisiert sie die OLED-Anzeige mit diesen Informationen und prüft auf Warnungen. Wenn eine Warnung aktiv ist, wird ein Ausrufezeichen neben dem Batterieprozentsatz angezeigt.
Der wichtige Unterschied zwischen der Warnung auf dem OLED und der Warnung über die rote LED ist, dass das OLED nur alle 3 Sekunden aktualisiert wird, während die LED sofort reagiert.
Und das war’s. Mit diesen Schaltungen und dem Code kannst du den Batterieladezustand genau überwachen und schnell auf Niedrig-Akku-Warnungen reagieren.
Fazit
Der MAX1704X ist ein sehr praktischer kleiner IC, um den Batterieladezustand bei batteriebetriebenen Projekten zu überwachen. Die beiden Versionen, MAX17043 und MAX17044, sind im Wesentlichen gleich. Der oben gezeigte Code und die Schaltungen funktionieren für beide. Der einzige Unterschied ist, dass der MAX17043 für eine einzelne LiPo-Zelle (3,7V) gedacht ist, während der MAX17044 für zwei LiPo-Zellen (7,4V) in Serie verwendet wird.
Eine Funktion des MAX1704X, die wir in diesem Tutorial nicht behandelt haben, ist die Kompensationsfunktion. Sie kann offenbar die IC-Leistung für verschiedene Lithium-Chemien oder Betriebstemperaturen optimieren. Im Datenblatt gibt es aber keine Details zu den genauen Werten und deren Verwendung.
Eine weitere nette Funktion des MAX1704X, die dokumentiert ist, ist der Schlafmodus. Das ist praktisch in Verbindung mit dem Deep-Sleep-Modus des ESP32 (oder Arduino/ESP8266). So kannst du sowohl den Mikrocontroller als auch den Batteriemonitor in den Tiefschlaf versetzen, um die Batterielaufzeit zu verlängern.
Alternativ zum MAX1704X könntest du auch einen Spannungsteiler verwenden und die Batteriespannung über einen analogen Eingang messen, um ein einfaches Niedrig-Akku-Warnsystem zu implementieren. Mehr dazu findest du in unserem Tutorial How to Monitor Battery Voltage for Battery Powered Projects. Das ist günstiger, aber deutlich weniger zuverlässig, besonders wenn du die verbleibende Laufzeit schätzen und rechtzeitig nachladen möchtest.
Und jetzt viel Spaß ; )
Links
Hier ein paar Links, die ich beim Schreiben dieses Tutorials nützlich fand:
- SparkFun MAX1704x Fuel Gauge Arduino Library
- LiPo Fuel Gauge (MAX1704X) Hookup Guide – SparkFun Learn
- ESP32 get data from max17043 | All About Circuits
- Battery Monitoring Done Right (Arduino & ESP32)
Häufig gestellte Fragen
Wie genau ist der MAX1704X Fuel Gauge bei der Überwachung des Batterieladezustands?
Der MAX1704X Fuel Gauge ist sehr genau, mit einem typischen Fehler von nur ±1% über den gesamten Temperaturbereich.
Kann der MAX1704X mit anderen Mikrocontrollern als ESP32 und Arduino verwendet werden?
Ja, der MAX1704X kann mit verschiedenen Mikrocontrollern verwendet werden, solange sie I2C-Kommunikation unterstützen.
Ist es möglich, den Schwellenwert für die Niedrig-Akku-Warnung beim MAX1704X anzupassen?
Ja, der Schwellenwert für die Niedrig-Akku-Warnung kann an deine Anforderungen angepasst werden, indem du die entsprechenden Registerwerte änderst. Der maximale Schwellenwert ist 32%, der minimale 1%.
Kann der MAX1704X mit anderen Batterietypen als LiPo verwendet werden?
Obwohl der MAX1704X für LiPo-Akkus optimiert ist, kann er mit anderen Batterietypen verwendet werden, wenn die Konfiguration entsprechend angepasst wird.
Wie wird der MAX1704X Fuel Gauge mit Strom versorgt?
Der MAX1704X Fuel Gauge kann direkt vom überwachten Akku mit Strom versorgt werden, aber ich empfehle, ihn vom Mikrocontroller zu versorgen.
Kann der MAX1704X mehrere Batterien gleichzeitig überwachen?
Nein, der MAX1704X ist dafür ausgelegt, jeweils nur eine Batterie zu überwachen.
Welche Schnittstelle verwendet der MAX1704X Fuel Gauge zur Kommunikation?
Der MAX1704X Fuel Gauge kommuniziert mit dem Mikrocontroller über die I2C-Schnittstelle.
Ist es möglich, den MAX1704X für noch höhere Genauigkeit zu kalibrieren?
Ja, der MAX1704X kann per Softwarebefehlen kalibriert werden, um die Genauigkeit für spezifische Anwendungen zu verbessern. Siehe die compensation() Funktion der MAX1704X Bibliothek und das Datenblatt des MAX1704X.
Wie schützt der MAX1704X vor Überladung des Akkus?
Der MAX1704X bietet selbst keinen Überladeschutz, kann aber den Ladezustand überwachen, um in Verbindung mit geeigneter Ladetechnik eine Überladung zu verhindern.
Wie schützt der MAX1704X vor Tiefentladung des Akkus?
Der MAX1704X bietet keinen Schutz vor Tiefentladung, kann aber den Ladezustand überwachen, um in Verbindung mit geeigneten Energiemanagementsystemen eine Tiefentladung zu verhindern.
Wie groß ist der typische Betriebs-Spannungsbereich des MAX1704X Fuel Gauge?
Der MAX1704X arbeitet typischerweise im Spannungsbereich von 2,7V bis 5,5V; geeignet zur Überwachung der typischen Spannung eines LiPo-Akkus (3,7V).
Wie hoch ist der Stromverbrauch des MAX1704X Fuel Gauge?
Der typische Stromverbrauch des MAX1704X beträgt 50µA, im Schlafmodus sogar nur 1µA.

