A list of binary numbers is a sequence of base-2 values (using only 0s and 1s) that represent discrete voltage states—typically LOW (0V) and HIGH (3.3V or 5V)—in digital circuits and microcontrollers. When you write code or configure hardware, this list dictates the exact physical output state of GPIO pins, shift register outputs, or communication addresses, turning abstract logic into physical voltage levels that drive relays, LEDs, and motor controllers. If you misinterpret the sequence, your hardware will behave erratically, often without throwing a software error.
The Core Mechanics: Translating a List of Binary Numbers
To apply a list of binary numbers to a circuit, you must translate the base-2 sequence into a decimal or hexadecimal value that your microcontroller can process. Microcontrollers like the ESP32 or Arduino Uno do not natively "see" binary strings in memory; they process byte-sized (8-bit) or word-sized (16-bit) integers.
Let us look at a worked numeric example. Suppose your circuit requires an 8-bit payload to configure a port expander, and your design notes provide this list of binary numbers: 01101001.
To convert this to a decimal value your code can use, you map each bit to its positional weight (powers of 2, starting from the right):
- Bit 7 (Leftmost): 0 × 128 = 0
- Bit 6: 1 × 64 = 64
- Bit 5: 1 × 32 = 32
- Bit 4: 0 × 16 = 0
- Bit 3: 1 × 8 = 8
- Bit 2: 0 × 4 = 0
- Bit 1: 0 × 2 = 0
- Bit 0 (Rightmost): 1 × 1 = 1
Summing these values: 64 + 32 + 8 + 1 = 105. In your C++ firmware, you would pass 105 (or 0x69 in hex) to the I2C or SPI transmission function. The hardware receives the byte, unpacks it back into the physical voltage list 01101001, and sets the corresponding pins LOW, HIGH, HIGH, LOW, HIGH, LOW, LOW, HIGH.
Where You Meet This in Practice
You will rarely write out raw binary lists for simple tasks like toggling a single LED. However, sequences of binary numbers become mandatory in the following real-world scenarios:
- Shift Registers (e.g., 74HC595): When you run out of GPIO pins, you send an 8-bit list of binary numbers serially to a shift register, which then outputs those states in parallel to 8 physical pins.
- I2C Address Configuration: Devices like the TCA9548A I2C multiplexer require you to send a binary list (e.g.,
00000100) to its control register to route the I2C bus to a specific downstream channel. - DIP Switch Decoding: When reading an 8-position DIP switch on a PCB, the microcontroller reads the physical switch states as a list of binary numbers to determine a device ID or baud rate setting.
- PWM and Motor Commutation: Brushless DC (BLDC) motor controllers use a 6-step commutation table, which is essentially a repeating list of 6-bit binary numbers (e.g.,
100001,100010) to energize the correct stator coils.
Real-World Scenario Walkthrough: The Shift Register Mishap
Abstract theory is clean; the workbench is messy. Here is a scenario that frequently traps hobbyists and junior engineers when applying binary lists to physical hardware.
The Setup: You are building an automated irrigation controller using an ESP32-WROOM-32. Because the ESP32 is handling WiFi and sensor reads, you are low on pins. You wire a Texas Instruments SN74HC595 shift register to control 8 solenoid valves via a ULN2803 Darlington array. You map ESP32 GPIO 23 to Serial Data (SER), GPIO 18 to Shift Clock (SRCLK), and GPIO 5 to Storage Register Clock (RCLK).
The Numbers: You want to open valves 1, 3, 5, and 7 simultaneously. You write down your target list of binary numbers: 10101010 (where 1 means valve OPEN). You convert this to decimal (170) and write the following Arduino-framework code:
shiftOut(SER_PIN, SRCLK_PIN, MSBFIRST, 170);
digitalWrite(RCLK_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(RCLK_PIN, LOW);
The Outcome: You upload the code. Valves 2, 4, 6, and 8 click open. Valves 1, 3, 5, and 7 remain closed. The system is doing the exact opposite of your binary list.
What Went Wrong: The error is not in your math; it is in the physical mapping of the binary list. The shiftOut() function is set to MSBFIRST (Most Significant Bit First). This means the leftmost '1' in your list (10101010) is pushed into the shift register first and ends up at the Q7 output pin. However, on your breadboard, you wired Q0 to Valve 1, Q1 to Valve 2, and so on. The bit order was physically reversed relative to your logical list.
The Fix: You have two choices. You can rewire the breadboard (tedious), or you can change a single parameter in your code to shift the Least Significant Bit first, aligning the software list with the hardware layout:
- Locate the
shiftOutfunction in your loop. - Change the bit-order parameter from
MSBFIRSTtoLSBFIRST. - Re-upload the firmware; the ESP32 now pushes the rightmost bit into Q0, perfectly matching your physical valve layout.
Common Confusions: Bit Index vs. Bit Weight
The most common mistake when reading a list of binary numbers from a datasheet is confusing the index of the bit with its decimal weight. Datasheets for port expanders like the PCF8574 label pins as P0 through P7. P0 is the index, but its weight is 1 (2^0). P7 is the index, but its weight is 128 (2^7).
| Pin Label (Index) | Binary Position | Decimal Weight | Hex Equivalent |
|---|---|---|---|
| P0 | Bit 0 (LSB) | 1 | 0x01 |
| P1 | Bit 1 | 2 | 0x02 |
| P2 | Bit 2 | 4 | 0x04 |
| P3 | Bit 3 | 8 | 0x08 |
| P4 | Bit 4 | 16 | 0x10 |
| P5 | Bit 5 | 32 | 0x20 |
| P6 | Bit 6 | 64 | 0x40 |
| P7 | Bit 7 (MSB) | 128 | 0x80 |
If a datasheet instructs you to "set bit P3 HIGH to enable the interrupt," you must send a binary list where the 4-weight position is a 1 (e.g., 00001000), not the third position from the left. For a deeper dive into how microcontrollers handle these bitwise operations, the Arduino byte data type documentation provides excellent foundational syntax.
FAQ: Binary Lists in Embedded Systems
Q: Why do I2C addresses in datasheets look different from the binary list I pass in code?
A: I2C addresses are typically 7 bits long. However, microcontrollers transmit them inside an 8-bit byte. The 8th bit (the LSB) is reserved for the Read/Write flag (0 for Write, 1 for Read). If a datasheet lists the 7-bit address as 0100000 (0x20), your code must shift it left by one bit to make room for the R/W flag, resulting in 01000000 (0x40) for a write operation. Libraries like Wire.h handle this shift automatically, which often causes confusion when reading raw logic analyzer traces.
Q: Can I write binary numbers directly in my C++ code instead of converting to decimal?
A: Yes. Modern C++ compilers (including the GCC ARM toolchain used for ESP32 and STM32) support binary literals. You can prefix your list of binary numbers with 0b. For example, shiftOut(SER, CLK, MSBFIRST, 0b10101010); is perfectly valid, compiles to the exact same machine code as 170, and makes your firmware vastly easier to read when cross-referencing hardware schematics.
Q: What happens if my binary list is longer than 8 bits?
A: Standard shift registers and GPIO ports are 8 bits wide. If you need to send a 16-bit list of binary numbers (e.g., to daisy-chained 74HC595s), you must call the shiftOut() function twice. Send the most significant byte first, followed by the least significant byte, before pulsing the latch pin. The shift register chain will physically cascade the bits into the correct 16 output pins.






