What I want to do
Une one of the physical buttons of my M5Stack to simulate a click on a logical button on the screen
My setup
A MStack running the latest micropython with lvgl bindings (I included the modification described in https://forum.lvgl.io/t/hardware-button-multiple-points/1953/7)
What happens
If I use an Encoder input device, my button indeed recieves the verious events and behaves as expected. If I turn to the Button encoder device, nothing happens.
My code
import lvgl as lv
import lvesp32
from ili9341 import ili9341
from input import DigitalInput
from micropython import schedule, const, alloc_emergency_exception_buf
from machine import Pin
alloc_emergency_exception_buf(150)
BUTTON_A_PIN = const(39)
BUTTON_B_PIN = const(38)
BUTTON_C_PIN = const(37)
# Physical button class
class BoutonPhy(object):
def __init__(self, pin, id=0):
self._press = False
self._changed = False
self._id = id
self.setPin(pin)
def _cb(self, pin, press):
if self._press != press:
print("State change [{}] {}->{}".format(pin, self._press, press))
self._changed = True
self._press = press
@property
def pressed(self):
return self._press
@property
def changed(self):
ch = self._changed
self._changed = False
return ch
@property
def id(self):
return self._id
def setPin(self, pin):
# DigitalIput : the class that monitors/debounces pin. Uses an irq internally
# see : https://github.com/tuupola/micropython-m5stack/blob/master/firmware/lib/input.py
# Can be replaced with an explicit irq on the pin object.
self._input = DigitalInput(pin, self._cb)
# Constructs the button reader
def buttonReadConstr(but):
def button_read(drv, data):
press = but.pressed
if press:
data.state = lv.INDEV_STATE.PR
else:
data.state = lv.INDEV_STATE.REL
data.btn_id = but.id
if but.changed:
print("Button read [{}] ({}) state: {}, id:{}".format(but,drv,data.state, data.btn_id))
return False
return button_read
# Dummy event handler
def eventHandler(obj, event):
print("Event handler [{}] event: {}".format(obj, event))
# M5Stack screen
disp = ili9341(miso=19, mosi=23, clk=18, cs=14, dc=27, rst=33, backlight=32,power=-1,power_on=-1, backlight_on=1,
mhz=40, factor=4, hybrid=True, width=320, height=240,
colormode=ili9341.COLOR_MODE_BGR, rot=ili9341.MADCTL_ML, invert=False, double_buffer=False)
# I want button A to click on the button in the center of the screen
# Stting up button A
boutonA = BoutonPhy(Pin(BUTTON_A_PIN), id=1)
button_readA = buttonReadConstr(boutonA)
# Setting up the screen
scr = lv.obj()
bout = lv.btn(scr)
bout.align(None, lv.ALIGN.CENTER,0,0)
lab = lv.label(bout)
lab.set_text("Test")
bout.set_event_cb(eventHandler)
lv.scr_load(scr)
# Setting up the input device
indev_drv = lv.indev_drv_t()
lv.indev_drv_init(indev_drv)
indev_drv.type = lv.INDEV_TYPE.BUTTON
indev_drv.read_cb = button_readA
# Screen center (160,120) right above the centered button bout.
point = lv.point_t()
point.x = 160
point.y = 120
win_drv = lv.indev_drv_register(indev_drv)
lv.indev_set_button_points(win_drv, [point])
With this code, I get messages showing the button is pressed/released, but the event handler is not called.
If I replace indev_drv.type = lv.INDEV_TYPE.BUTTON
with indev_drv.type = lv.INDEV_TYPE.ENCODER
and add
group = lv.group_create()
lv.group_add_obj(group, bout)
lv.indev_set_group(win_drv, group)
at the end of the script, the logical button is focused (and I get a message to that effect from the event handler) and clicks are transmitted: I get messages from the message handler…