Thanks @amirgon. I think you were right with the looping through the buttons. I got it working based on the example here, removing that loop. My code now looks like:
main.py
...
BUTTON_A_PIN = const(18)
BUTTON_B_PIN = const(19)
BUTTON_C_PIN = const(23)
encoder_state = {'left': 0, 'right': 0, 'pressed': False}
def on_press_a(btn):
if btn.pressed:
encoder_state['left'] += 1
print('on_press_a')
def on_press_b(btn):
encoder_state['pressed'] = btn.pressed
print('on_press_b')
def on_press_c(btn):
if btn.pressed:
encoder_state['right'] += 1
print('on_press_c')
def button_read_constr():
def button_read(drv, data):
data.enc_diff = encoder_state['right'] - encoder_state['left']
encoder_state['right'] = 0
encoder_state['left'] = 0
if encoder_state['pressed']:
data.state = lv.INDEV_STATE.PRESSED
encoder_state['pressed'] = False
else:
data.state = lv.INDEV_STATE.RELEASED
# gc.collect()
return False
return button_read
Button(Pin(BUTTON_A_PIN), id=1, key=lv.KEY.UP, user_callback=on_press_a)
Button(Pin(BUTTON_B_PIN), id=2, key=lv.KEY.ENTER, user_callback=on_press_b)
Button(Pin(BUTTON_C_PIN), id=3, key=lv.KEY.DOWN, user_callback=on_press_c)
indev_drv = lv.indev_drv_t()
indev_drv.type = lv.INDEV_TYPE.ENCODER
indev_drv.read_cb = read_button
win_drv = indev_drv.register()
group = lv.group_create()
group.add_obj(dd)
win_drv.set_group(group)
...
utils.py
from input import DigitalInput
class Button:
def __init__(self, pin, id, key, user_callback=None):
self._press = False
self._changed = False
self._id = id
self._key = key
self._user_callback = user_callback
self.setPin(pin)
def _cb(self, pin, press):
if self._press != press:
print("State change [{}] {}->{} [{}]".format(pin, self._press, press, self._key))
self._changed = True
self._press = press
return self._user_callback(self)
@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
@property
def key(self):
return self._key
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)