mathertel / RotaryEncoder

RotaryEncoder Arduino Library
Other
328 stars 107 forks source link

Decrement does not work when setPosition is called between latchstates #25

Closed Tikral closed 3 years ago

Tikral commented 3 years ago

Hello, and thanks for your lib, works great for me besides this issue I just spent some time debugging.

Symptom: slow decrements not being registered.

Context: I'm using the lib with interrupts (tick() called in an ISR), and agressively used getPosition and setPosition(0) at each iteration of my main loop.

nointerrupts();
local_coderCounter = encoder.getPosition();
encoder.setPosition(0);
interrupts();

Issue Turns out, if setPosition(0) is executed between 2 latchstates, if _position was negative, the way _position is reassigned is incorrect: it is treated as an unsigned int: _position = ((newPosition<<2) | (_position & 0x03L));

mathertel commented 3 years ago

The new _position is calculated using binary operations. They don't care about signed/unsigned. Sorry dont't see the problem.

I implemented a testcase tor the assignment, output seems right:

void testcase(long newPosition, long _position) {
  long p = ((newPosition<<2) | (_position & 0x03L));
  Serial.printf("%08lx %08lx = %08lx\n", newPosition, _position, p);
}
  testcase(0, 3);
  testcase(0, 2);
  testcase(0, 1);
  testcase(0, 0);
  testcase(0, -1);
  testcase(0, -2);
  testcase(0, -3);
  testcase(0, -4);
  testcase(0, -5);

Test output:
00000000 00000003 = 00000003
00000000 00000002 = 00000002
00000000 00000001 = 00000001
00000000 00000000 = 00000000
00000000 ffffffff = 00000003
00000000 fffffffe = 00000002
00000000 fffffffd = 00000001
00000000 fffffffc = 00000000
00000000 fffffffb = 00000003