From 4b3faa32dde01e60a96de6d05894bf66e7f979c2 Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Fri, 20 Jun 2025 23:41:45 +0200 Subject: [PATCH] Finialize battery icon --- .../lib/mpos/battery_voltage.py | 51 +++++++++++++++++-- internal_filesystem/lib/mpos/ui/__init__.py | 51 ++++++++----------- 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/internal_filesystem/lib/mpos/battery_voltage.py b/internal_filesystem/lib/mpos/battery_voltage.py index bcc7d6d3..2412d6b9 100644 --- a/internal_filesystem/lib/mpos/battery_voltage.py +++ b/internal_filesystem/lib/mpos/battery_voltage.py @@ -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 0–4.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): diff --git a/internal_filesystem/lib/mpos/ui/__init__.py b/internal_filesystem/lib/mpos/ui/__init__.py index 6e4a5e00..4e011942 100644 --- a/internal_filesystem/lib/mpos/ui/__init__.py +++ b/internal_filesystem/lib/mpos/ui/__init__.py @@ -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