I have now hit an issue, which I can't find my way around -and after banging my head on it for the best part of a week- I decided to turn here.
I am trying to set up a basic device which uses an I2C SSD1306 for output, and a rotary encoder w/ push button for input.
While I have no issues using these two peripherals separately, and I manage to get very decent refresh rates on the display alone, as well as very precise readings on the rotary encoder (using the micropython-stm-lib by SpotlightKid), I run into jitter / skipped readings issues whenever I try using them together.
My stripped-down code looks like this:
Code: Select all
old_v = rotary.value
while True:
...
- draw something on the display -
...
if rotary.value != old_v:
print(rotary.value)
old_v = rotary.value
display.show()
display.fill(0)
If I try to refresh the display, the encoder readings start behaving erratically, and I get very jittery values.
The test application I've made to highlight this problem is a simple paddle-ball game where a pixel bounces around the edges of the SSD1306 display, and a paddle on the bottom moves according to the rotary encoder's readings (which is absolutely NOT the intended final result

I tried capturing a video to better show what I'm experiencing, but I'm unsure whether this helps:

See video on Gyfcat
I understand this has to do with the reading frequency of the changing edges on the encoder's pins, which likely becomes too low when the display is refreshed, but I don't understand why would that be, since the library is interrupt-driven, and I assumed that such interrupts could easily take over the display refresh routines?
I have tried in several ways getting around this issue, but as I'm clearly not experienced at low-level programming, I have miserably failed so far. What I have tried:
- Tried using different encoder libraries
- Tried writing my own poll-driven encoder library, and polling it for changes at every iteration of the loop. Same problem when using it together with the display.
- Tried putting the display refresh instructions in a separate thread (both using a hardware timer, and the _threading module)