EmbeddedRelated.com

Gray Code

Category: Standards | Also known as: gray-code

Gray code is a binary numbering scheme in which consecutive values differ by exactly one bit -- a property that holds for the standard reflected binary Gray code and, more broadly, defines the class of unit-distance codes to which Gray code belongs. It is commonly used in applications where transitions between states must not produce spurious intermediate values caused by multiple bits changing simultaneously.

In practice

Gray code appears most often in rotary encoders and absolute position sensors. Mechanical and optical encoders output a Gray-coded value so that, at any transition between adjacent positions, only a single output line changes state. If standard binary were used instead, a transition such as 3 (011) to 4 (100) requires three bits to change; if the bits do not settle at exactly the same moment, the reading logic can briefly see 000, 001, 010, 101, 110, or 111 -- none of which are the correct value. With Gray code, that same boundary only toggles one bit, reducing this class of error by ensuring no unintended intermediate word is produced (though a sampled bit can still metastabilize on its own).

Converting between Gray code and binary is straightforward in firmware. Binary-to-Gray is computed as `gray = binary ^ (binary >> 1)`. Gray-to-binary requires a short iterative or parallel XOR reduction: each binary bit is the XOR of all Gray code bits of equal or higher significance. Both operations fit in a small number of instructions on typical MCUs, though the exact count varies with word size, architecture, and compiler.

Gray code also appears in the sequencing logic of asynchronous FIFOs that cross clock domains. Because only one bit changes per count step, a Gray-coded read or write pointer can be safely sampled by the other clock domain with at most one bit of ambiguity, rather than the multi-bit glitches that a binary counter would produce during a transition. This technique is standard in FPGA designs and in the register-transfer-level descriptions of many on-chip peripherals.

One pitfall is assuming Gray code eliminates all encoder errors. It removes glitches at clean single-step transitions, but if the encoder moves fast enough to skip positions between samples, or if the sensor has mechanical wear producing simultaneous edge noise on multiple tracks, errors can still occur. Gray code is not a substitute for debouncing, appropriate sampling rates, or good sensor selection.

Frequently asked

How do I convert a Gray code value to binary in C?
A standard implementation iterates from the MSB downward: `uint32_t gray_to_binary(uint32_t g) { uint32_t b = g; while (g >>= 1) b ^= g; return b; }`. For a known fixed width, this can also be unrolled into a sequence of XOR-and-shift operations. Converting binary to Gray is simpler: `gray = binary ^ (binary >> 1)`.
Why is Gray code used for asynchronous FIFO pointers in FPGAs?
When a read or write pointer crosses a clock domain boundary, the receiving domain samples the pointer asynchronously and can catch it mid-transition. A binary counter may have multiple bits changing at once, producing a briefly invalid intermediate value that can be any number. A Gray-coded counter changes only one bit per increment, so the worst-case sample is either the old value or the new value -- never a third, unintended multi-bit combination. Note that the single changing bit can still metastabilize in the synchronizer flip-flop; Gray coding limits the damage to that one bit rather than eliminating metastability itself.
Do all rotary encoders use Gray code?
No. Incremental encoders output two quadrature signals (A and B) rather than a multi-bit code, so Gray code is not directly involved. Absolute encoders -- which output a multi-bit word representing the current angular position -- commonly use Gray code on their parallel or serial output tracks precisely to avoid multi-bit transition glitches.
Is Gray code the same as a Hamming-distance-1 code?
Gray code is one example of a unit-distance code, meaning consecutive codewords have a Hamming distance of exactly 1. The standard reflected binary Gray code is the most common variant. Other unit-distance codes exist, but 'Gray code' in practice almost always refers to the reflected binary construction unless otherwise specified.
Can Gray code help with mechanical switch debouncing?
Indirectly. A Gray-coded rotary switch limits glitches to single-bit transitions at detent boundaries, which simplifies debounce logic -- you only need to handle one line bouncing rather than multiple lines changing simultaneously. However, debouncing itself (filtering out repeated transitions during contact bounce) still requires its own timing logic or hysteresis; Gray code reduces the complexity of the problem but does not eliminate it.

Differentiators vs similar concepts

Gray code is sometimes confused with other error-resistant codes such as Hamming codes or Manchester encoding. Hamming codes add redundant bits to detect and correct bit errors in stored or transmitted data -- they are not concerned with transition glitches between sequential values. Manchester encoding is a line-coding scheme that embeds a clock signal within data transitions; it has nothing to do with the ordering of numeric values. Gray code addresses a specific problem: ensuring that incrementing or decrementing a counter or position value causes only one physical signal line to change at a time.