External ESP32 Display for Laptop Battery Percentage (From BMS)
PART A — PC (Windows) Side : Battery Measurement & Data Export
1. Battery Percentage Technical Meaning
Laptop battery percentage is not derived from voltage or current directly. It is a software-calculated value produced by the Battery Management System (BMS).
2. How the Battery Data Reaches Windows
Battery → BMS → Embedded Controller → CPU → Windows
3. Why External Testers Cannot Be Used
- They conflict with laptop power-path circuits
- They fight the internal BMS
- They produce incorrect results
- They may damage the motherboard
4. Correct PC-Side Architecture
Laptop Battery → BMS → Windows → Digital Output
5. Required PC Software
pip install psutil pyserial flask bleak
6. Windows Battery Reader (Core Module)
import psutil
def get_battery():
b = psutil.sensors_battery()
if not b:
return None
return {
"percent": int(b.percent),
"plugged": int(b.power_plugged)
}
7. USB (Serial) Data Export
import time, serial
from battery import get_battery
ser = serial.Serial("COM5", 115200)
while True:
b = get_battery()
if b:
ser.write(f"BAT={b['percent']};PLUG={b['plugged']}\n".encode())
time.sleep(2)
8. Wi-Fi (HTTP) Data Export
from flask import Flask, jsonify
from battery import get_battery
app = Flask(__name__)
@app.route("/battery")
def battery():
return jsonify(get_battery())
app.run(host="0.0.0.0", port=5000)
9. Bluetooth (BLE) Data Export
- Service UUID: 0x180F
- Characteristic UUID: 0x2A19
10. PC-Side Summary
Windows is the only correct measurement point because it reads data directly from the BMS through ACPI.
PART B — ESP32 Side : Data Reception & External Display
1. ESP32 Role
ESP32 acts only as a receiver and display device. It never measures the battery directly.
2. Accepted Input Format
BAT=87;PLUG=1
3. ESP32 Hardware
- ESP32 Dev Module
- OLED 128×64 (SSD1306)
4. Required ESP32 Libraries
Adafruit SSD1306 Adafruit GFX WiFi HTTPClient ESP32 BLE Arduino ArduinoJson
5. Data Source Priority
- USB Serial
- Wi-Fi HTTP
- Bluetooth BLE
6. ESP32 Display Code (USB + Wi-Fi + BLE)
#include#include #include #include #include #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); #define WIFI_SSID "YOUR_WIFI" #define WIFI_PASS "YOUR_PASS" #define BATTERY_URL "http://WINDOWS_IP:5000/battery" int batteryPercent = -1; bool charging = false; String source = "NONE"; unsigned long lastSerial = 0; #define SERIAL_TIMEOUT 3000 void setup() { Serial.begin(115200); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.setTextColor(SSD1306_WHITE); WiFi.begin(WIFI_SSID, WIFI_PASS); } void readUSB() { if (Serial.available()) { String d = Serial.readStringUntil('\n'); int b = d.indexOf("BAT="); int p = d.indexOf("PLUG="); if (b >= 0 && p >= 0) { batteryPercent = d.substring(b+4, d.indexOf(';')).toInt(); charging = d.substring(p+5).toInt(); source = "USB"; lastSerial = millis(); } } } void readWiFi() { if (millis() - lastSerial < SERIAL_TIMEOUT) return; if (WiFi.status() != WL_CONNECTED) return; HTTPClient http; http.begin(BATTERY_URL); if (http.GET() == 200) { StaticJsonDocument<200> doc; deserializeJson(doc, http.getString()); batteryPercent = doc["percent"]; charging = doc["plugged"]; source = "WiFi"; } http.end(); } void drawUI() { display.clearDisplay(); display.setTextSize(2); display.setCursor(0,0); display.print(batteryPercent); display.print("%"); display.setTextSize(1); display.setCursor(0,28); display.print(charging ? "CHARGING" : "DISCHARGING"); display.setCursor(0,45); display.print("SRC:"); display.print(source); display.display(); } void loop() { readUSB(); readWiFi(); drawUI(); delay(500); }
7. ESP32 Safety Rules
- No battery terminal connection
- No voltage measurement
- No SMBus probing
8. Final Architecture
Laptop Battery → BMS → Windows → USB / Wi-Fi / BLE → ESP32 → Display
9. Final Conclusion
The ESP32 external display must always show battery percentage exported digitally from Windows, instead of measured electrically.
Comments
Post a Comment