Skip to content

Commit 51716d3

Browse files
update battery voltage icon
1 parent 6b1709a commit 51716d3

File tree

3 files changed

+68
-11
lines changed

3 files changed

+68
-11
lines changed

internal_filesystem/builtin/system/button.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ def on_long_press(t): # Callback for when long press duration is reached.
3434
else:
3535
is_pressed = False
3636

37-
3837
def button_handler(pin):
3938
"""Interrupt handler for button press and release."""
4039
global press_start_time, is_pressed, timer
@@ -49,7 +48,6 @@ def button_handler(pin):
4948
timer.deinit() # Cancel timer if button is released early
5049
is_pressed = False
5150

52-
5351
# Set up interrupt for both falling (press) and rising (release) edges
5452
button.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=button_handler)
5553

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
have_adc=True
2+
try:
3+
from machine import ADC, Pin
4+
# Configure ADC on pin 5 (IO5 / BAT_ADC)
5+
adc = ADC(Pin(5))
6+
# Set ADC to 11dB attenuation for 0–3.3V range (common for ESP32)
7+
adc.atten(ADC.ATTN_11DB)
8+
except Exception as e:
9+
print("Info: this platform has no ADC for measuring battery voltage")
10+
have_adc=False
11+
12+
import time
13+
14+
# ADC parameters
15+
VREF = 3.3 # Reference voltage (3.3V for most boards, adjust if different)
16+
ADC_MAX = 4095 # 12-bit ADC resolution
17+
VOLTAGE_DIVIDER = 3 # (R1 + R2) / R2 = (200k + 100k) / 100k = 3
18+
19+
def read_battery_voltage():
20+
if not have_adc:
21+
import random
22+
return random.randint(370,420) / 100
23+
# Read raw ADC value
24+
raw_value = adc.read()
25+
# Convert to voltage, accounting for divider and reference
26+
voltage = (raw_value / ADC_MAX) * VREF * VOLTAGE_DIVIDER
27+
# Clamp to 0–4.2V range for LiPo battery
28+
voltage = max(0, min(voltage, 4.2))
29+
return voltage
30+
31+
# Main loop to read and print battery voltage
32+
while False: # for testing
33+
battery_voltage = read_battery_voltage()
34+
print("Battery Voltage: {:.2f} V".format(battery_voltage))
35+
time.sleep(1) # Wait 1 second

internal_filesystem/lib/mpos/ui/__init__.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import lvgl as lv
44
import mpos.apps
5+
import mpos.battery_voltage
56
import mpos.wifi
67
from mpos.ui.anim import WidgetAnimator
78

@@ -15,6 +16,7 @@
1516

1617
CLOCK_UPDATE_INTERVAL = 1000 # 10 or even 1 ms doesn't seem to change the framerate but 100ms is enough
1718
WIFI_ICON_UPDATE_INTERVAL = 1500
19+
BATTERY_ICON_UPDATE_INTERVAL = 30000
1820
TEMPERATURE_UPDATE_INTERVAL = 2000
1921
MEMFREE_UPDATE_INTERVAL = 5000 # not too frequent because there's a forced gc.collect() to give it a reliable value
2022

@@ -157,10 +159,10 @@ def create_notification_bar():
157159
time_label.align(lv.ALIGN.LEFT_MID, 0, 0)
158160
temp_label = lv.label(notification_bar)
159161
temp_label.set_text("00°C")
160-
temp_label.align_to(time_label, lv.ALIGN.OUT_RIGHT_MID, NOTIFICATION_BAR_HEIGHT , 0)
162+
temp_label.align_to(time_label, lv.ALIGN.OUT_RIGHT_MID, mpos.ui.pct_of_display_width(7) , 0)
161163
memfree_label = lv.label(notification_bar)
162164
memfree_label.set_text("")
163-
memfree_label.align_to(temp_label, lv.ALIGN.OUT_RIGHT_MID, NOTIFICATION_BAR_HEIGHT, 0)
165+
memfree_label.align_to(temp_label, lv.ALIGN.OUT_RIGHT_MID, mpos.ui.pct_of_display_width(7), 0)
164166
#style = lv.style_t()
165167
#style.init()
166168
#style.set_text_font(lv.font_montserrat_8) # tiny font
@@ -169,19 +171,21 @@ def create_notification_bar():
169171
#notif_icon = lv.label(notification_bar)
170172
#notif_icon.set_text(lv.SYMBOL.BELL)
171173
#notif_icon.align_to(time_label, lv.ALIGN.OUT_RIGHT_MID, PADDING_TINY, 0)
174+
# Battery percentage
175+
battery_label = lv.label(notification_bar)
176+
battery_label.set_text("100%")
177+
battery_label.align(lv.ALIGN.RIGHT_MID, 0, 0)
178+
battery_label.add_flag(lv.obj.FLAG.HIDDEN)
172179
# Battery icon
173180
battery_icon = lv.label(notification_bar)
174181
battery_icon.set_text(lv.SYMBOL.BATTERY_FULL)
175-
battery_icon.align(lv.ALIGN.RIGHT_MID, 0, 0)
182+
battery_icon.align_to(battery_label, lv.ALIGN.OUT_LEFT_MID, 0, 0)
183+
battery_icon.add_flag(lv.obj.FLAG.HIDDEN)
176184
# WiFi icon
177185
wifi_icon = lv.label(notification_bar)
178186
wifi_icon.set_text(lv.SYMBOL.WIFI)
179-
wifi_icon.align_to(battery_icon, lv.ALIGN.OUT_LEFT_MID, -NOTIFICATION_BAR_HEIGHT, 0)
187+
wifi_icon.align_to(battery_icon, lv.ALIGN.OUT_LEFT_MID, -mpos.ui.pct_of_display_width(7), 0)
180188
wifi_icon.add_flag(lv.obj.FLAG.HIDDEN)
181-
# Battery percentage - not shown to conserve space
182-
#battery_label = lv.label(notification_bar)
183-
#battery_label.set_text("100%")
184-
#battery_label.align(lv.ALIGN.RIGHT_MID, 0, 0)
185189
# Update time
186190
import time
187191
def update_time(timer):
@@ -197,6 +201,25 @@ def update_time(timer):
197201
except Exception as e:
198202
print("Warning: could not check WLAN status:", str(e))
199203

204+
def update_battery_icon(timer=None):
205+
volt = mpos.battery_voltage.read_battery_voltage()
206+
percent = (volt - 3.7) * 100 / (4.2 - 3.7)
207+
battery_label.set_text(f"{round(percent)}%")
208+
battery_label.remove_flag(lv.obj.FLAG.HIDDEN)
209+
# 3.7 - 4.15 => 0.5V diff / 3 = 0.015
210+
if volt > 4.15:
211+
battery_icon.set_text(lv.SYMBOL.BATTERY_FULL)
212+
elif volt > 4:
213+
battery_icon.set_text(lv.SYMBOL.BATTERY_3)
214+
elif volt > 3.85:
215+
battery_icon.set_text(lv.SYMBOL.BATTERY_2)
216+
elif volt > 3.75:
217+
battery_icon.set_text(lv.SYMBOL.BATTERY_1)
218+
else:
219+
battery_icon.set_text(lv.SYMBOL.BATTERY_EMPTY)
220+
battery_icon.remove_flag(lv.obj.FLAG.HIDDEN)
221+
update_battery_icon() # run it immediately instead of waiting for the timer
222+
200223
def update_wifi_icon(timer):
201224
if mpos.wifi.WifiService.is_connected():
202225
wifi_icon.remove_flag(lv.obj.FLAG.HIDDEN)
@@ -229,6 +252,7 @@ def update_memfree(timer):
229252
timer2 = lv.timer_create(update_temperature, TEMPERATURE_UPDATE_INTERVAL, None)
230253
timer3 = lv.timer_create(update_memfree, MEMFREE_UPDATE_INTERVAL, None)
231254
timer4 = lv.timer_create(update_wifi_icon, WIFI_ICON_UPDATE_INTERVAL, None)
255+
timer5 = lv.timer_create(update_battery_icon, BATTERY_ICON_UPDATE_INTERVAL, None)
232256

233257
# hide bar animation
234258
global hide_bar_animation
@@ -371,7 +395,7 @@ def poweroff_cb(e):
371395
import machine
372396
# DON'T configure BOOT button (Pin 0) as wake-up source because it wakes up immediately.
373397
# Luckily, the RESET button can be used to wake it up.
374-
#wake_pin = Pin(0, machine.Pin.IN, machine.Pin.PULL_UP) # Pull-up enabled, active low
398+
#wake_pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP) # Pull-up enabled, active low
375399
#import esp32
376400
#esp32.wake_on_ext0(pin=wake_pin, level=esp32.WAKEUP_ALL_LOW)
377401
print("Entering deep sleep. Press BOOT button to wake up.")

0 commit comments

Comments
 (0)