SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
axp517_charger_web_monitor.ino
Go to the documentation of this file.
1
40#include <Wire.h>
41#include <SPI.h>
42#include <Arduino.h>
43#ifdef ARDUINO_ARCH_ESP32
44#include <WiFi.h>
45#include <WebServer.h>
46#include <PmicDrv.hpp>
47
48
49#ifndef WIFI_SSID
50#define WIFI_SSID "YourSSID"
51#endif
52#ifndef WIFI_PASSWORD
53#define WIFI_PASSWORD "YourPassword"
54#endif
55
56#ifndef PMIC_SDA
57#define PMIC_SDA 3
58#endif
59
60#ifndef PMIC_SCL
61#define PMIC_SCL 2
62#endif
63
64#ifndef PMIC_IRQ
65#define PMIC_IRQ -1
66#endif
67
68volatile bool irqTriggered = false;
69
70WebServer server(80);
71
73
74String ledModeStr(PmicLedBase::Mode mode)
75{
76 switch (mode) {
77 case PmicLedBase::Mode::AUTO: return "Auto";
78 case PmicLedBase::Mode::MANUAL: return "Manual";
79 case PmicLedBase::Mode::BREATH: return "Breath";
80 case PmicLedBase::Mode::DISABLE: return "Disabled";
81 default: return "Unknown";
82 }
83}
84
85String ledStateStr(PmicLedBase::ManualState state)
86{
87 switch (state) {
88 case PmicLedBase::ManualState::HiZ: return "Off (Hi-Z)";
89 case PmicLedBase::ManualState::LEVEL_LOW: return "Low";
90 case PmicLedBase::ManualState::LEVEL_HIGH: return "High";
91 case PmicLedBase::ManualState::BLINK_1HZ: return "Blink 1Hz";
92 case PmicLedBase::ManualState::BLINK_4HZ: return "Blink 4Hz";
93 default: return "Unknown";
94 }
95}
96
97void printBanner()
98{
99 Serial.println("");
100 Serial.println("╔══════════════════════════════════════════╗");
101 Serial.println("║ AXP517 Charger Web Monitor Test ║");
102 Serial.println("╚══════════════════════════════════════════╝");
103 Serial.println("");
104}
105
106void setup()
107{
108 bool rlst;
109
110 Serial.begin(115200);
111
112 printBanner();
113
114 rlst = bmu.begin(Wire, AXP517_SLAVE_ADDRESS, PMIC_SDA, PMIC_SCL);
115 if (!rlst) {
116 Serial.println("AXP517 begin() failed. Check wiring.");
117 while (1) {
118 delay(1000);
119 }
120 }
121
122 Serial.println("AXP517 initialized successfully");
123
124 // Enable charger module
125 bmu.enableModule(PmicAXP517::Module::CHARGE, true);
126
127 // Configure LED mode
129
130 // Pre-charge current: 0-960mA, 64mA steps
131 rlst = bmu.charger().setPreChargeCurrent(256);
132 if (!rlst) Serial.println("setPreChargeCurrent failed");
133 // Fast charge current: 0-5120mA, 64mA steps
134 rlst = bmu.charger().setFastChargeCurrent(1024);
135 if (!rlst) Serial.println("setFastChargeCurrent failed");
136 // Termination current: 0-960mA, 64mA steps
137 rlst = bmu.charger().setTerminationCurrent(64);
138 if (!rlst) Serial.println("setTerminationCurrent failed");
139 // Charge voltage: 3600/3800/4000/4100/4200/4350/4400/5000 mV
140 rlst = bmu.charger().setChargeVoltage(4200);
141 if (!rlst) Serial.println("setChargeVoltage failed");
142
143 Serial.print("Pre Charge Current: ");
144 Serial.println(bmu.charger().getPreChargeCurrent());
145 Serial.print("Fast Charge Current: ");
146 Serial.println(bmu.charger().getFastChargeCurrent());
147 Serial.print("Termination Current: ");
148 Serial.println(bmu.charger().getTerminationCurrent());
149 Serial.print("Charge Voltage: ");
150 Serial.println(bmu.charger().getChargeVoltage());
151
152 // Power path configuration
153 // Input current limit: 100-3250mA, 50mA steps
155 // Input voltage limit: 3600-16200mV, 100mV steps
157 // Minimum system voltage: 1000-3800mV, 100mV steps
159
160 Serial.print("Input Current Limit: ");
161 Serial.println(bmu.power().getInputCurrentLimit());
162 Serial.print("Input Voltage Limit: ");
163 Serial.println(bmu.power().getInputVoltageLimit());
164 Serial.print("Minimum System Voltage: ");
165 Serial.println(bmu.power().getMinimumSystemVoltage());
166
167 // Enable ADC channels for monitoring
175
176
177 const char *ssid = WIFI_SSID;
178 const char *password = WIFI_PASSWORD;
179 WiFi.begin(ssid, password);
180 while (WiFi.status() != WL_CONNECTED) {
181 delay(500);
182 Serial.print(".");
183 }
184 Serial.println();
185 Serial.print("WiFi connected, IP: ");
186 Serial.println(WiFi.localIP());
187
188 server.on("/boost/on", []() {
189 bool ret = bmu.power().enableBoost(true);
190 server.send(200, "text/plain", ret ? "OK" : "FAILED");
191 });
192
193 server.on("/boost/off", []() {
194 bool ret = bmu.power().enableBoost(false);
195 server.send(200, "text/plain", ret ? "OK" : "FAILED");
196 });
197
198 server.on("/ship/on", []() {
200 if (status.vbusPresent) {
201 server.send(400, "text/plain", "ERROR: Remove USB power first to enable ship mode");
202 return;
203 }
204 bool ret = bmu.power().enableShipMode(true);
205 server.send(200, "text/plain", ret ? "OK" : "FAILED");
206 });
207
208 server.on("/led/mode", []() {
209 if (!server.hasArg("mode")) {
210 server.send(400, "text/plain", "Missing mode argument");
211 return;
212 }
213 String mode = server.arg("mode");
214 bool ret = false;
215 if (mode == "auto") {
217 } else if (mode == "manual") {
219 } else if (mode == "breath") {
221 } else if (mode == "disable") {
223 } else {
224 server.send(400, "text/plain", "Invalid mode");
225 return;
226 }
227 server.send(200, "text/plain", ret ? "OK" : "FAILED");
228 });
229
230 server.on("/led/state", []() {
231 if (!server.hasArg("state")) {
232 server.send(400, "text/plain", "Missing state argument");
233 return;
234 }
235 String state = server.arg("state");
236 bool ret = false;
237 if (state == "off") {
239 } else if (state == "low") {
241 } else if (state == "high") {
243 } else if (state == "blink1") {
245 } else if (state == "blink4") {
247 } else {
248 server.send(400, "text/plain", "Invalid state");
249 return;
250 }
251 server.send(200, "text/plain", ret ? "OK" : "FAILED");
252 });
253
254 server.on("/", []() {
255 char timeStr[32];
256 time_t now = millis() / 1000;
257 int hrs = (now / 3600) % 24;
258 int mins = (now / 60) % 60;
259 int secs = now % 60;
260 sprintf(timeStr, "%02d:%02d:%02d", hrs, mins, secs);
261
262 bool boostEnabled = bmu.power().isBoostEnabled();
263 bool shipEnabled = bmu.power().isShipModeEnabled();
265
266 String html = "<html><head><meta charset='utf-8'><title>AXP517 Charger Monitor</title>";
267 html += "<script>";
268 html += "function toggleBoost(enable) {";
269 html += " var xhr = new XMLHttpRequest();";
270 html += " xhr.open('GET', enable ? '/boost/on' : '/boost/off', true);";
271 html += " xhr.onload = function() { if(xhr.status==200) location.reload(); else alert(xhr.responseText); };";
272 html += " xhr.send();";
273 html += "}";
274 html += "function enableShipMode() {";
275 html += " if(!confirm('WARNING: Ship mode will disconnect the battery and power off the device!\\n\\nYou must connect USB power or press PWR button to keep the device running after enabling ship mode.\\n\\nAre you sure you want to continue?')) return;";
276 html += " var xhr = new XMLHttpRequest();";
277 html += " xhr.open('GET', '/ship/on', true);";
278 html += " xhr.onload = function() { if(xhr.status==200) { alert('Ship mode enabled! Device will power off.'); location.reload(); } else { alert(xhr.responseText); } };";
279 html += " xhr.send();";
280 html += "}";
281 html += "function setLedMode(mode) {";
282 html += " var xhr = new XMLHttpRequest();";
283 html += " xhr.open('GET', '/led/mode?mode=' + mode, true);";
284 html += " xhr.onload = function() { if(xhr.status==200) location.reload(); else alert(xhr.responseText); };";
285 html += " xhr.send();";
286 html += "}";
287 html += "function setLedState(state) {";
288 html += " var xhr = new XMLHttpRequest();";
289 html += " xhr.open('GET', '/led/state?state=' + state, true);";
290 html += " xhr.onload = function() { if(xhr.status==200) location.reload(); else alert(xhr.responseText); };";
291 html += " xhr.send();";
292 html += "}";
293 html += "</script>";
294 html += "</head><body>";
295 html += "<h1>AXP517 Charger Status</h1>";
296 html += "<p><strong>Last Update: " + String(timeStr) + "</strong></p>";
297
298 html += "<h2>Boost Control</h2>";
299 html += "<p>Boost Status: <strong>" + String(boostEnabled ? "ON" : "OFF") + "</strong></p>";
300 if (boostEnabled) {
301 html += "<button onclick='toggleBoost(false)' style='background:#f44336;color:white;padding:10px 20px;border:none;cursor:pointer;'>Turn OFF Boost</button>";
302 } else {
303 html += "<button onclick='toggleBoost(true)' style='background:#4CAF50;color:white;padding:10px 20px;border:none;cursor:pointer;'>Turn ON Boost</button>";
304 }
305
306 html += "<h2>Ship Mode (Battery Off)</h2>";
307 html += "<p>Ship mode is <strong>" + String(shipEnabled ? "Enabled" : "Disabled") + "</strong></p>";
308 html += "<p>Ship mode disconnects the battery and powers off the device.</p>";
309 html += "<p>To exit ship mode, connect USB power.</p>";
310 html += "<button onclick='enableShipMode()' style='background:#FF9800;color:white;padding:10px 20px;border:none;cursor:pointer;'>Enable Ship Mode</button>";
311
312 html += "<h2>LED Control</h2>";
313 html += "<p>LED Mode: <strong>" + String(ledModeStr(bmu.led().getMode())) + "</strong></p>";
314 html += "<div>";
315 html += "<button onclick='setLedMode(\"auto\")' style='background:#2196F3;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>Auto</button>";
316 html += "<button onclick='setLedMode(\"manual\")' style='background:#2196F3;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>Manual</button>";
317 html += "<button onclick='setLedMode(\"breath\")' style='background:#2196F3;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>Breath</button>";
318 html += "<button onclick='setLedMode(\"disable\")' style='background:#f44336;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>Disable</button>";
319 html += "</div>";
320 html += "<p>Manual State: <strong>" + String(ledStateStr(bmu.led().getManualState())) + "</strong></p>";
321 html += "<div>";
322 html += "<button onclick='setLedState(\"off\")' style='background:#607D8B;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>Off (Hi-Z)</button>";
323 html += "<button onclick='setLedState(\"low\")' style='background:#607D8B;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>Low</button>";
324 html += "<button onclick='setLedState(\"high\")' style='background:#4CAF50;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>High</button>";
325 html += "<button onclick='setLedState(\"blink1\")' style='background:#FF9800;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>Blink 1Hz</button>";
326 html += "<button onclick='setLedState(\"blink4\")' style='background:#FF9800;color:white;padding:8px 16px;border:none;cursor:pointer;margin:2px;'>Blink 4Hz</button>";
327 html += "</div>";
328
329 html += "<h2>Charger Status</h2>";
330 html += "<table border='1' cellpadding='10'>";
331
332 float val;
333 bool ret;
334
335 html += "<tr><td>Chip</td><td>AXP517</td></tr>";
336
338 html += "<tr><td>VBUS Voltage</td><td>" + String(ret ? val : -1) + " mV</td></tr>";
339
341 html += "<tr><td>VBUS Current</td><td>" + String(ret ? val : -1) + " mA</td></tr>";
342
344 html += "<tr><td>Battery Voltage</td><td>" + String(ret ? val : -1) + " mV</td></tr>";
345
347 html += "<tr><td>Battery Current</td><td>" + String(ret ? val : -1) + " mA</td></tr>";
348
350 html += "<tr><td>VSYS Voltage</td><td>" + String(ret ? val : -1) + " mV</td></tr>";
351
353 html += "<tr><td>Die Temperature</td><td>" + String(ret ? val : -1) + " C</td></tr>";
354
356 html += "<tr><td>NTC Temperature</td><td>" + String(ret ? val : -1) + " %</td></tr>";
357
358 html += "<tr><td>Charging</td><td>" + String(status.charging ? "Yes" : "No") + "</td></tr>";
359 html += "<tr><td>Online</td><td>" + String(status.online ? "Yes" : "No") + "</td></tr>";
360 html += "<tr><td>VBUS Present</td><td>" + String(status.vbusPresent ? "Yes" : "No") + "</td></tr>";
361 html += "<tr><td>Battery Present</td><td>" + String(status.batteryPresent ? "Yes" : "No") + "</td></tr>";
362 html += "<tr><td>Charge Done</td><td>" + String(status.chargeDone ? "Yes" : "No") + "</td></tr>";
363 html += "<tr><td>Fault</td><td>" + String(status.fault ? "Yes" : "No") + "</td></tr>";
364
365 String chargingStatusStr;
366 switch (status.chargingStatus) {
367 case PmicChargerBase::ChargingStatus::NO_CHARGING: chargingStatusStr = "No charging";
368 break;
369 case PmicChargerBase::ChargingStatus::PRE_CHARGE: chargingStatusStr = "Pre-charge";
370 break;
371 case PmicChargerBase::ChargingStatus::FAST_CHARGE: chargingStatusStr = "Fast Charging";
372 break;
373 case PmicChargerBase::ChargingStatus::TERMINATION: chargingStatusStr = "Charge Termination Done";
374 break;
375 default:
376 break;
377 }
378 html += "<tr><td>Charging Status</td><td>" + chargingStatusStr + "</td></tr>";
379
380 html += "<tr><td>Boost Enabled</td><td>" + String(boostEnabled ? "Yes" : "No") + "</td></tr>";
381 html += "<tr><td>Boost Voltage</td><td>" + String(bmu.power().getBoostVoltage()) + " mV</td></tr>";
382
383 html += "<tr><td>Pre-Charge Current</td><td>" + String(bmu.charger().getPreChargeCurrent()) + " mA</td></tr>";
384 html += "<tr><td>Fast Charge Current</td><td>" + String(bmu.charger().getFastChargeCurrent()) + " mA</td></tr>";
385 html += "<tr><td>Termination Current</td><td>" + String(bmu.charger().getTerminationCurrent()) + " mA</td></tr>";
386 html += "<tr><td>Charge Voltage</td><td>" + String(bmu.charger().getChargeVoltage()) + " mV</td></tr>";
387
388 html += "<tr><td>Input Current Limit</td><td>" + String(bmu.power().getInputCurrentLimit()) + " mA</td></tr>";
389 html += "<tr><td>Input Voltage Limit</td><td>" + String(bmu.power().getInputVoltageLimit()) + " mV</td></tr>";
390 html += "<tr><td>Min System Voltage</td><td>" + String(bmu.power().getMinimumSystemVoltage()) + " mV</td></tr>";
391
392 html += "</table>";
393 html += "<meta http-equiv='refresh' content='1'>";
394 html += "<p>Auto-refresh every 1 second</p>";
395 html += "</body></html>";
396
397 server.send(200, "text/html", html);
398 });
399
400 server.begin();
401 Serial.println("Web server started");
402
403 Serial.println("Setup complete!");
404
405#if PMIC_IRQ != -1
406 pinMode(PMIC_IRQ, INPUT_PULLUP);
407 attachInterrupt(PMIC_IRQ, +[]() {
408 irqTriggered = true;
409 }, FALLING);
410#endif
411
412}
413
414void loop()
415{
416
417 server.handleClient();
418 delay(1);
419
420#if PMIC_IRQ != -1
421 if (irqTriggered) {
422 irqTriggered = false;
423 uint32_t irqStatus = bmu.irq().readStatus(true);
424 if (irqStatus) {
425 Serial.print("IRQ Status: 0x");
426 Serial.println(irqStatus, HEX);
427 if (bmu.irq().isVbusInsert(irqStatus)) {
428 Serial.println("VBUS Inserted");
429 }
430 if (bmu.irq().isVbusRemove(irqStatus)) {
431 Serial.println("VBUS Removed");
432 }
433 if (bmu.irq().isBatteryInsert(irqStatus)) {
434 Serial.println("Battery Inserted");
435 }
436 if (bmu.irq().isBatteryRemove(irqStatus)) {
437 Serial.println("Battery Removed");
438 }
439 if (bmu.irq().isChargeDone(irqStatus)) {
440 Serial.println("Charge Done");
441 }
442 if (bmu.irq().isChargeStart(irqStatus)) {
443 Serial.println("Charge Started");
444 }
445 if (bmu.irq().isVbusOverVoltage(irqStatus)) {
446 Serial.println("VBUS Over Voltage");
447 }
448 if (bmu.irq().isBoostOverVoltage(irqStatus)) {
449 Serial.println("Boost Over Voltage");
450 }
451 if (bmu.irq().isDieOverTempLevel1(irqStatus)) {
452 Serial.println("Die Over Temperature");
453 }
454 if (bmu.irq().isChgSafetyTimer(irqStatus)) {
455 Serial.println("Safety Timer Expired");
456 }
457 if (bmu.irq().isBatOverVoltage(irqStatus)) {
458 Serial.println("Battery Over Voltage");
459 }
460 if (bmu.irq().isBatFetOcp(irqStatus)) {
461 Serial.println("Battery FET Over Current");
462 }
463 }
464 }
465#endif
466}
467#else
468void setup()
469{
470 Serial.begin(115200);
471 Serial.println("This example is only compatible with ESP32. Please run on ESP32 platform.");
472}
473void loop()
474{
475 delay(1000);
476}
477#endif
@license MIT License
void printBanner()
#define PMIC_SDA
#define PMIC_SCL
#define PMIC_IRQ
volatile bool irqTriggered
PmicBQ25896 bmu
bool enableChannels(uint32_t mask) override
Enable one or more ADC channels.
bool read(Channel ch, float &out) override
Read ADC value for specified channel.
bool setFastChargeCurrent(uint16_t mA) override
Set fast charge (constant-current) current.
uint16_t getPreChargeCurrent() override
Get pre-charge current.
uint16_t getFastChargeCurrent() override
Get fast charge current.
bool setTerminationCurrent(uint16_t mA) override
Set termination current.
bool setChargeVoltage(uint16_t mV) override
Set charge voltage (constant voltage phase)
uint16_t getChargeVoltage() override
Get charge voltage.
bool setPreChargeCurrent(uint16_t mA) override
Set pre-charge current.
uint16_t getTerminationCurrent() override
Get termination current.
Status getStatus() override
Get charger status.
bool setMode(Mode mode) override
Set LED operating mode.
ManualState getManualState() override
Get manual LED state.
bool setManualState(ManualState state) override
Set manual LED state.
Mode getMode() override
Get LED operating mode.
bool isBoostEnabled() const override
Check if boost mode is enabled.
bool enableShipMode(bool enable) override
Enable or disable ship mode.
bool setMinimumSystemVoltage(uint32_t mv) override
Set minimum system voltage.
bool setInputVoltageLimit(uint32_t mv) override
Set input voltage limit (VINDPM)
bool setInputCurrentLimit(uint32_t mA) override
Set input current limit.
bool enableBoost(bool enable) override
Enable or disable OTG (boost) mode.
uint32_t getInputVoltageLimit() const override
Get input voltage limit.
uint16_t getBoostVoltage() const override
Get boost output voltage.
uint32_t getInputCurrentLimit() const override
Get input current limit.
uint32_t getMinimumSystemVoltage() const override
Get minimum system voltage.
bool isShipModeEnabled() const override
Check if ship mode is enabled.
High-level driver facade for the X-Powers AXP517 PMIC.
@ DIE_TEMPERATURE
Die temperature.
@ BAT_VOLTAGE
Battery voltage.
@ BAT_TEMPERATURE
Battery temperature.
@ BAT_CURRENT
Battery current.
@ VBUS_CURRENT
VBUS current.
@ VBUS_VOLTAGE
VBUS voltage.
@ VSYS_VOLTAGE
VSYS voltage.
BQ25896Adc & adc()
BQ25896Led & led()
BQ25896Power & power()
bool begin(SensorCommCustom::CustomCallback callback, SensorCommCustomHal::CustomHalCallback hal_cb, uint8_t addr)
Initialize using custom I2C callback.
BQ25896Charger & charger()
Get charger interface.
@ NO_CHARGING
Not charging, battery idle or disconnected.
@ PRE_CHARGE
Pre-charge phase (low current for weak battery)
@ TERMINATION
Charging terminated (battery full)
@ FAST_CHARGE
Fast charge phase (constant current)
ManualState
Manual LED state (portable subset).
Mode
High-level LED operating mode (portable subset).
@ BREATH
Breath/blink mode controlled by PMIC/hardware (if supported).
@ MANUAL
Manual control through registers.
@ AUTO
PMIC controls LED automatically (e.g.
@ DISABLE
LED is disabled (if supported).
Charger status structure.
bool vbusPresent
VBUS detected / good (USB power present)
bool chargeDone
Charge termination/done (battery full)
bool fault
Any fault latched/active.
bool charging
Charging state (coarse: true if in precharge/fastcharge)
bool batteryPresent
Battery present and detected.
ChargingStatus chargingStatus
Charging status enumeration.
bool online
PMIC reachable / initialized.