ChatGPT: External ESP32 Display for Laptop Battery Percentage (From BMS)

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

  1. USB Serial
  2. Wi-Fi HTTP
  3. 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