Designing the Gray Encoder Top.

A project log for 3D Printed Rotary Time Tracker for Task Management

Track your tasks at your desk when working from home using magnets!

quincyquincy 07/17/2021 at 18:580 Comments

Let me start this by saying:

I’m not an expert on anything I’m about to talk about.

But I do think it’s worth having an in-depth look at how I got this device to work and how the Gray Encoder works.

When I first sat down to design the Task Tracker. I had two constraints:

In the first photo, we see that light emits onto all photoresistors sending the value to ‘1 1 1’ or 7 when converted to decimal. In the second photo, the middle sensor is blocked, corresponding to ‘1 0 1’ or 5. Here lies the interesting problem in implementing this practice. The rotation of the dial in the device should correspond to eight specific positions; in ideal conditions, it should just count as position 0, 1, 2, … to  7. Let's see what that looks like in just binary around a circle.

(photo credit:

Here white means 0, and black means 1. Starting at the top, going counter-clockwise, we see our immediate problem: ‘000’, 001’, ‘010’ (read from the center of the circle to the outside). Right there. Transitioning from ‘001’ -> ‘010’ means you have to switch two bits at once. If you have an imperfect system (for example light shining through a small slit and detected with a photoresistor) the signal-to-noise ratio is very high, and switching two bits at once can confound results. So we need a system that only turns one bit at once while still being addressable to ensure we know we changed states. Enter the Gray Code (

New design:

(photo credit:

Here, we start in the same sequence: ‘000’, ‘001’, but next is ‘011’. So this next state of ‘3’ is only a one-bit movement away from ‘1’ and this applies for all numbers from 0-7, even 7->0 is very convenient when we want to ensure that we know when a state transition happens.

Lastly, I want to ensure I translate the sensor values to a position that is interpretable back to the human, so I must convert the gray code back to a number. In code, this looks like this:

int gray_to_num(int s[])
  int num = 0;
  //convert array to int
  for (int i = 0; i < 3; i++)
    num += s[i] << i;

  // Convert Gray Code num to Decimal
  int mask = num;
  while (mask)
    mask >>= 1;
    num ^= mask;

  return num;

The overall code (under the Arduino file TaskTrack.ino in the resources section) posts to the serial what position is the device in, the only thing left for the user to do is to make sure the Lid.stl icons are aligned with the correct code status, and that the order in the software on the computer (to be posted is correct).

The next update will be about the sensor results and getting the signal conditioning correct.