micropython-mcp23017
micropython-mcp23017 copied to clipboard
rotary example
Does the rotary example work properly ?
I do get the switch: 1 when pressed, but when rotating, I get the same thing, it does not update the value, just repeating switch 1
I think something goes wrong with the bitshifting in this part of rotary:
def _rotated(self, clk, dt):
# shuffle left and add current 2-bit state
self.state = (self.state & 0x3f) << 2 | (clk << 1) | dt
# debug
print('clk: {}, dt: {}, self.state: {}'.format(clk, dt,self.state))
# it will never arrive here....
if self.state == 180:
output:
clk: 1, dt: 0, self.state: 210
clk: 1, dt: 1, self.state: 75
clk: 0, dt: 1, self.state: 45
clk: 1, dt: 0, self.state: 182
clk: 1, dt: 1, self.state: 219
clk: 1, dt: 0, self.state: 110
clk: 0, dt: 1, self.state: 185
clk: 0, dt: 1, self.state: 229
clk: 1, dt: 1, self.state: 151
clk: 0, dt: 0, self.state: 92
clk: 0, dt: 1, self.state: 113
clk: 1, dt: 1, self.state: 199
clk: 1, dt: 0, self.state: 30
clk: 0, dt: 1, self.state: 121
clk: 1, dt: 1, self.state: 231
...
I have modified the code and this seems to be working for me instead:
def _rotated(self, clk, dt):
if (clk == 1) and (dt == 1):
self._step(-1)
elif (clk == 1) and (dt == 0):
self._step(1)
Hi @bakman2
In an ideal world, an encoder should produce 4x states per step.
One step clockwise:
01 -> 11 -> 10 -> 00
One step counter-clockwise:
10 -> 11 -> 01 -> 00
This line is combining the clk + dt values with the last 3 executions.
self.state = (self.state & 0x3f) << 2 | (clk << 1) | dt
Could also be written as:
self.state = ((self.state << 2) | (clk << 1) | dt) & 0xff
Shift the state 2 bits left, add clk and dt bits, limit to 0-255
01 -> 11 -> 10 -> 00 == state 0b_0111_1000 == 120
10 -> 11 -> 01 -> 00 == state 0b_1011_0100 == 180
The last CD bits in both 8-bit sequences are 00. This is why it evaluates whether it should +/- step on 120/180.
Looking at your example with state in binary, it shows some missed steps in the sequence
clk: 1, dt: 0, self.state: 210 1101 0010 counter clockwise, mid sequence
clk: 1, dt: 1, self.state: 75 0100 1011 counter clockwise, mid sequence
clk: 0, dt: 1, self.state: 45 0010 1101 counter clockwise, mid sequence
clk: 1, dt: 0, self.state: 182 1011 0110 counter clockwise, missed a 11 in the sequence
clk: 1, dt: 1, self.state: 219 1101 1011 counter clockwise, missed a 00 in the sequence
clk: 1, dt: 0, self.state: 110 0110 1110 clockwise missed a 11 in the sequence
clk: 0, dt: 1, self.state: 185 1011 1001 unexpected 10 after the 1011
clk: 0, dt: 1, self.state: 229 1110 0101 unexpected 0101 in sequence
clk: 1, dt: 1, self.state: 151 1001 0111 missed 00, double 01
clk: 0, dt: 0, self.state: 92 0101 1100 double 01, missed 10 after 11
clk: 0, dt: 1, self.state: 113 0111 0001 missed 10 after 11
clk: 1, dt: 1, self.state: 199 1100 0111 missed 10 after 11
clk: 1, dt: 0, self.state: 30 0001 1110 clockwise, mid sequence
clk: 0, dt: 1, self.state: 121 0111 1001 missed 00 after 10
clk: 1, dt: 1, self.state: 231 1110 0111 missed 00 after 10
This could be caused by not polling fast enough, or a flakey encoder, loose wiring, all of the above, etc.
In your solution, you're using the CD states 11 and 10 to +/- the step. This doesn't work as 11 and 10 are in both clockwise and counter clockwise sequences.
I'll try to replicate on some of my old encoders.