I have a project in which I control a display using an Arduino Due microcontroller.
The user can navigate on the TFT display (RA8875 driver ic) with a rotary enconder/pushbutton. The display shows a certain menu. You can the selected item in the menu by rotating the rotary encoder and you can move into a submenu by pressing the rotary encoder (because it is also a button). This is how the menu looks like:
The problem is that sometimes when rotating the encoder the menu doesn't refresh the screen properly and seems to have gotten stuck while drawing the screen. Though when rotating the encoder some more the screen gets properly rendered so the code isn't actually 'stuck'. This is een example of a bad rendering after rotating the encoder. (Sometimes no text gets written, sometimes some text gets written):
I also made a video to make my problem more clear: Video with rendering problem.
The code for my menu is rather big so I'll try to explain the working principle and attach the used Arduino code.
I attached an interrupt to the encoder signal and to the push button.
attachInterrupt(digitalPinToInterrupt(BTN_ROT), push_button_interrupt, FALLING); attachInterrupt(digitalPinToInterrupt(ROT_A), rotary_enc_int, LOW);
In the interrupt function I update a 'virtual position' value. In my main loop I run a function that checks if the virtual position is different from the last seen position and updates the 'current_index'-value of the menu accordingly. It also sets 'refresh_menu' to True. In the main loop the variable 'refresh_menu' gets checked and if true the screen gets redrawn with the menu item selected according to the value 'current_index'.
Link to full project code: Arduino due code. All the relevant code for this problem is in 'Menus.h'.
[Side note] I am not sure if my approach to build a menu is 'good'. It's not super responsive and the code is hard to maintain (changing a menu-item from position requires a lote of changes in the code). Any advice in a better approach is appreciated!
rotary_enc_int
should be called on signal transition, not on signal level .... increase the time difference in the ISR to 50 ms from 5 ms ... i think that you accidentally forgot the zero – jsotola Oct 31 '20 at 18:13lastInterruptTime = interruptTime;
.... this needs to be inside theif
block ..................... theif
may work better asif (interruptTime - lastInterruptTime > 50)
– jsotola Oct 31 '20 at 19:05