SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
bq25896_charger_web_monitor.ino
Go to the documentation of this file.
1
39#include <Wire.h>
40#include <SPI.h>
41#include <Arduino.h>
42#ifdef ARDUINO_ARCH_ESP32
43#include <WiFi.h>
44#include <WebServer.h>
45#include <PmicDrv.hpp>
46
47#ifndef WIFI_SSID
48#define WIFI_SSID "YourSSID"
49#endif
50#ifndef WIFI_PASSWORD
51#define WIFI_PASSWORD "YourPassword"
52#endif
53
54#ifndef PMIC_SDA
55#define PMIC_SDA 2
56#endif
57
58#ifndef PMIC_SCL
59#define PMIC_SCL 3
60#endif
61
62#ifndef PMIC_IRQ
63#define PMIC_IRQ -1
64#endif
65
66volatile bool isFaultTrigger = false;
67
68WebServer server(80);
69
71
72#define CHECK_FOR_ERRORS(condition) if (condition) {log_e("BQ25896 error"); while(1)delay(1000);}
73
74void printBanner()
75{
76 Serial.println("");
77 Serial.println("╔══════════════════════════════════════════╗");
78 Serial.println("║ BQ25896 Charger Web Monitor Test ║");
79 Serial.println("╚══════════════════════════════════════════╝");
80 Serial.println("");
81}
82
83void setup()
84{
85 bool rlst;
86
87 Serial.begin(115200);
88
90
91 rlst = bmu.begin(Wire, BQ25896_SLAVE_ADDRESS, PMIC_SDA, PMIC_SCL);
92 if (!rlst) {
93 Serial.println("BQ25896 begin() failed. Check wiring.");
94 while (1) {
95 delay(1000);
96 }
97 }
98
99 Serial.println("BQ25896 initialized successfully");
100
101 // bmu.led().setMode(PmicLedBase::Mode::AUTO); // STAT pin indicates charging status
102 bmu.led().setMode(PmicLedBase::Mode::DISABLE); // DISABLE LED to save power (if STAT pin is not used for indication)
103
104 // Pre-charge current: 64-1024mA, 64mA steps (fuzzy: auto-adjusts to nearest valid value)
105 rlst = bmu.charger().setPreChargeCurrent(256);
106 CHECK_FOR_ERRORS(!rlst);
107 // Fast charge current: 0-3008mA, 64mA steps (fuzzy: auto-adjusts to nearest valid value)
108 rlst = bmu.charger().setFastChargeCurrent(1024);
109 CHECK_FOR_ERRORS(!rlst);
110 // Termination current: 64-1024mA, 64mA steps (fuzzy: auto-adjusts to nearest valid value)
111 rlst = bmu.charger().setTerminationCurrent(64);
112 CHECK_FOR_ERRORS(!rlst);
113 // Charge voltage: 3840-4608mV, 16mV steps (fuzzy: auto-adjusts to nearest valid value)
114 rlst = bmu.charger().setChargeVoltage(4288);
115 CHECK_FOR_ERRORS(!rlst);
116
117 Serial.print("Pre Charge Current: ");
118 Serial.println(bmu.charger().getPreChargeCurrent());
119 Serial.print("Fast Charge Current: ");
120 Serial.println(bmu.charger().getFastChargeCurrent());
121 Serial.print("Termination Current: ");
122 Serial.println(bmu.charger().getTerminationCurrent());
123 Serial.print("Charge Voltage: ");
124 Serial.println(bmu.charger().getChargeVoltage());
125
126 // Input current limit: 100-3008mA, 100mA steps (fuzzy: auto-adjusts to nearest valid value)
128 // Input voltage limit: 3900-14000mV, 100mV steps (fuzzy: auto-adjusts to nearest valid value)
130 // System minimum voltage: 3000-3700mV, 100mV steps (fuzzy: auto-adjusts to nearest valid value)
132
133 Serial.print("Input Current Limit: ");
134 Serial.println(bmu.power().getInputCurrentLimit());
135 Serial.print("Input Voltage Limit: ");
136 Serial.println(bmu.power().getInputVoltageLimit());
137 Serial.print("Minimum System Voltage: ");
138 Serial.println(bmu.power().getMinimumSystemVoltage());
139
140 // Enable ADC channels (VBUS voltage, Battery voltage, VSYS voltage, Charging current, NTC temperature)
142
143 // Disabling ADC can reduce quiescent current.
144 // If call `read` directly after disabling `adc`, it will trigger a single read operation.
145 // bmu.adc().disableChannels(0); // No specific channels to disable, but call for compatibility
146
147 const char *ssid = WIFI_SSID;
148 const char *password = WIFI_PASSWORD;
149 WiFi.begin(ssid, password);
150 while (WiFi.status() != WL_CONNECTED) {
151 delay(500);
152 Serial.print(".");
153 }
154 Serial.println();
155 Serial.print("WiFi connected, IP: ");
156 Serial.println(WiFi.localIP());
157
158 server.on("/boost/on", []() {
159 if (bmu.core().isVbusPresent()) {
160 server.send(400, "text/plain", "ERROR: Remove USB first before enabling boost");
161 return;
162 }
163 bool ret = bmu.power().enableBoost(true);
164 server.send(200, "text/plain", ret ? "OK" : "FAILED");
165 });
166
167 server.on("/boost/off", []() {
168 bool ret = bmu.power().enableBoost(false);
169 server.send(200, "text/plain", ret ? "OK" : "FAILED");
170 });
171
172 server.on("/ship/on", []() {
173 if (bmu.core().isVbusPresent()) {
174 server.send(400, "text/plain", "ERROR: Remove USB power first to enable ship mode");
175 return;
176 }
177 bool ret = bmu.power().enableShipMode(true);
178 server.send(200, "text/plain", ret ? "OK" : "FAILED");
179 });
180
181 server.on("/", []() {
182 char timeStr[32];
183 time_t now = millis() / 1000;
184 int hrs = (now / 3600) % 24;
185 int mins = (now / 60) % 60;
186 int secs = now % 60;
187 sprintf(timeStr, "%02d:%02d:%02d", hrs, mins, secs);
188
189 bool boostEnabled = bmu.power().isBoostEnabled();
190 bool vbusPresent = bmu.core().isVbusPresent();
191
192 String html = "<html><head><meta charset='utf-8'><title>BQ25896 Charger Monitor</title>";
193 html += "<script>";
194 html += "function toggleBoost(enable) {";
195 html += " var xhr = new XMLHttpRequest();";
196 html += " xhr.open('GET', enable ? '/boost/on' : '/boost/off', true);";
197 html += " xhr.onload = function() { if(xhr.status==200) location.reload(); else alert(xhr.responseText); };";
198 html += " xhr.send();";
199 html += "}";
200 html += "function enableShipMode() {";
201 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;";
202 html += " var xhr = new XMLHttpRequest();";
203 html += " xhr.open('GET', '/ship/on', true);";
204 html += " xhr.onload = function() { if(xhr.status==200) { alert('Ship mode enabled! Device will power off.'); location.reload(); } else { alert(xhr.responseText); } };";
205 html += " xhr.send();";
206 html += "}";
207 html += "</script>";
208 html += "</head><body>";
209 html += "<h1>BQ25896 Charger Status</h1>";
210 html += "<p><strong>Last Update: " + String(timeStr) + "</strong></p>";
211
212 html += "<h2>Boost Control</h2>";
213 html += "<p>USB Status: <strong>" + String(vbusPresent ? "Connected" : "Not Connected") + "</strong></p>";
214 html += "<p>Boost Status: <strong>" + String(boostEnabled ? "ON" : "OFF") + "</strong></p>";
215 if (boostEnabled) {
216 html += "<button onclick='toggleBoost(false)' style='background:#f44336;color:white;padding:10px 20px;border:none;cursor:pointer;'>Turn OFF Boost</button>";
217 } else if (vbusPresent) {
218 html += "<button disabled style='background:#ccc;color:#666;padding:10px 20px;border:none;cursor:not-allowed;'>Turn ON Boost (USB Connected)</button>";
219 } else {
220 html += "<button onclick='toggleBoost(true)' style='background:#4CAF50;color:white;padding:10px 20px;border:none;cursor:pointer;'>Turn ON Boost</button>";
221 }
222
223 html += "<h2>Ship Mode (Battery Off)</h2>";
224 html += "<p>Ship mode disconnects the battery and powers off the device.</p>";
225 html += "<p>To exit ship mode, connect USB power.</p>";
226 html += "<button onclick='enableShipMode()' style='background:#FF9800;color:white;padding:10px 20px;border:none;cursor:pointer;'>Enable Ship Mode</button>";
227
228 html += "<h2>Charger Status</h2>";
229 html += "<table border='1' cellpadding='10'>";
230
231 float val;
232 bool ret;
233
235 html += "<tr><td>VBUS Voltage</td><td>" + String(ret ? val : -1) + " mV</td></tr>";
236
238 html += "<tr><td>Battery Voltage</td><td>" + String(ret ? val : -1) + " mV</td></tr>";
239
241 html += "<tr><td>VSYS Voltage</td><td>" + String(ret ? val : -1) + " mV</td></tr>";
242
244 html += "<tr><td>Battery Current</td><td>" + String(ret ? val : -1) + " mA</td></tr>";
245
247 html += "<tr><td>NTC Temperature</td><td>" + String(ret ? val : -1) + " %</td></tr>";
248
249 html += "<tr><td>Charging</td><td>" + String(bmu.charger().isCharging() ? "Yes" : "No") + "</td></tr>";
250
252 html += "<tr><td>Online</td><td>" + String(status.online ? "Yes" : "No") + "</td></tr>";
253 html += "<tr><td>VBUS Present</td><td>" + String(status.vbusPresent ? "Yes" : "No") + "</td></tr>";
254 html += "<tr><td>Charge Done</td><td>" + String(status.chargeDone ? "Yes" : "No") + "</td></tr>";
255 html += "<tr><td>Fault</td><td>" + String(status.fault ? "Yes" : "No") + "</td></tr>";
256 String chargingStatusStr;
257 switch (status.chargingStatus) {
258 case PmicChargerBase::ChargingStatus::NO_CHARGING: chargingStatusStr = "No charging";
259 break;
260 case PmicChargerBase::ChargingStatus::PRE_CHARGE: chargingStatusStr = "Pre-charge";
261 break;
262 case PmicChargerBase::ChargingStatus::FAST_CHARGE: chargingStatusStr = "Fast Charging";
263 break;
264 case PmicChargerBase::ChargingStatus::TERMINATION: chargingStatusStr = "Charge Termination Done";
265 break;
266 default:
267 break;
268 }
269 html += "<tr><td>Charging Status</td><td>" + chargingStatusStr + "</td></tr>";
270
271 html += "<tr><td>Boost Enabled</td><td>" + String(boostEnabled ? "Yes" : "No") + "</td></tr>";
272 html += "<tr><td>Boost Voltage</td><td>" + String(bmu.power().getBoostVoltage()) + " mV</td></tr>";
273
274 html += "<tr><td>ICO Optimized</td><td>" + String(bmu.core().isInputCurrentOptimizerOptimized() ? "Yes" : "No") + "</td></tr>";
275 html += "<tr><td>VINDPM Active</td><td>" + String(bmu.core().isVindpmActive() ? "Yes" : "No") + "</td></tr>";
276 html += "<tr><td>IINDPM Active</td><td>" + String(bmu.core().isIindpmActive() ? "Yes" : "No") + "</td></tr>";
277 html += "<tr><td>VSYS in Regulation</td><td>" + String(bmu.core().isVsysInRegulation() ? "Yes" : "No") + "</td></tr>";
278
279 html += "</table>";
280 html += "<meta http-equiv='refresh' content='1'>";
281 html += "<p>Auto-refresh every 1 second</p>";
282 html += "</body></html>";
283
284 server.send(200, "text/html", html);
285 });
286
287 server.begin();
288 Serial.println("Web server started");
289
290 Serial.println("Setup complete!");
291
292#if PMIC_IRQ != -1
293 pinMode(PMIC_IRQ, INPUT_PULLUP);
294 attachInterrupt(PMIC_IRQ, +[]() {
295 isFaultTrigger = true;
296 }, FALLING);
297#endif
298
299}
300
301void loop()
302{
303
304 server.handleClient();
305 delay(1);
306
307#if PMIC_IRQ != -1
308 if (isFaultTrigger) {
309 isFaultTrigger = false;
311 if (status.fault) {
312 Serial.print("Fault Code: ");
313 Serial.println(status.faultCode);
314 using namespace BQ25896Faults;
315 if (isWatchdogTimeout(status.faultCode)) {
316 Serial.println("\t Watchdog Fault");
317 }
318 if (isBoostFault(status.faultCode)) {
319 Serial.println("\t Boost Mode Fault");
320 }
321 if (isChargeFault(status.faultCode)) {
322 Serial.println("\t Charge Mode Fault");
323 uint8_t type = getChargeFaultType(status.faultCode);
324 if (isChargeInputFault(status.faultCode)) {
325 Serial.println("\t - Input Fault (BUS OVP or VBAT<BUS<3.8V)");
326 }
327 if (isChargeThermalFault(status.faultCode)) {
328 Serial.println("\t - Thermal Shutdown");
329 }
330 if (isChargeTimerFault(status.faultCode)) {
331 Serial.println("\t - Safety Timer Expiration");
332 }
333 }
334 if (isBatteryFault(status.faultCode)) {
335 Serial.println("\t Battery Fault (BATOVP)");
336 }
337 uint8_t ntcFault = getNtcFault(status.faultCode);
338 if (ntcFault) {
339 Serial.println("\t NTC Fault");
340 }
341 }
342 }
343#endif
344}
345#else
346void setup()
347{
348 Serial.begin(115200);
349 Serial.println("This example is only compatible with ESP32. Please run on ESP32 platform.");
350}
351void loop()
352{
353 delay(1000);
354}
355#endif
@license MIT License
void printBanner()
#define PMIC_SDA
#define PMIC_SCL
#define PMIC_IRQ
PmicBQ25896 bmu
#define CHECK_FOR_ERRORS(condition)
bool enableChannels(uint32_t mask) override
Enable one or more ADC channels.
static constexpr uint8_t ADC_CONV_START
ADC control flags.
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 isCharging() override
Check if charging is in progress.
bool setPreChargeCurrent(uint16_t mA) override
Set pre-charge current.
uint16_t getTerminationCurrent() override
Get termination current.
Status getStatus() override
Get charger status.
bool isInputCurrentOptimizerOptimized()
Check if Input Current Optimizer has optimized.
bool isVsysInRegulation()
Check if VSYS is in regulation.
bool isVindpmActive()
Get fault status.
bool isVbusPresent()
Check if VBUS (USB power) is present.
bool isIindpmActive()
Check if IINDPM is active (input current limiting)
bool setMode(Mode mode) override
Set 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.
@ BAT_VOLTAGE
Battery voltage.
@ BAT_TEMPERATURE
Battery temperature.
@ BAT_CURRENT
Battery current.
@ VBUS_VOLTAGE
VBUS voltage.
@ VSYS_VOLTAGE
VSYS voltage.
BQ25896Adc & adc()
BQ25896Core & core()
Get core interface (mutable)
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)
@ DISABLE
LED is disabled (if supported).
bool isChargeThermalFault(uint8_t fault)
bool isChargeFault(uint8_t fault)
uint8_t getNtcFault(uint8_t fault)
uint8_t getChargeFaultType(uint8_t fault)
bool isBoostFault(uint8_t fault)
bool isBatteryFault(uint8_t fault)
bool isWatchdogTimeout(uint8_t fault)
bool isChargeTimerFault(uint8_t fault)
bool isChargeInputFault(uint8_t fault)
Charger status structure.
bool vbusPresent
VBUS detected / good (USB power present)
bool chargeDone
Charge termination/done (battery full)
uint32_t faultCode
Optional raw fault code for diagnostics.
bool fault
Any fault latched/active.
ChargingStatus chargingStatus
Charging status enumeration.
bool online
PMIC reachable / initialized.
volatile bool isFaultTrigger