If you can guarantee that the polling happen more frequently of the fastest rotation of a half turn (180°), the following considerations should be true:
- the absolute difference between current reading and the last one could not exceed half turn=180°
- If absolute difference is
>= 180°
we have crossed the 0°
. The count of degree we moved is calculated by adding or subtracting a full turn (360°) depending on current sense of rotation (cw add, ccw subtract).
- If absolute difference is
< 180°
and the difference sign is positive we have moved clockwise (increment angle)
- If absolute difference is
< 180°
and the difference sign is negative we have moved counter clockwise (decrement angle)
- If the difference
== 0
then no move have happened.
In code:
int LastAngle = GetAngle(); // Init angle reading
bool bClockWise = true;
...
// polling or interrupt handler
int CurrAngle = GetAngle();
int diff = CurrAngle - LastAngle;
if (diff==0)
{
//No move
...
}
else if (abs(diff) < 180) //Angle changed from last read
{
//if we are here diff is not 0
//we update rotation accordingly with the sign
if (diff > 0)
bClockWise = true; //we were rotating clockwise
else
bClockWise = false; //we were rotating counterclockwise
}
//If absolute difference was > 180° we are wrapping around the 0
//in this case we simply ignore the diff sign and leave the rotation
//to the last known verse.
...
If you want count the turns you can code:
int Turns = 0;
if ((diff != 0) && (abs(diff) > 180))
{
if (bClockWise)
Turns++; //Increase turns count
else
Turns--; //Decrease turns count
}
The following macros can be used to check for motion and rotation sense:
#define IsMoving (diff) //Give a value !=0 if there is a movement
#define IsCw (bClockWise) //Give true if clockwise rotation
#define IsWrap (abs(diff) >= 180) //Give true if knob wrapped
P.S. Please note that the diff
variable is functional for rotational sense detection and movement, is not the absolute difference in degrees between movements.
If you want compute the real movement you should take into account the wraparound:
int Angle = 0; //the real angle tracked from code start
if (diff != 0)
{
if (abs(diff) >= 180)
{
if (bClockWise)
Angle += diff + 360; //Adjust for positive rollover
else
Angle += diff - 360; //Adjust for negative rollover
}
else
Angle += diff;
}