diff --git a/components/micropython/vendor/ports/esp32/machine_pin.c b/components/micropython/vendor/ports/esp32/machine_pin.c
index b3c0783c79f2aa62310dc69daff33d61aa06e8c6..89515976e4993d88d00c07f114f33ab4965cf573 100644
--- a/components/micropython/vendor/ports/esp32/machine_pin.c
+++ b/components/micropython/vendor/ports/esp32/machine_pin.c
@@ -155,7 +155,7 @@ STATIC const machine_pin_obj_t machine_pin_obj[GPIO_NUM_MAX] = {
{{&machine_pin_type}, GPIO_NUM_6}, // Badgelink
{{&machine_pin_type}, GPIO_NUM_7}, // Badgelink
{{NULL}, -1}, // 8
- {{NULL}, -1}, // 9
+ {{&machine_pin_type}, GPIO_NUM_9}, // Battery ADC
{{NULL}, -1}, // 10
{{NULL}, -1}, // 11
{{NULL}, -1}, // 12
diff --git a/python_payload/mypystubs/machine.pyi b/python_payload/mypystubs/machine.pyi
index 4e527e1d56f69cdd720f53c286fce2cf5e94a8d6..5f1a7adbde03a02ec785825cb5f408c521cac864 100644
--- a/python_payload/mypystubs/machine.pyi
+++ b/python_payload/mypystubs/machine.pyi
@@ -1,30 +1,36 @@
-try:
- from typing import Protocol
-except ImportError:
- from typing_extensions import Protocol # type: ignore
+from typing import Any
-class Pin(Protocol):
+class Pin:
"""
See the official micropython docs for more details:
https://docs.micropython.org/en/latest/library/machine.Pin.html
"""
- IN: int
- OUT: int
- OPEN_DRAIN: int
- PULL_UP: int
- PULL_DOWN: int
- IRQ_RISING: int = 1
- IRQ_FALLING: int = 2
- WAKE_LOW: int
- WAKE_HIGH: int
- DRIVE_0: int
- DRIVE_1: int
- DRIVE_2: int
- DRIVE_3: int
+ IN: int = 1
+ OUT: int = 2
+ OPEN_DRAIN: int = 3
+ PULL_UP: int = 4
+ PULL_DOWN: int = 5
+ IRQ_RISING: int = 6
+ IRQ_FALLING: int = 7
+ WAKE_LOW: int = 8
+ WAKE_HIGH: int = 9
+ DRIVE_0: int = 10
+ DRIVE_1: int = 11
+ DRIVE_2: int = 12
+ DRIVE_3: int = 13
- def __init__(self, id, mode=-1, pull=-1, *, value=None, drive=0, alt=-1):
+ def __init__(
+ self,
+ id: int,
+ mode: int = -1,
+ pull: int = -1,
+ *,
+ value: Any = None,
+ drive: int = 0,
+ alt: int = -1
+ ) -> None:
"""
Available pins for the flow3r badge are:
@@ -35,17 +41,30 @@ class Pin(Protocol):
* 17 (QWIIC SDA)
* 45 (QWIIC SCL)
"""
- def init(self, mode=-1, pull=-1, *, value=None, drive=0, alt=-1): ...
- def value(self, x=None): ...
- def __call__(self, x=None): ...
- def on(self): ...
- def off(self): ...
+ def init(
+ self,
+ mode: int = -1,
+ pull: int = -1,
+ *,
+ value: Any = None,
+ drive: int = 0,
+ alt: int = -1
+ ) -> None: ...
+ def value(self, x: Any = None) -> int: ...
+ def __call__(self, x: Any = None) -> None: ...
+ def on(self) -> None: ...
+ def off(self) -> None: ...
def irq(
self,
- handler=None,
- trigger=IRQ_FALLING | IRQ_RISING,
+ handler: Any = None,
+ trigger: Any = IRQ_FALLING | IRQ_RISING,
*,
- priority=1,
- wake=None,
- hard=False
- ): ...
+ priority: int = 1,
+ wake: Any = None,
+ hard: bool = False
+ ) -> None: ...
+
+class ADC:
+ ATTN_11DB: int = 1
+ def __init__(self, p: Pin, atten: int = 0): ...
+ def read_uv(self) -> float: ...
diff --git a/python_payload/st3m/input.py b/python_payload/st3m/input.py
index 17f6b78cd8da60dab38f5b8f1b9f723c92b87372..06a2660073e8cdfe210ac078097bc76669342b6e 100644
--- a/python_payload/st3m/input.py
+++ b/python_payload/st3m/input.py
@@ -4,7 +4,7 @@ import hardware
import captouch
import imu
-import math
+import machine
class InputState:
@@ -458,6 +458,24 @@ class IMUState:
self.pressure, self.temperature = imu.pressure_read()
+class PowerState:
+ __slots__ = ("_ts", "_adc_pin", "_adc", "battery_voltage")
+
+ def __init__(self) -> None:
+ self._adc_pin = machine.Pin(9, machine.Pin.IN)
+ self._adc = machine.ADC(self._adc_pin, atten=machine.ADC.ATTN_11DB)
+ self.battery_voltage = self._battery_voltage_sample()
+ self._ts = 0
+
+ def _battery_voltage_sample(self) -> float:
+ return self._adc.read_uv() * 2 / 1e6
+
+ def _update(self, ts: int, hr: InputState) -> None:
+ if ts >= self._ts + 1000:
+ self.battery_voltage = self._battery_voltage_sample()
+ self._ts = ts
+
+
class InputController:
"""
A stateful input controller. It accepts InputState updates from the Reactor
@@ -475,6 +493,7 @@ class InputController:
"left_shoulder",
"right_shoulder",
"imu",
+ "power",
"_ts",
)
@@ -483,6 +502,7 @@ class InputController:
self.left_shoulder = TriSwitchState(TriSwitchHandedness.left)
self.right_shoulder = TriSwitchState(TriSwitchHandedness.right)
self.imu = IMUState()
+ self.power = PowerState()
self._ts = 0
def think(self, hr: InputState, delta_ms: int) -> None:
@@ -491,6 +511,7 @@ class InputController:
self.left_shoulder._update(self._ts, hr)
self.right_shoulder._update(self._ts, hr)
self.imu._update(self._ts, hr)
+ self.power._update(self._ts, hr)
def _ignore_pressed(self) -> None:
"""
diff --git a/sim/fakes/machine.py b/sim/fakes/machine.py
new file mode 100644
index 0000000000000000000000000000000000000000..77b2272a1ec254b6a7f5da0b15f3140fb3c47edd
--- /dev/null
+++ b/sim/fakes/machine.py
@@ -0,0 +1,16 @@
+class Pin:
+ IN = None
+
+ def __init__(self, _1, _2):
+ pass
+
+
+class ADC:
+ ATTN_11DB = None
+
+ def __init__(self, _1, atten):
+ pass
+
+ def read_uv(self):
+ # A half full battery as seen by the ADC
+ return 3.8e6 / 2