Decoding binary is the process of translating base-2 digital signals—represented physically by HIGH and LOW voltage states on a pin—into human-readable base-10 numbers, hexadecimal values, or specific hardware logic commands. In a real circuit or installation, this translation is what bridges the gap between abstract microcontroller math and physical reality; it changes a raw 3.3V pulse on an ESP32 GPIO pin into an actionable parameter like a motor's PWM duty cycle, a temperature sensor's reading, or a specific DMX lighting address. Without decoding, a microcontroller is just toggling voltages blindly.
The Physical Reality of 1s and 0s (And Why Voltage Matters)
When we talk about decoding binary on a workbench, we aren't dealing with abstract math. We are dealing with physical voltage thresholds defined by logic families. A logical '1' (HIGH) and a logical '0' (LOW) mean entirely different things depending on the silicon you are probing.
For a classic 5V TTL device like the Arduino Uno R3 (ATmega328P), a logical '1' is typically any voltage above 2.0V, though it outputs closer to 4.8V under light load. For a 3.3V CMOS device like the ESP32-WROOM-32 or a Raspberry Pi, a logical '1' is anything above roughly 2.0V, but it outputs 3.3V. If you are decoding RS-232 serial data, the rules flip entirely: a logical '1' (mark) is represented by a negative voltage (-3V to -15V), and a logical '0' (space) is a positive voltage (+3V to +15V).
Never feed a 5V HIGH signal directly into a 3.3V microcontroller input pin without a level shifter or voltage divider. While the ESP32's absolute maximum rating on some pins is 3.6V, sustained 5V logic will degrade the input protection diodes and eventually brick the silicon. Use a dedicated level translator IC like the Texas Instruments TXS0108E or a simple MOSFET-based bidirectional shifter when decoding binary data between 5V and 3.3V domains.
Understanding these physical thresholds is the first step in decoding. Once you capture the voltage states, you map them to standard numerical formats. Below is a reference matrix for common 8-bit binary bytes you will encounter when reading sensor registers or configuring shift registers.
| Binary (8-bit) | Hexadecimal | Decimal (Base-10) | 5.0V ADC Equivalent | 3.3V ADC Equivalent |
|---|---|---|---|---|
00000000 |
0x00 |
0 | 0.000 V | 0.000 V |
01010101 |
0x55 |
85 | 1.667 V | 1.100 V |
10000000 |
0x80 |
128 | 2.510 V | 1.656 V |
10110100 |
0xB4 |
180 | 3.529 V | 2.329 V |
11111111 |
0xFF |
255 | 5.000 V | 3.300 V |
Worked Example: Decoding an 8-Bit Sensor Register
Let's walk through a real-world scenario. You are reading an 8-bit status register from an I2C temperature sensor using an Arduino, and your logic analyzer or serial monitor spits out the raw binary sequence: 10110100. How do you decode this into a physical voltage or temperature value?
First, we convert the base-2 positional weighting into a base-10 decimal. In an 8-bit byte, the rightmost bit is the Least Significant Bit (LSB, $2^0$) and the leftmost is the Most Significant Bit (MSB, $2^7$).
- Bit 7 (1): $1 \times 2^7 = 128$
- Bit 6 (0): $0 \times 2^6 = 0$
- Bit 5 (1): $1 \times 2^5 = 32$
- Bit 4 (1): $1 \times 2^4 = 16$
- Bit 3 (0): $0 \times 2^3 = 0$
- Bit 2 (1): $1 \times 2^2 = 4$
- Bit 1 (0): $0 \times 2^1 = 0$
- Bit 0 (0): $0 \times 2^0 = 0$
Summing the active bits: $128 + 32 + 16 + 4 = 180$. The decimal value is 180 (or 0xB4 in hex).
Now, what does '180' mean in the physical circuit? If this byte came from an 8-bit Analog-to-Digital Converter (ADC) referenced to a 5.0V supply, we calculate the actual voltage on the pin. An 8-bit ADC has $2^8 = 256$ possible steps (0 through 255).
Decoded Voltage: 180 steps × 0.0196V = 3.529V.
If your sensor outputs 10mV per degree Celsius, that 3.529V reading decodes directly to a physical temperature of 352.9°C. This is the exact mechanical process of decoding binary: capturing the bit pattern, converting to decimal, and applying the hardware's scaling factor to yield a real-world unit.
Where You Meet Binary Decoding in Practice
You will rarely sit down with a pen and paper to convert bits. Instead, you decode binary in these common bench and jobsite scenarios:
1. Setting DMX512 Lighting Addresses via DIP Switches
In stage and architectural lighting, DMX512 addresses are set using a bank of 9 or 10 physical DIP switches on the fixture. These switches represent pure binary positional weights (1, 2, 4, 8, 16, 32, 64, 128, 256). If the lighting console is patching the fixture to universe address 137, you must decode 137 into binary to know which physical switches to flip ON. Since $137 = 128 + 8 + 1$, you flip switches 8, 4, and 1 to the ON position.
2. I2C Hardware Addressing (A0, A1, A2 Pins)
When wiring multiple identical sensors (like PCF8574 I/O expanders or AT24C32 EEPROMs) to an ESP32's I2C bus, you use physical jumper pins (A0, A1, A2) to decode the device's address. According to the NXP I2C-bus specification, these pins modify the least significant bits of the 7-bit slave address. If the base address is 0x20 (0100000 in binary) and you tie A0 to VCC (HIGH), the decoded address becomes 0x21. You are physically hardwiring binary bits to resolve bus collisions.
3. Reading Shift Registers (74HC595)
When expanding GPIO outputs using a Texas Instruments 74HC595 shift register, you send an 8-bit byte over SPI or bit-banged GPIO. If you want to turn on Relay 1 (QA) and Relay 8 (QH) simultaneously while leaving the others off, you must decode the desired physical state into a binary byte: 10000001 (Decimal 129, Hex 0x81), and shift that specific byte into the register's serial input.
Common Confusions: BCD, Inversion, and Endianness
When troubleshooting digital circuits, misinterpreting the binary format is the most common reason a project 'doesn't work' despite having correct wiring. Watch out for these three traps:
Binary Coded Decimal (BCD) vs. Pure Binary
This is the most frequent point of confusion with hardware thumbwheel switches and older digital displays. In pure binary, the decimal number 19 is 00010011. In BCD, each decimal digit is encoded into its own 4-bit nibble. Therefore, 19 in BCD is 0001 (for the '1') and 1001 (for the '9'), resulting in 00011001. If you feed a pure binary decoding algorithm a BCD input from a thumbwheel switch, your microcontroller will read the value as 25, not 19, causing massive calibration errors.
Active-Low Logic (Inversion)
In many industrial control circuits and microcontroller reset lines, a logical '0' (0V / GND) actually means the feature is ON or ACTIVE, while a logical '1' (HIGH) means OFF. This is called active-low logic, often denoted by a bar over the pin name (e.g., $\overline{RESET}$ or $\overline{CS}$). If you are decoding a status register and bit 3 is '0', you must remember that in an active-low scheme, this means the fault condition is currently triggered, not cleared.
Endianness in Multi-Byte Data
When decoding 16-bit or 32-bit values from sensors (like a 12-bit ADC reading from an ESP32 ADC peripheral padded to 16 bits), you must know the byte order. Big-Endian sends the Most Significant Byte (MSB) first; Little-Endian sends the Least Significant Byte (LSB) first. If a sensor outputs 0x12 then 0x34, decoding it as Big-Endian yields 4660, while Little-Endian yields 13330. Always check the sensor's datasheet for byte order before writing your decoding bit-shift math.
Frequently Asked Questions
Why do we use hexadecimal instead of just binary or decimal?
Hexadecimal (base-16) is used because it maps perfectly to binary nibbles (4 bits). One hex digit represents exactly four binary bits. An 8-bit byte is always exactly two hex digits (e.g., 1111 1111 is FF). This makes it vastly easier for humans to visually decode memory dumps and register maps without doing complex base-2 to base-10 math in their heads.
How do I decode a 12-bit ADC value on an ESP32?
The ESP32's SAR ADC outputs up to 12 bits of resolution, meaning values range from 0 to 4095 ($2^{12}-1$). To decode the raw binary reading into a voltage, divide your raw decimal reading by 4095, then multiply by the reference voltage (typically 3.3V, though the ESP32's internal ADC is notoriously non-linear above 2.5V, so calibration or an external ADC like the ADS1115 is recommended for precision work).
What is the fastest way to convert binary to decimal on the bench?
Memorize the first 8 positional weights: 128, 64, 32, 16, 8, 4, 2, 1. When you see a binary byte, simply add the weights together wherever there is a '1'. For example, 11001000 is just 128 + 64 + 8 = 200. It is much faster than typing it into a calculator app.






