miketeachman / micropython-rotary

MicroPython module to read a rotary encoder.
MIT License
269 stars 56 forks source link

Is the transition table wrong? #16

Closed yuanyanhui closed 2 years ago

yuanyanhui commented 2 years ago

I like this FSM approach, however I have doubts about the transition table. I checked the original Arduino implementation and found similar issues were also raised. Take the CW sequence as an example, to register a full cycle, CLK/DT should go through 00 -> 10 -> 11 -> 01 -> 00. Start from the initial state _R_START, when CLK/DT==10, the state proceeds to _R_CW_1 as expected. Afterwards, CLK/DT==11, the state should change from _R_CW_1 to _R_CW_2. At this point, the transition in the table is different. The table shows 11 results in _R_START and 00 results in _R_CW_2. Since majority of users reported back correct results, maybe I missed something here?

`_transition_table = [

# |------------- NEXT STATE -------------|            |CURRENT STATE|
# CLK/DT    CLK/DT     CLK/DT    CLK/DT
#   00        01         10        11
[_R_START, _R_CCW_1, _R_CW_1,  _R_START],             # _R_START
[_R_CW_2,  _R_START, _R_CW_1,  _R_START],             # _R_CW_1
[_R_CW_2,  _R_CW_3,  _R_CW_1,  _R_START],             # _R_CW_2
[_R_CW_2,  _R_CW_3,  _R_START, _R_START | _DIR_CW],   # _R_CW_3
[_R_CCW_2, _R_CCW_1, _R_START, _R_START],             # _R_CCW_1
[_R_CCW_2, _R_CCW_1, _R_CCW_3, _R_START],             # _R_CCW_2
[_R_CCW_2, _R_START, _R_CCW_3, _R_START | _DIR_CCW],  # _R_CCW_3
[_R_START, _R_START, _R_START, _R_START]]             # _R_ILLEGAL`
miketeachman commented 2 years ago

In the initial state _R_START, CLK/DT==11. For a CW turn: CLK/DT 11 -> 10 -> 00 -> 01 -> 11. Looking at the oscilloscope capture helps to see what is happening.

Does that help?

yuanyanhui commented 2 years ago

Thank you for your explanation, Mike. Looking at the oscilloscope capture did the trick. I didn't realize the states in the table must be associated with the actual pin states. One more question though, under what scenario is the _R_ILLEGAL state entered? It's not obvious to me as the _R_ILLEGAL state is not present inside the table.

miketeachman commented 2 years ago

The _R_ILLEGAL state is included to make the state machine fault tolerant, in the case the value of state becomes 0x07, an undefined state. state is 3 bits (&'d with _STATE_MASK) so it can have the values, 0x00 to 0x07. Under normal conditions state should never take the value 0x07, but if that happens, the state machine will recover by moving to the _R_START state. While reviewing the code, I see that the half step table is missing the fault tolerant characteristics that I just explained. I made a note to fix this in a future update.

yuanyanhui commented 2 years ago

Than you for the clarification, Mike.