I'm sampling an encoder and this sample has a value between the interval [30, 230]; I have to use this value to define two output counter variables (one increasing counter and one decreasing counter).
The problem is that sometimes when there is a rollover, which means that the encoder passes from 230 to 30 or vice versa, the sampling is too slow and I lose the direction of the movement (counterclockwise or clockwise) and this results in a wrong behaviour.
Example:
If the encoder is on the 220 value and I move it really fast in clockwise direction, my next value is for example 100 and that means that the value passed through 30 (rollover): the direction should be clockwise. But the software thinks that I moved the encoder from 230 to 100 and it gives me a counter clockwise movement.
Remind that I cannot encrease the sampling speed, it is steady.
It's in a real-time enviroment.
If you cannot guarantee that the encoder will not move more then half the range in one polling period, then the problem cannot be solved. If you assume that it will not move that far, then it is solvable - you simply assume that the movement between two polling events was the shortest of the two possible directions.
You don't explain, why your encoder range starts from non-zero, but the arithmetic is easier to follow (and code) if you remove that offset and work with a range 0 to 200 by subtracting the offset.
Given an encoder read function uint8_t ReadEnc()
for example:
#define ENCODER_RANGE 200
#define ENCODER_OFFSET 30 // remove offset for range 0 to 200
static unsigned ccw_counter = 0 ;
static unsigned cw_counter = 0
static uint8_t previous_enc = ReadEnc() - ENCODER_OFFSET ;
uint8_t enc = ReadEnc() - ENCODER_OFFSET ;
signed enc_diff = enc - previous_enc ;
previous_enc = enc ;
// If absolute difference is greater then half the range
// assume that it rotated the opposite way.
if( enc_diff > ENCODER_RANGE / 2)
{
enc_diff = -(ENCODER_RANGE - enc_diff)
}
else if( enc_diff < -(ENCODER_RANGE / 2) )
{
enc_diff = (ENCODER_RANGE + enc_diff)
}
// Update counters
if( enc_diff < 0 )
{
// Increment CCW counter
ccw_counter -= enc_diff ;
}
else
{
// Increment CW counter
cw_counter += enc_diff ;
}