to use the buttons inside lvgl. For this I can simulate an encoder, navigation with a 3 key keypad or link the physical buttons to lvgl objects.
to properly read the state of the physical buttons.
Until recently I firmly believed that to read the button state, one had to use an IRQ+ISR solution. However two things made this approach unuesable:
The ESP32 has issues with IRQs. Sometimes they take time to actualy interrupt if they do, giving a very sluggish feeling to the interface…
The M5Stack’s hardware (or worse, the underlying ESP32) has an issue. If the wifi is turned on, then pin 39, the gpio linked to button A, gets a very short pulse about every second. Perhaps more if wifi is being used rather than merely being active.
My solution, in following lvgl’s philosophy, is to poll the pins associatied with the physical buttons. For that I use the ESP32’s pulse counter hardware through the espidf module exposed by lvgl. I basically count both raising and falling pulses. An odd count means pressed, an even count means depressed. The spurious pulses caused by wifi, just add an even count and are so short that, unless one is incredibly unlucky, one only detects their passing by an increase of 2 of the count register.
Yes I did. I set the filtering parameter to its maximum: 1023 clock cycles (about 13us) and the pulse still exists. However, further testing showed that the pulse is shorter than the time it takes uPy to
read the value of the counter
test if it changed (in order to display something)
loop
I have not tried to see how long it takes uPy to perform that loop. That would give an upper value to the length of the pulse…
Just to show you my testing code. The pcnt counter is set up so that it counts every rising and falling part of a pulse. I would therefore get an odd count if I were in the middle of a pulse.
So roughly a complete pulse every 0.82s. A sightly more complex loop (with a counter counting the number of loops…) shows that in average a complete loop takes about 170us. So, for sure, the pulse has a length somewhere between 13us and 170us.
Another thing: the released state for the button is pin==1, so the pulse is pulling down the signal being read by the pin.
Found an issue that is related with lvgl so i will ask it here.
When I try to use keypad with a lvgl list it doesn’t work, I can’t change items in the list , but if I press ok it will select the standard item). When using to cycle through buttons it works really great!
Any idea on what is wrong?
One possible answer is checking if you are sending the right key event. As far as I can tell, for a list one should send lv.KEY.LEFT, lv.KEY.RIGHT (or UP/DOWN). So when you create the keypad you shoudl write something like:
If you want a behaviour that changes according to what is currently selected, then you will have to subclass KeyPad and overwrite _reader (rather heavy duty) or change the keys sent by having lines like:
tA._key = lv.KEY.PREV
This is dirty: it plays with internals. It really should be done using a setter.I think I shoud add a setter for the key property of the KeyButton object.
You are right!
I was playing with that just now and if I change to LEFT, RIGHT I can now cycle through my list, but if I then try to cycle through buttons I can’t…
I have then tried what you suggested and made tA._key = lv.KEY.PREV when I have Buttons and it works!
The problem is that I have to always be switching from one to the other depending on if I am on a list or on a menu with buttons and I have to hardcode it in each.
It is a shame that the encoder version is not working right of the bat. But this is the second best option for now! If you come up with any other solution for this case let me know.
Thank you!
Alas, I cannot change the encoder behaviour: it is part of lvgl’s way of handling encoders. The thing is that the documentation is a bit unclear on this:
in Porting I see: “By turning the encoder you can focus on the next/previous object.”
in Overview I see: “With an encoder, you should use only LV_KEY_LEFT , LV_KEY_RIGHT , and LV_KEY_ENTER .”
So: previous/next or left/right? From experience it is the former rather than the latter.