SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
sy6970_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 5
56#endif
57
58#ifndef PMIC_SCL
59#define PMIC_SCL 6
60#endif
61
62#ifndef PMIC_IRQ
63#define PMIC_IRQ 21
64#endif
65
66volatile bool isFaultTrigger = false;
67
68WebServer server(80);
69
71
72#define CHECK_FOR_ERRORS(condition) if (condition) {log_e("SY6970 error"); while(1)delay(1000);}
73
74
75void printBanner()
76{
77 Serial.println("");
78 Serial.println("╔══════════════════════════════════════════╗");
79 Serial.println("║ SY6970 Charger Web Monitor Test ║");
80 Serial.println("╚══════════════════════════════════════════╝");
81 Serial.println("");
82}
83
84void setup()
85{
86 bool rlst;
87
88 Serial.begin(115200);
89
91
92 rlst = bmu.begin(Wire, SY6970_SLAVE_ADDRESS, PMIC_SDA, PMIC_SCL);
93 if (!rlst) {
94 Serial.println("SY6970 begin() failed. Check wiring.");
95 while (1) {
96 delay(1000);
97 }
98 }
99
100 Serial.println("SY6970 initialized successfully");
101
102 // bmu.led().setMode(PmicLedBase::Mode::AUTO); // STAT pin indicates charging status
103 bmu.led().setMode(PmicLedBase::Mode::DISABLE); // DISABLE LED to save power (if STAT pin is not used for indication)
104
105 // Pre-charge current: 64-1024mA, 64mA steps (fuzzy: auto-adjusts to nearest valid value)
106 rlst = bmu.charger().setPreChargeCurrent(256);
107 CHECK_FOR_ERRORS(!rlst);
108 // Fast charge current: 0-3008mA, 64mA steps (fuzzy: auto-adjusts to nearest valid value)
109 rlst = bmu.charger().setFastChargeCurrent(1024);
110 CHECK_FOR_ERRORS(!rlst);
111 // Termination current: 64-1024mA, 64mA steps (fuzzy: auto-adjusts to nearest valid value)
112 rlst = bmu.charger().setTerminationCurrent(64);
113 CHECK_FOR_ERRORS(!rlst);
114 // Charge voltage: 3840-4656mV, 16mV steps (fuzzy: auto-adjusts to nearest valid value)
115 rlst = bmu.charger().setChargeVoltage(4288);
116 CHECK_FOR_ERRORS(!rlst);
117
118 Serial.print("Pre Charge Current: ");
119 Serial.println(bmu.charger().getPreChargeCurrent());
120 Serial.print("Fast Charge Current: ");
121 Serial.println(bmu.charger().getFastChargeCurrent());
122 Serial.print("Termination Current: ");
123 Serial.println(bmu.charger().getTerminationCurrent());
124 Serial.print("Charge Voltage: ");
125 Serial.println(bmu.charger().getChargeVoltage());
126
127 // Input current limit: 100-3008mA, 100mA steps (fuzzy: auto-adjusts to nearest valid value)
129 // Input voltage limit: 3900-14000mV, 100mV steps (fuzzy: auto-adjusts to nearest valid value)
131 // System minimum voltage: 3000-3700mV, 100mV steps (fuzzy: auto-adjusts to nearest valid value)
133
134 Serial.print("Input Current Limit: ");
135 Serial.println(bmu.power().getInputCurrentLimit());
136 Serial.print("Input Voltage Limit: ");
137 Serial.println(bmu.power().getInputVoltageLimit());
138 Serial.print("Minimum System Voltage: ");
139 Serial.println(bmu.power().getMinimumSystemVoltage());
140
141 // Enable ADC channels (VBUS voltage, Battery voltage, VSYS voltage, Charging current, NTC temperature)
143
144 // Disabling ADC can reduce quiescent current.
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: Connect 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>SY6970 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>SY6970 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 += "</table>";
275 html += "<meta http-equiv='refresh' content='1'>";
276 html += "<p>Auto-refresh every 1 second</p>";
277 html += "</body></html>";
278
279 server.send(200, "text/html", html);
280 });
281
282 server.begin();
283 Serial.println("Web server started");
284
285 Serial.println("Setup complete!");
286
287#if PMIC_IRQ != -1
288 pinMode(PMIC_IRQ, INPUT_PULLUP);
289 attachInterrupt(PMIC_IRQ, +[]() {
290 isFaultTrigger = true;
291 }, FALLING);
292#endif
293}
294
295void loop()
296{
297 server.handleClient();
298 delay(1);
299
300#if PMIC_IRQ != -1
301 if (isFaultTrigger) {
302 isFaultTrigger = false;
304 if (status.fault) {
305 Serial.print("Fault Code: ");
306 Serial.println(status.faultCode);
307
308 using namespace SY6970Faults;
309 if (isWatchdogTimeout(status.faultCode)) {
310 Serial.println("\t Watchdog Fault");
311 }
312 if (isBoostFault(status.faultCode)) {
313 Serial.println("\t Boost Mode Fault");
314 }
315 if (isChargeFault(status.faultCode)) {
316 Serial.println("\t Charge Mode Fault");
317 if (isChargeInputFault(status.faultCode)) {
318 Serial.println("\t - Input Fault (BUS OVP or VBAT<BUS<3.8V)");
319 }
320 if (isChargeThermalFault(status.faultCode)) {
321 Serial.println("\t - Thermal Shutdown");
322 }
323 if (isChargeTimerFault(status.faultCode)) {
324 Serial.println("\t - Safety Timer Expiration");
325 }
326 }
327 if (isBatteryFault(status.faultCode)) {
328 Serial.println("\t Battery Fault (BATOVP)");
329 }
330 uint8_t ntcFault = getNtcFault(status.faultCode);
331 if (ntcFault) {
332 Serial.println("\t NTC Fault");
333 }
334 }
335 }
336#endif
337}
338#else
339void setup()
340{
341 Serial.begin(115200);
342 Serial.println("This example is only compatible with ESP32. Please run on ESP32 platform.");
343}
344void loop()
345{
346 delay(1000);
347}
348#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.
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 isVbusPresent()
Check if VBUS (USB power) is present.
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).
static constexpr uint8_t ADC_CONV_START
ADC control flags.
Definition SY6970Adc.hpp:78
bool isChargeThermalFault(uint8_t fault)
bool isChargeFault(uint8_t fault)
uint8_t getNtcFault(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