Advanced Users can post their questions and comments here for the not so Newbie crowd.

Moderator: eriksl

User avatar
By eriksl
#82690 I am using rotary encoders here and there. They are the simple type, where in one direction, first contact A shorts, then contact B, then A releases and then B does the same. In the other direction A and B are reversed.

Until now I did it the simple way, using a flip-flop (in hardware). This has the drawback that the flip-flop always remains in the last state, which always requires to do an additional click, which is interpreted the wrong way around and only then the clicks come in in the correct order.

So I am now eliminating that part. The hardware debouncer remains though, it's great, I can recommend it!

So what I now need to do is to interprete the clicks of 'A' and 'B' into clicks 'clock' and 'counterclock', in software. I think there are two approaches here:

- have a flag on both gpio's that are related (connected to either 'A' or 'B');
* if neither flag is set, set flag on the GPIO that was hit
* if both flags are set, see which one is to be set now (the flag belonging to the GPIO that now hit), if it's the first of the pair, note 'clock', otherwise note 'counterlock'; after that, clear both flags

or

- set a timestamp on every GPIO when it's hit, check the other GPIO of a pair and see if it's within the time window that a clock on the encoder may take; whichever of the two was the first, determines the direction.

The first solution has the drawback that one really would need to clear all flags after some timeout, because rotary encoders tend to miss contacts and otherwise we'd remain in some stuck state, giving spurious results. The problem is that we don't know when we set the flag, so it may be cleared the nanosecond after it was set. This could be resolved, I guess, by making the cleanup function timed.

The second solution has the drawback of quick timer overflow. We'd really need to have at least microsecond resolution, ideally nanosecond. The timestamp as a 32 bit value would turnover very quickly, giving cause to race conditions. And no, I don't want to have 64 bit timestamp values ;)

I am now using code that does the first, but it doesn't work very well. Probably because the encoders are very cheap and very frequently missing a hit. I guess I need to pull them quite a bit stronger and maybe then it starts working.

So, just brainstorming here.
User avatar
By Bonzo
#82691 I had a mirror mount driven by a stepper motor, worm and wheel and there was a twenty step backlash. I had a flag set and the flag status was checked before any move. If it was the opposite direction the motor moved an extra twenty steps.
This seemed to work well and I never had any complaints from the users.
User avatar
By heweb123
#83091 I have to debounce by software and I am using cooperative multitasking.

Steps:
1) Clock_Pin does an interrupt - and disables its own interrupt [if (flag) return] - and starts a task.
2) The started task does delay (non blockíg) some millisconds.
3) The started tasks resumes and reads Clock_Pin and Data_pin - both are debounced now.
4) The combination of both pins tell me very easily , which direction the Rotary was moved.
5) The task allows interrupt for the rotary agáin.

Turning the rotary by hand never misses a puls.
User avatar
By eriksl
#83309 I have implemented a similar scheme.

- there is already running a background task which is called every 100 ms.
- on pin change interrupt, "a valid for x ticks" value is recorded for that pin (where x is something like a second), also check the "mated" pin if it already has such a value (i.e. it was hit before this one), if it does, we have a complete cycle and we can determine the direction; after that, clear both recorded values.
- use the background task to decrement the "valid for x ticks" value for all relevant pins.
- if something weird occurs (very probable with external contacts), reset both values

I am using a hardware debouncer, very much advised! I do have software debouncing, but a bare mechanic contact can make so many on/off transitions in a short time, it will overflow the pin change change interrupt mechanism and crash the esp. With the hardware debouncer it works very well and also not missing a single click from the encoder, if the hardware debouncer is set to a very small time span.