From d772cdb7e585ce2576b3a2069a994d50338293ad Mon Sep 17 00:00:00 2001 From: Amin Date: Tue, 7 Jul 2026 11:41:49 -0400 Subject: [PATCH] unit: Add SimpleDualButtonUnit for callback-free polling Add SimpleButton class and SimpleDualButtonUnit factory that wrap machine.Pin directly, providing simple polling methods (value, is_active, was_pressed, was_released) without requiring tick() or callbacks. The existing DualButtonUnit is unchanged. Co-authored-by: Cursor --- .../dualbutton/dual_button_core_example.py | 41 +++++++++++-------- m5stack/libs/unit/__init__.py | 1 + m5stack/libs/unit/dual_button.py | 39 ++++++++++++++++++ 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/examples/unit/dualbutton/dual_button_core_example.py b/examples/unit/dualbutton/dual_button_core_example.py index c80a5516..e1951f01 100644 --- a/examples/unit/dualbutton/dual_button_core_example.py +++ b/examples/unit/dualbutton/dual_button_core_example.py @@ -1,35 +1,44 @@ import os, sys, io import M5 from M5 import * -from unit import DualButtonUnit +from unit import SimpleDualButtonUnit +import time -dual_button_0_blue = None -dual_button_0_red = None - - -def dual_button_0_blue_wasClicked_event(state): # noqa: N802 - global dual_button_0_blue, dual_button_0_red - print(dual_button_0_blue.isHolding()) +blue = None +red = None def setup(): - global dual_button_0_blue, dual_button_0_red + global blue, red M5.begin() Widgets.fillScreen(0x222222) - dual_button_0_blue, dual_button_0_red = DualButtonUnit((36, 26)) - dual_button_0_blue.setCallback( - type=dual_button_0_blue.CB_TYPE.WAS_CLICKED, cb=dual_button_0_blue_wasClicked_event - ) - print(dual_button_0_blue.isHolding()) + blue, red = SimpleDualButtonUnit((36, 26)) def loop(): - global dual_button_0_blue, dual_button_0_red + global blue, red M5.update() - dual_button_0_blue.tick(None) + blue.update() + red.update() + + if blue.is_active(): + print("blue held down") + if blue.was_pressed(): + print("blue just pressed") + if blue.was_released(): + print("blue just released") + + if red.is_active(): + print("red held down") + if red.was_pressed(): + print("red just pressed") + if red.was_released(): + print("red just released") + + time.sleep(0.05) if __name__ == "__main__": diff --git a/m5stack/libs/unit/__init__.py b/m5stack/libs/unit/__init__.py index 53034afd..cee92da5 100644 --- a/m5stack/libs/unit/__init__.py +++ b/m5stack/libs/unit/__init__.py @@ -39,6 +39,7 @@ "DLightUnit": "dlight", "DMX512Unit": "dmx", "DualButtonUnit": "dual_button", + "SimpleDualButtonUnit": "dual_button", "EarthUnit": "earth", "EncoderUnit": "encoder", "Encoder8Unit": "encoder8", diff --git a/m5stack/libs/unit/dual_button.py b/m5stack/libs/unit/dual_button.py index d6bb0ce8..830e51e6 100644 --- a/m5stack/libs/unit/dual_button.py +++ b/m5stack/libs/unit/dual_button.py @@ -2,7 +2,46 @@ # # SPDX-License-Identifier: MIT from hardware import Button +from machine import Pin def DualButtonUnit(port): # noqa: N802 return Button(port[0]), Button(port[1]) + + +class SimpleButton: + def __init__(self, pin_num, active_low=True): + self._pin = Pin(pin_num, Pin.IN, Pin.PULL_UP) + self._active_low = active_low + self._prev_active = False + self._was_pressed = False + self._was_released = False + + def value(self): + """Raw pin value: 0 or 1.""" + return self._pin.value() + + def is_active(self): + """True when button is physically pressed (accounts for active_low).""" + if self._active_low: + return self._pin.value() == 0 + return self._pin.value() == 1 + + def update(self): + """Call once per loop iteration to enable edge detection.""" + active = self.is_active() + self._was_pressed = active and not self._prev_active + self._was_released = not active and self._prev_active + self._prev_active = active + + def was_pressed(self): + """True once on the loop tick when button transitions from released to pressed.""" + return self._was_pressed + + def was_released(self): + """True once on the loop tick when button transitions from pressed to released.""" + return self._was_released + + +def SimpleDualButtonUnit(port, active_low=True): # noqa: N802 + return SimpleButton(port[0], active_low), SimpleButton(port[1], active_low)