|
@@ -3,6 +3,59 @@
|
3
|
3
|
import uasyncio as asyncio
|
4
|
4
|
import io
|
5
|
5
|
import sys
|
|
6
|
+import machine
|
|
7
|
+import os
|
|
8
|
+import gc
|
|
9
|
+import time
|
|
10
|
+
|
|
11
|
+# https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/pico_lipo_shim/battery_pico.py
|
|
12
|
+# https://github.com/pimoroni/enviro/pull/146
|
|
13
|
+# TODO https://github.com/micropython/micropython/issues/11185
|
|
14
|
+
|
|
15
|
+full_battery = 4.2
|
|
16
|
+empty_battery = 3.2
|
|
17
|
+
|
|
18
|
+charging = machine.Pin("WL_GPIO2", machine.Pin.IN)
|
|
19
|
+conversion_factor = 3 * 3.3 / 65535
|
|
20
|
+cachedVoltage = None
|
|
21
|
+lastCaching = time.time()
|
|
22
|
+
|
|
23
|
+def set_pad(gpio, value):
|
|
24
|
+ machine.mem32[0x4001c000 | (4 + (4 * gpio))] = value
|
|
25
|
+
|
|
26
|
+def get_pad(gpio):
|
|
27
|
+ return machine.mem32[0x4001c000 | (4 + (4 * gpio))]
|
|
28
|
+
|
|
29
|
+def batteryVoltageRead():
|
|
30
|
+ vsys = machine.ADC(3)
|
|
31
|
+ voltage = vsys.read_u16() * conversion_factor
|
|
32
|
+ return voltage
|
|
33
|
+
|
|
34
|
+def batteryVoltageAverage():
|
|
35
|
+ old_pad = get_pad(29)
|
|
36
|
+ set_pad(29, 128) # no pulls, no output, no input
|
|
37
|
+
|
|
38
|
+ sample_count = 10
|
|
39
|
+ voltage = 0
|
|
40
|
+ for i in range(0, sample_count):
|
|
41
|
+ voltage += batteryVoltageRead()
|
|
42
|
+ voltage /= sample_count
|
|
43
|
+
|
|
44
|
+ set_pad(29, old_pad)
|
|
45
|
+ return voltage
|
|
46
|
+
|
|
47
|
+def batteryVoltage():
|
|
48
|
+ global cachedVoltage, lastCaching
|
|
49
|
+
|
|
50
|
+ if ((time.time() - lastCaching) >= 2) or (cachedVoltage == None):
|
|
51
|
+ lastCaching = time.time()
|
|
52
|
+ cachedVoltage = batteryVoltageAverage()
|
|
53
|
+
|
|
54
|
+ percentage = 100.0 * ((cachedVoltage - empty_battery) / (full_battery - empty_battery))
|
|
55
|
+ if percentage > 100.0:
|
|
56
|
+ percentage = 100.0
|
|
57
|
+
|
|
58
|
+ return cachedVoltage, percentage
|
6
|
59
|
|
7
|
60
|
class States:
|
8
|
61
|
def __init__(self, lcd):
|
|
@@ -16,7 +69,19 @@ class States:
|
16
|
69
|
async def draw(self):
|
17
|
70
|
self.lcd.fill(self.lcd.black)
|
18
|
71
|
self.lcd.text("Volcano Remote Control App", 0, 0, self.lcd.green)
|
|
72
|
+
|
19
|
73
|
r = await self.states[self.current].draw()
|
|
74
|
+
|
|
75
|
+ voltage, percentage = batteryVoltage()
|
|
76
|
+ s = "Charging ({:.2f}V)".format(voltage)
|
|
77
|
+ c = self.lcd.green
|
|
78
|
+ if charging.value() != 1:
|
|
79
|
+ s = "{:.0f}% ({:.2f}V)".format(percentage, voltage)
|
|
80
|
+ c = self.lcd.white
|
|
81
|
+ if percentage <= 20:
|
|
82
|
+ c = self.lcd.red
|
|
83
|
+ self.lcd.text("Battery: {}".format(s), 0, self.lcd.height - 10, c)
|
|
84
|
+
|
20
|
85
|
self.lcd.show()
|
21
|
86
|
return r
|
22
|
87
|
|
|
@@ -90,15 +155,28 @@ lcd = LCD()
|
90
|
155
|
|
91
|
156
|
# splash screen
|
92
|
157
|
lcd.fill(lcd.black)
|
93
|
|
-lcd.textC("S&B Volcano Remote", int(lcd.width / 2), int(lcd.height / 2) - 25, lcd.green)
|
94
|
|
-lcd.textC("by xythobuz", int(lcd.width / 2), int(lcd.height / 2), lcd.yellow)
|
95
|
|
-lcd.textC("Initializing...", int(lcd.width / 2), int(lcd.height / 2) + 25, lcd.white)
|
|
158
|
+lcd.textC("S&B Volcano Remote", int(lcd.width / 2), 10, lcd.green)
|
|
159
|
+lcd.textC("by xythobuz", int(lcd.width / 2), 20, lcd.yellow)
|
|
160
|
+lcd.textC("Initializing...", int(lcd.width / 2), 30, lcd.white)
|
|
161
|
+lcd.textC(os.uname()[0][ 0 : 30], int(lcd.width / 2), lcd.height - 50, lcd.green)
|
|
162
|
+lcd.textC(os.uname()[3][ 0 : 30], int(lcd.width / 2), lcd.height - 40, lcd.yellow)
|
|
163
|
+lcd.textC(os.uname()[3][30 : 60], int(lcd.width / 2), lcd.height - 30, lcd.yellow)
|
|
164
|
+lcd.textC(os.uname()[4][ 0 : 30], int(lcd.width / 2), lcd.height - 20, lcd.white)
|
|
165
|
+lcd.textC(os.uname()[4][30 : 60], int(lcd.width / 2), lcd.height - 10, lcd.white)
|
96
|
166
|
lcd.show()
|
97
|
167
|
lcd.brightness(1.0)
|
98
|
168
|
|
|
169
|
+# bootloader access with face buttons
|
|
170
|
+keys = lcd.buttons()
|
|
171
|
+if keys.once("a") and keys.once("b"):
|
|
172
|
+ machine.bootloader()
|
|
173
|
+
|
99
|
174
|
try:
|
100
|
175
|
state_machine(lcd)
|
101
|
176
|
except Exception as e:
|
|
177
|
+ sys.print_exception(e)
|
|
178
|
+
|
|
179
|
+ gc.collect()
|
102
|
180
|
os = io.StringIO()
|
103
|
181
|
sys.print_exception(e, os)
|
104
|
182
|
s = os.getvalue()
|
|
@@ -107,4 +185,5 @@ except Exception as e:
|
107
|
185
|
lcd.fill(lcd.black)
|
108
|
186
|
lcd.textBlock(s, lcd.white)
|
109
|
187
|
lcd.show()
|
|
188
|
+
|
110
|
189
|
raise e
|