Finialize battery icon

This commit is contained in:
Thomas Farstrike
2025-06-20 23:41:45 +02:00
parent 77853bc926
commit 4b3faa32dd
2 changed files with 70 additions and 32 deletions
@@ -16,10 +16,47 @@ VREF = 3.3 # Reference voltage (3.3V for most boards, adjust if different)
ADC_MAX = 4095 # 12-bit ADC resolution
VOLTAGE_DIVIDER = 3 # (R1 + R2) / R2 = (200k + 100k) / 100k = 3
MIN_VOLTAGE = 3.7
MAX_VOLTAGE = 4.2
# USB connected, full battery: VBAT 4.179 5V: 5.1
# read_battery_voltage raw_value: 1598.4
# read_battery_voltage raw_value: 1598.1
# read_battery_voltage raw_value: 1596.5
# on display: 1596.8
# => FULL is 1597 at 4.193V so * 2.6255 / 1000
#
# unplugged: VBAT: 4.157 5V: 0
# 1591.3: 4.157 2.6123
# 1588.5: 4.156
# 1580.4: 4.14 2.619
# 1577.8: 4.12
# 1561.2: 4.08 2.61
# 1555: 4.06
# 1505: 3.95 2.624
# 1489: 3.90
# 1470: 3.85 2.61
# 1454: 3.8
# 1445: 3.81
# 1412 should be empty 3.7
#
# USB connected, no battery:
# 1566 * 0.00261 = 4.08V = 75%
# 1566 * 0.00241 = 3.77V = 14%
# 1564-1567
#
# quite empty and charging:
# 1594: 4.18V
# 16..
#
# logically, it should be * 0.00241758241758 but emperically, it seems to be * 0.00261 which is 8% higher
# => Let's go with 0.00262
def read_battery_voltage():
if not have_adc:
import random
return random.randint(370,420) / 100
random_voltage = random.randint(round(MIN_VOLTAGE*100),round(MAX_VOLTAGE*100)) / 100
#print(f"returning random voltage: {random_voltage}")
return random_voltage
# Read raw ADC value
total = 0
# Read multiple times to try to reduce variability.
@@ -27,12 +64,20 @@ def read_battery_voltage():
for _ in range(10):
total = total + adc.read()
raw_value = total / 10
#print(f"read_battery_voltage raw_value: {raw_value}")
# Convert to voltage, accounting for divider and reference
voltage = (raw_value / ADC_MAX) * VREF * VOLTAGE_DIVIDER
#voltage = (raw_value / ADC_MAX) * VREF * VOLTAGE_DIVIDER
voltage = raw_value * 262 / 100000
# Clamp to 04.2V range for LiPo battery
voltage = max(0, min(voltage, 4.2))
voltage = max(0, min(voltage, MAX_VOLTAGE))
#return raw_value
return voltage
# Could be interesting to keep a "rolling average" of the percentage so that it doesn't fluctuate too quickly
def get_battery_percentage():
return (read_battery_voltage() - MIN_VOLTAGE) * 100 / (MAX_VOLTAGE - MIN_VOLTAGE)
# Main loop to read and print battery voltage
if False:
#for _ in range(10):
+22 -29
View File
@@ -16,7 +16,7 @@ NOTIFICATION_BAR_HEIGHT=24
CLOCK_UPDATE_INTERVAL = 1000 # 10 or even 1 ms doesn't seem to change the framerate but 100ms is enough
WIFI_ICON_UPDATE_INTERVAL = 1500
BATTERY_ICON_UPDATE_INTERVAL = 30000
BATTERY_ICON_UPDATE_INTERVAL = 5000
TEMPERATURE_UPDATE_INTERVAL = 2000
MEMFREE_UPDATE_INTERVAL = 5000 # not too frequent because there's a forced gc.collect() to give it a reliable value
@@ -136,15 +136,8 @@ def init_rootscreen():
rootlabel.set_text("Welcome to MicroPythonOS")
rootlabel.center()
timer1 = None
timer2 = None
timer3 = None
timer4 = None
def create_notification_bar():
global notification_bar
global timer1, timer2, timer3, timer4
# Create notification bar
notification_bar = lv.obj(lv.layer_top())
notification_bar.set_size(lv.pct(100), NOTIFICATION_BAR_HEIGHT)
@@ -172,15 +165,16 @@ def create_notification_bar():
#notif_icon.set_text(lv.SYMBOL.BELL)
#notif_icon.align_to(time_label, lv.ALIGN.OUT_RIGHT_MID, PADDING_TINY, 0)
# Battery percentage
battery_label = lv.label(notification_bar)
battery_label.set_text("100%")
battery_label.align(lv.ALIGN.RIGHT_MID, 0, 0)
battery_label.add_flag(lv.obj.FLAG.HIDDEN)
#battery_label = lv.label(notification_bar)
#battery_label.set_text("100%")
#battery_label.align(lv.ALIGN.RIGHT_MID, 0, 0)
#battery_label.add_flag(lv.obj.FLAG.HIDDEN)
# Battery icon
battery_icon = lv.label(notification_bar)
battery_icon.set_text(lv.SYMBOL.BATTERY_FULL)
battery_icon.align_to(battery_label, lv.ALIGN.OUT_LEFT_MID, 0, 0)
battery_icon.add_flag(lv.obj.FLAG.HIDDEN)
#battery_icon.align_to(battery_label, lv.ALIGN.OUT_LEFT_MID, 0, 0)
battery_icon.align(lv.ALIGN.RIGHT_MID, 0, 0)
battery_icon.add_flag(lv.obj.FLAG.HIDDEN) # keep it hidden until it has a correct value
# WiFi icon
wifi_icon = lv.label(notification_bar)
wifi_icon.set_text(lv.SYMBOL.WIFI)
@@ -202,22 +196,21 @@ def create_notification_bar():
print("Warning: could not check WLAN status:", str(e))
def update_battery_icon(timer=None):
volt = mpos.battery_voltage.read_battery_voltage()
percent = (volt - 3.7) * 100 / (4.2 - 3.7)
battery_label.set_text(f"{round(percent)}%")
battery_label.remove_flag(lv.obj.FLAG.HIDDEN)
# 3.7 - 4.15 => 0.5V diff / 3 = 0.015
if volt > 4.15:
percent = mpos.battery_voltage.get_battery_percentage()
if percent > 80: # 4.1V
battery_icon.set_text(lv.SYMBOL.BATTERY_FULL)
elif volt > 4:
elif percent > 60: # 4.0V
battery_icon.set_text(lv.SYMBOL.BATTERY_3)
elif volt > 3.85:
elif percent > 40: # 3.9V
battery_icon.set_text(lv.SYMBOL.BATTERY_2)
elif volt > 3.75:
elif percent > 20: # 3.8V
battery_icon.set_text(lv.SYMBOL.BATTERY_1)
else:
else: # > 3.7V
battery_icon.set_text(lv.SYMBOL.BATTERY_EMPTY)
battery_icon.remove_flag(lv.obj.FLAG.HIDDEN)
# Percentage is not shown for now:
#battery_label.set_text(f"{round(percent)}%")
#battery_label.remove_flag(lv.obj.FLAG.HIDDEN)
update_battery_icon() # run it immediately instead of waiting for the timer
def update_wifi_icon(timer):
@@ -248,11 +241,11 @@ def create_notification_bar():
percentage = round(free * 100 / (free + used))
memfree_label.set_text(f"{percentage}%")
timer1 = lv.timer_create(update_time, CLOCK_UPDATE_INTERVAL, None)
timer2 = lv.timer_create(update_temperature, TEMPERATURE_UPDATE_INTERVAL, None)
timer3 = lv.timer_create(update_memfree, MEMFREE_UPDATE_INTERVAL, None)
timer4 = lv.timer_create(update_wifi_icon, WIFI_ICON_UPDATE_INTERVAL, None)
timer5 = lv.timer_create(update_battery_icon, BATTERY_ICON_UPDATE_INTERVAL, None)
lv.timer_create(update_time, CLOCK_UPDATE_INTERVAL, None)
lv.timer_create(update_temperature, TEMPERATURE_UPDATE_INTERVAL, None)
lv.timer_create(update_memfree, MEMFREE_UPDATE_INTERVAL, None)
lv.timer_create(update_wifi_icon, WIFI_ICON_UPDATE_INTERVAL, None)
lv.timer_create(update_battery_icon, BATTERY_ICON_UPDATE_INTERVAL, None)
# hide bar animation
global hide_bar_animation