[sdiy] Rotary encoder reading.. hardware solution (fast & accurate)

cheater cheater cheater00social at gmail.com
Sat Aug 21 15:43:39 CEST 2021

On Thu, Aug 12, 2021 at 2:37 AM Jean-Pierre Desrochers
<jpdesroc at oricom.ca> wrote:
> > Typically I'd use a 1 ms timer to poll the switch and run a state machine. State machine would look for the encoder changing, start a count down timer for
> > debouncing, when timer is 0 read encoder and compare it to last stable value to see if it has changed.
> That’s exactly what I had coded before the hardware ‘solution’.
> Polling the 3 encoder pins.  Everything was working fine until I added some
> code to process the encoder changes. Then BOOM..
> Many missed counts everywhere (increments/decrements).
> The interrupt style was even harder to implement since there were
> 4 different states to read before any final counts.
> A $2 bucks chips solution makes me spend my  time
> elsewhere in my  project releasing.
> Again..
> Any simple, fast and reliable interrupt driven code to suggest ??
> Managing all the encoder 4 steps with debouncing too ?

It sounds like you have a problem with the way your code is
structured. My theory is your polling misses counts because it
sometimes doesn't poll often enough, and that happens because your
processing functions take too long at a time before the next iteration
of your event loop can run, and therefore the encoder is polled the
next time.

If you want to keep polling, you'll have to break down your processing
functions. You can do it manually - code a processing function, upload
to hardware, see if codes are skipped, if yes then shorten the
function / break it down into two loops. You can do it by assuming a
new programming paradigm.

You can program your code using callbacks - which enable breaking down
long processing chains into short functions that can be hung up by the
scheduler (called reactor). It can try to process as much as possible
during a single iteration of the loop before it knows that the timing
guarantees on the necessary polling loop run out. It's still your
responsibility to make the callbacks as short as possible, but you
don't have to tune the scheduling by hand.

You can program your code to have a generic data processing
functionality: when you're processing, the data to process is stored
somewhere in memory, and as it is processed, the new state is created
bit by bit, but the new state is not used until it is fully formed.
Every bit of data is processed by a short function that only does a
bunch of work. The nice thing about this is that usually you can break
down changes to state in a step by step fashion anyways so it's not
hard to program in this way. After each step is done you just keep
info on what the last step was and then during the next iteration of
the main loop your main state updating function has to decide on what
the next step is and perform it. Meanwhile, as the state is being
updated bit by bit, all the real time stuff (encoder polling, audio
processing, etc) keeps running in its hard realtime slots, and you
know how long they take, because you programmed those bits in a hard
real time fashion.

More information about the Synth-diy mailing list