The binary representation of a number is a base-2 numerical system using only the digits 0 and 1 to encode values, where each position represents a successive power of two. In a physical circuit or installation, this mathematical concept dictates how microcontrollers, analog-to-digital converters (ADCs), and logic gates process physical voltage levels as discrete data, directly determining your system's measurement resolution, memory allocation, and overflow limits. Beginners commonly confuse binary representation (the mathematical encoding of a value) with binary logic levels (the physical voltages like 0V and 3.3V that represent those digits on a wire), or they conflate base-2 math with the hexadecimal shorthand used in C++ firmware.

The Core Math: Powers of Two and Bit Weighting

Unlike the decimal (base-10) system you use daily, which rolls over to a new column every time you hit 10, binary rolls over every time you hit 2. Each column—referred to as a "bit"—has a specific decimal weight. To read or write a binary number, you must understand the weight of each bit position, starting from the Least Significant Bit (LSB) on the far right.

Table 1: 8-Bit Binary Weighting and Hexadecimal Mapping
Bit Position Power of 2 Decimal Weight Hex Nibble Equivalent Typical Register Use
Bit 7 (MSB) 2^7 128 0x80 Sign bit / Overflow flag
Bit 6 2^6 64 0x40 Data / Config bit
Bit 5 2^5 32 0x20 Data / Config bit
Bit 4 2^4 16 0x10 High nibble boundary
Bit 3 2^3 8 0x08 Low nibble boundary
Bit 2 2^2 4 0x04 Data / Config bit
Bit 1 2^1 2 0x02 Data / Config bit
Bit 0 (LSB) 2^0 1 0x01 Enable / Parity bit
Worked Numeric Example: Converting Decimal 173 to Binary

Let's convert the decimal number 173 into an 8-bit binary representation. We subtract the largest possible power of two sequentially:

  • 128: 173 - 128 = 45. (Bit 7 = 1)
  • 64: 45 is smaller than 64. (Bit 6 = 0)
  • 32: 45 - 32 = 13. (Bit 5 = 1)
  • 16: 13 is smaller than 16. (Bit 4 = 0)
  • 8: 13 - 8 = 5. (Bit 3 = 1)
  • 4: 5 - 4 = 1. (Bit 2 = 1)
  • 2: 1 is smaller than 2. (Bit 1 = 0)
  • 1: 1 - 1 = 0. (Bit 0 = 1)

Reading from Bit 7 down to Bit 0, the binary representation of 173 is 10101101. In hexadecimal, this is 0xAD.

Where You Meet This in Practice: Microcontrollers and ADCs

You rarely write raw binary math when wiring a house, but on the electronics workbench, the binary representation of a number is the bridge between the physical world and your code. The most common place you will encounter this is when reading sensors via an Analog-to-Digital Converter (ADC).

Take the popular ESP32-WROOM-32 module. Its primary ADC is a 12-bit successive approximation register (SAR) ADC. A 12-bit system means the converter can output 4,096 distinct binary states (from 000000000000 to 111111111111), representing decimal values 0 through 4095. If your ESP32 is configured with a 3.3V reference voltage, the binary number returned by the analogRead() function maps directly to a physical voltage.

ESP32 12-Bit ADC Resolution: 3.3V ÷ 4096 steps = 0.805 mV per bit.

Suppose you are monitoring a LiFePO4 battery pack and the ESP32 returns a binary representation of 100000000000 (decimal 2048). Because 2048 is exactly half of the 4096 total steps, you instantly know the voltage at the GPIO pin is exactly half of 3.3V, or 1.65V. If your voltage divider scales the battery down by a factor of 4, the actual battery voltage is 1.65V × 4 = 6.6V. Understanding how the binary bit-depth limits your resolution prevents you from trying to measure 0.1mV changes on a 12-bit ADC that physically bottoms out at 0.8mV steps. For higher precision, you must step up to a 16-bit or 24-bit external ADC like the ADS1115, which outputs a 16-bit binary representation (up to 65,535 steps) over an I2C bus.

Common Confusions: Binary Math vs. Physical Logic Levels

The most frequent mistake hobbyists make is assuming that a binary "1" means exactly 3.3V or 5.0V, and a "0" means exactly 0.0V. In reality, silicon logic gates do not operate on perfect mathematical integers; they operate on voltage thresholds defined in the component's datasheet.

When you send a binary representation out of an ESP32 GPIO pin configured as an output, a "1" will measure close to 3.3V, and a "0" will measure close to 0V. However, when that signal travels down a wire and enters the input pin of a 5V shift register like the TI SN74HC595, the receiving chip doesn't look for an exact voltage. It looks for specific threshold boundaries:

  • V_IH (Input Voltage High): The minimum voltage the chip guarantees to read as a binary "1". For the 74HC family at 5V, this is typically 3.5V.
  • V_IL (Input Voltage Low): The maximum voltage the chip guarantees to read as a binary "0". For the 74HC family at 5V, this is typically 1.5V.

If noise on your breadboard causes your signal to droop to 2.5V, you are in the "forbidden zone" between V_IL and V_IH. The chip might read a 1, it might read a 0, or it might oscillate wildly, causing excessive current draw and heating. The mathematical binary representation is absolute, but the physical implementation requires careful attention to noise margins, pull-up resistors, and logic level translation when mixing 3.3V and 5V domains.

FAQ: Binary Representation in Embedded Systems

Why do we use hexadecimal instead of just writing out the binary representation?

Writing out a 32-bit binary register (e.g., 11001010111100001010101011001010) is highly prone to human reading errors. Hexadecimal (base-16) acts as a direct shorthand for binary. Because 16 is a power of 2 (2^4), every single hex digit perfectly maps to exactly four binary bits (a "nibble"). The 32-bit binary string above condenses neatly into 0xCAF0AACA, making it vastly easier to read, write, and debug in C++ firmware.

What happens if my binary number exceeds the bit-width of my variable?

This causes an integer overflow. If you attempt to store the decimal value 256 in an 8-bit unsigned integer (which maxes out at 255, or 11111111), the 9th bit is simply discarded. The variable wraps around to 00000000 (decimal 0). In motor control or timing loops, an unexpected overflow can cause a machine to step backward or a timer to reset prematurely, which is why selecting the correct variable size (uint8_t vs uint16_t vs uint32_t) is critical.

How does two's complement represent negative numbers in binary?

Microcontrollers use a system called two's complement to represent negative integers. In an 8-bit signed integer, the Most Significant Bit (Bit 7) acts as a negative weight (-128) rather than a positive weight (+128). Therefore, the binary representation 11111111 is not 255; it is calculated as -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1, which equals -1. This elegant mathematical trick allows the ALU (Arithmetic Logic Unit) to use the exact same addition circuits for both positive and negative numbers.

For a deeper dive into how digital logic relies on these base-2 principles, the All About Circuits digital textbook provides excellent foundational schematics. Additionally, when configuring ADC registers on modern microcontrollers, always consult the specific Espressif ESP-IDF ADC documentation to verify the exact bit-depth and attenuation mappings for your specific silicon revision.