Files
mcp_screen/battery_util.py
T

71 lines
2.4 KiB
Python

from machine import ADC, Pin
class BatteryMonitor:
"""Utility class for monitoring battery voltage and capacity on ESP32-S3-RLCD-4.2."""
def __init__(self, pin_num=4):
# Initialize ADC on GPIO 4 with 11dB attenuation
self.adc = ADC(Pin(pin_num))
self.adc.atten(ADC.ATTN_11DB)
def read_voltage(self):
"""Reads the battery voltage in Volts using internal calibration.
Returns:
float: Battery voltage in Volts (e.g. 4.15) or None on error.
"""
try:
# Try calibrated reading in microvolts first
uv = self.adc.read_uv()
# 3x voltage divider onboard scales 3.0V-4.2V battery to 1.0V-1.4V
voltage = (uv / 1_000_000.0) * 3.0
return round(voltage, 3)
except AttributeError:
# Fallback if read_uv() is not supported on older MicroPython builds
try:
# Read 12-bit value (0-4095)
raw = self.adc.read()
# 3.3V reference at 11dB attenuation, 3x divider
voltage = (raw / 4095.0) * 3.3 * 3.0
return round(voltage, 3)
except Exception as e:
print(f"Error reading battery raw ADC: {e}")
return None
except Exception as e:
print(f"Error reading battery calibrated ADC: {e}")
return None
def read_percentage(self):
"""Computes approximate battery percentage based on discharge curve.
Assumes linear approximation between 3.0V (0%) and 4.2V (100%).
Returns:
int: Percentage between 0 and 100.
"""
voltage = self.read_voltage()
if voltage is None:
return 0
# Bound typical lithium-ion limits
# 3.0V is typically empty for ESP32 systems where the LDO drops out around 3.3V
v_min = 3.0
v_max = 4.2
if voltage <= v_min:
return 0
if voltage >= v_max:
return 100
# Linear scaling
pct = (voltage - v_min) / (v_max - v_min) * 100.0
return int(pct)
def get_status_summary(self):
"""Returns a string description of battery status."""
v = self.read_voltage()
p = self.read_percentage()
if v is None:
return "Battery: Error"
return f"Battery: {v:.2f}V ({p}%)"