Please suggest an algorithm to compare Gray code numbers

925 views algorithm

I have an absolute encoder which is outputting a 10 bit value (0 to 1023) in Gray code. The problem I am trying to solve is how to figure out if the encoder is moving forwards or backwards.

I decided that the “best” algorithm is as follows: first I convert the Gray code to regular binary (full credit to the last answer in:

int grayCodeToBinaryConversion(int bits)
  bits ^= bits >> 16; // remove if word is 16 bits or less
  bits ^= bits >>  8; // remove if word is 8 bits or less
  bits ^= bits >>  4;
  bits ^= bits >>  2;
  bits ^= bits >>  1;
  return bits;

Second I compare two values that were sampled apart by 250 milliseconds. I thought that comparing two values will let me know if I am moving forwards or backwards. For example:

if((SampleTwo – SampleOne) > 1)
  //forward motion actions

if((SampleTwo – SampleOne) < 1)
  //reverse motion actions

if(SampleTwo == SampleOne)
  //no motion action

Right as I started to feel smart, to my disappointment I realized this algorithm has a fatal flaw. This solution works great when I am comparing a binary value of say 824 to 1015. At this point I know which way the encoder is moving. However at some point the encoder will roll over from 1023 to 0 and climb, and when I then go to compare the first sampled value of say 1015 to the second sampled value of say 44, even though I am physically moving in the same direction, the logic I have written does not correctly capture this. Another no go is Taking the Gray code value as an int, and comparing the two ints.

How do I compare two Gray code values that were taken 250 milliseconds apart and determine the direction of rotation while taking into account the rolling over aspect of the encoder? If you are so kind to help, could you please provide a simple code example?

answered question

How much do you expect your encoder to move in a 250ms interval?

not more than 400 pulses (ball park). But when it goes from 950 to 250, my algorithm doesn't work.

One way to do it, is to compute the difference between the readings assuming you're going "forwards" and then going "backwards". You then assume that the encoder is travelling in the direction of the smaller value. Of course, this would fail if your encoder is going to travel more than half the interval in 250ms; in which case you would increase the sampling frequency.

The result of S2-S1 is in the range -1023 to +1023; of that range, -1023 ~ -512 and +1 ~ +511 are forward and -511 ~ -1 and 512 ~ 1023 are backward.

1 Answer


Suppose A is your initial reading, and B is the reading after 250ms.

Let's assume the encoder is moving forwards (its value is increasing with time).

Then, the distance covered is (B - A + 1023) % 1023. Let's call this d_forward.
The distance covered going backwards would be 1023 - d_forward.

The minimum of d_forward and d_backward would give the direction the encoder is travelling.

This will not work if the encoder is going to travel more than 1023/2 units in 250ms.

posted this

Have an answer?


Please login first before posting an answer.