The Binary Code for 6: Theory and Embedded Application

The binary code for the decimal number 6 in a standard 4-bit system is 0110 (or 00000110 in 8-bit). In hexadecimal, this is represented as 0x06. The math is straightforward: the second bit (value 2) and the third bit (value 4) are HIGH, while the first bit (value 1) and fourth bit (value 8) are LOW. Therefore, 4 + 2 = 6.

While converting decimal to binary is a basic classroom exercise, recognizing specific binary states in real-time is a critical skill in embedded debugging. When you are reverse-engineering a legacy parallel bus, monitoring a state machine, or sniffing address lines on a microcontroller, you often need to trigger an action only when the bus hits a specific value. In this guide, we will build a "State 6 Sniffer"—a hardware tool that monitors a 4-bit digital input and fires a physical relay the millisecond it detects the binary code for 6 (0110).

Bench Tip: In digital logic, bit ordering matters. Always define whether your system is LSB-first (Least Significant Bit) or MSB-first. For this build, we will map Bit 0 (LSB, value 1) to the lowest GPIO pin and Bit 3 (MSB, value 8) to the highest.

Parts List and Pin Mapping for the Binary Trigger

This project targets the ESP32 DevKit V1 (30-pin variant with the ESP-WROOM-32 module). We specifically use the input-only pins on the ESP32 for our 4-bit bus because they do not drive boot-strapping logic on startup, preventing unintended relay toggling when you press the EN/RESET button.

ComponentExact Variant / SpecificationEstimated Cost
MicrocontrollerESP32 DevKit V1 (30-pin, ESP-WROOM-32)$6.50
Input Source4-Position DIP Switch (2.54mm pitch)$0.50
Pull-up Resistors4x 10kΩ Through-hole (1/4W)$0.10
Output Actuator5V Relay Module (Opto-isolated, 3.3V logic compatible)$2.00
Wiring22 AWG Solid Core Hookup Wire$5.00

Critical Hardware Note: GPIOs 34, 35, 36, and 39 on the ESP32 are input-only. According to the Espressif GPIO documentation, these pins do not have internal pull-up or pull-down resistors. You must use external 10kΩ resistors tied to 3.3V, or the inputs will float and trigger the relay erratically.

Pin Mapping Table

FunctionESP32 GPIOBinary WeightExternal Components
Bit 0 (LSB)GPIO 34110kΩ pull-up to 3.3V
Bit 1GPIO 35210kΩ pull-up to 3.3V
Bit 2GPIO 36410kΩ pull-up to 3.3V
Bit 3 (MSB)GPIO 39810kΩ pull-up to 3.3V
Relay ControlGPIO 26N/ADirect to Relay IN pin

Wiring and Build Steps

  1. Prep the DIP Switch: Insert the 4-position DIP switch into the breadboard, straddling the center trench. Identify Pin 1 (usually marked with a dot or bevel). This will be Bit 0 (LSB).
  2. Wire the Inputs: Connect the four switch pins on one side to ESP32 GPIOs 34, 35, 36, and 39 respectively. Connect the opposite side of the switch to the breadboard ground (GND) rail.
  3. Install Pull-ups: Insert a 10kΩ resistor between each of the four input GPIOs and the 3.3V power rail. Do not skip this step.
  4. Wire the Relay Module: Connect the relay module VCC to the ESP32's VIN (5V) pin, not the 3.3V pin. Connect GND to GND. Connect the IN pin to GPIO 26.
  5. Verify Logic Levels: Ensure your relay module is explicitly rated for 3.3V logic triggering. Standard 5V opto-isolated modules often require 4.5V on the IN pin to switch the internal LED; a 3.3V logic-compatible module includes an onboard NPN transistor or MOSFET to bridge this gap.

Complete ESP32 Firmware with Bitwise Masking

The following C++ code is written for the Arduino IDE using the ESP32 board manager. It uses bitwise operators to assemble the pin states into a single byte, then compares it against 0x06.

/*
 * Binary Code for 6 (0110) State Sniffer
 * Target Board: ESP32 DevKit V1 (30-pin)
 * Author: ElectricalFlux Bench Team
 */

// Pin Definitions
const uint8_t PIN_BIT0 = 34; // LSB (Value 1)
const uint8_t PIN_BIT1 = 35; // Value 2
const uint8_t PIN_BIT2 = 36; // Value 4
const uint8_t PIN_BIT3 = 39; // MSB (Value 8)
const uint8_t PIN_RELAY = 26;

// State tracking to prevent relay chatter
bool lastTriggerState = false;

void setup() {
  Serial.begin(115200);
  
  // Configure input pins (External pull-ups used, so INPUT is sufficient)
  pinMode(PIN_BIT0, INPUT);
  pinMode(PIN_BIT1, INPUT);
  pinMode(PIN_BIT2, INPUT);
  pinMode(PIN_BIT3, INPUT);
  
  // Configure relay output
  pinMode(PIN_RELAY, OUTPUT);
  digitalWrite(PIN_RELAY, HIGH); // Assuming active-LOW relay module (standard)
  
  Serial.println("State Sniffer Initialized. Waiting for binary 0110 (6)...");
}

void loop() {
  // Read pins and assemble into a single 8-bit integer using bitwise shifts
  uint8_t busState = 0;
  busState |= (digitalRead(PIN_BIT0) == HIGH ? 1 : 0);
  busState |= (digitalRead(PIN_BIT1) == HIGH ? 2 : 0);
  busState |= (digitalRead(PIN_BIT2) == HIGH ? 4 : 0);
  busState |= (digitalRead(PIN_BIT3) == HIGH ? 8 : 0);
  
  // Check if the state exactly matches the binary code for 6 (0x06)
  bool currentTriggerState = (busState == 0x06);
  
  // Edge detection: only fire serial logs and relay on state CHANGE
  if (currentTriggerState != lastTriggerState) {
    if (currentTriggerState) {
      Serial.println("[TRIGGER] Binary 0110 detected! Energizing relay.");
      digitalWrite(PIN_RELAY, LOW); // Active-LOW relay: LOW turns it ON
    } else {
      Serial.print("[RELEASE] Bus changed to: ");
      Serial.println(busState, BIN);
      digitalWrite(PIN_RELAY, HIGH); // Turn relay OFF
    }
    lastTriggerState = currentTriggerState;
  }
  
  // Small delay to debounce mechanical DIP switches and yield to RTOS
  delay(10); 
}

Debugging: When the Trigger Fails to Fire

When your sniffer fails to trigger on 0110, or the ESP32 crashes outright, follow this diagnostic path. Here are the first three things to check:

  1. Measure the Pull-up Voltage: Put your multimeter in DC voltage mode. Probe GPIO 34 with the DIP switch open. If it reads < 3.0V, your external 10kΩ resistors are missing or wired to GND instead of 3.3V. Floating inputs will read random noise, occasionally hitting 6 but never holding it.
  2. Check DIP Switch Polarity: If the binary code for 6 triggers when you set the switches to 1001 (decimal 9), your LSB and MSB are swapped. Flip the physical switch orientation or reverse the pin definitions in the code.
  3. Verify Relay Power Isolation: If the ESP32 resets the moment the relay clicks, you have wired the relay VCC to the ESP32's 3.3V pin. The relay coil draws ~70mA, instantly collapsing the 3.3V regulator.

Common Error Strings and Ranked Causes

Error 1: Brownout detector was triggered

  • Cause A (Most Likely): Relay module VCC is wired to the 3.3V pin instead of VIN/5V. The voltage sag triggers the ESP32's internal brownout protection.
  • Cause B: Your USB cable is low-quality and cannot supply the 500mA required when the relay engages. Swap to a heavy-gauge data cable.

Error 2: error: 'GPIO_NUM_36' was not declared in this scope

  • Cause A: You are using ESP-IDF macros in an Arduino sketch without including #include "driver/gpio.h". Stick to standard Arduino integers (e.g., 36) as shown in the code above.
  • Cause B: You selected the wrong board in the Arduino IDE Tools menu. Ensure "ESP32 Dev Module" is selected, not a generic ESP8266 or Arduino Uno board.

Decision Tree: Choosing Your Binary Decoding Method

How you read binary states in firmware depends entirely on the frequency of the bus you are sniffing. Use this decision path to select your implementation strategy.

Signal FrequencyMethodPros / ConsVerdict
< 100 Hz
(Manual switches, slow state machines)
Standard digitalRead() polling in loop() Pro: Easy to read, cross-platform.
Con: Consumes CPU cycles.
DEFAULT PICK. Use the bitwise polling method provided in this article.
100 Hz - 10 kHz
(Audio clocks, moderate serial buses)
Direct Port Manipulation (e.g., REG_READ(GPIO_IN_REG)) Pro: Reads 32 pins in one clock cycle.
Con: Highly hardware-specific; breaks if you move to ESP32-S3.
Use only if standard polling drops states. Map pins to a single 32-bit GPIO register.
> 10 kHz
(High-speed address buses, SPI lines)
Hardware Interrupts + DMA or Logic Analyzer Pro: Zero missed states.
Con: Overkill for simple debugging; requires complex ISR handling.
Abandon the ESP32 for this task. Buy a $15 USB Logic Analyzer (Saleae clone) and use PulseView.

Extending and Simplifying the Build

Once you have the 4-bit sniffer working, you will inevitably want to adapt it for different bench scenarios.

How to Extend to 8-Bit or 16-Bit

Do not wire 16 individual DIP switches to 16 ESP32 GPIOs. You will run out of pins and create a wiring nightmare. Instead, extend the build by adding a 74HC165 Parallel-in/Serial-out Shift Register. Wire your 8 or 16 input lines to the 74HC165, and use the ESP32's SPI or bit-banged shift-in functions to read the entire bus state over just 3 GPIO pins (Clock, Latch, Data). You can then compare the resulting 16-bit integer against 0x0006 or any other target value.

How to Simplify (No Code Required)

If you do not want to write firmware, or if you need to decode the binary code for 6 at speeds far beyond what a microcontroller can handle, strip the ESP32 out of the circuit entirely. Use a 74HC85 4-bit Magnitude Comparator IC.

According to the Texas Instruments 74HC85 datasheet, you can hardwire the 'B' input pins of the IC to 0110 (tie B0 and B3 to GND, tie B1 and B2 to VCC). Feed your live bus into the 'A' inputs. The IC's A=B output pin will instantly go HIGH whenever the live bus matches the binary code for 6, with propagation delays measured in nanoseconds rather than microseconds. This is the ultimate hardware-level solution for high-speed digital debugging.