Decimal to binary and binary to decimal conversion is the mathematical process of translating base-10 numbers (our everyday counting system) into base-2 numbers (the 1s and 0s that digital circuits and microcontrollers actually process), and vice versa. When you are writing firmware for an ESP32 or setting the DIP switches on a stepper motor driver, the silicon does not care about your base-10 inputs; it only understands high and low voltage states. Understanding this translation changes how you directly manipulate hardware registers, configure pulse-width modulation (PWM) duty cycles, and decode raw I2C sensor payloads. A common trap for beginners is confusing base conversion with bitwise logic operations (like AND, OR, and XOR), assuming hexadecimal is a separate mathematical base rather than a shorthand, or confusing a bit's index position with its decimal weight.

The Core Concept: Base-10 vs. Base-2 at the Bench

In the physical world of a workbench, binary is just voltage. For a 5V Arduino Uno (ATmega328P), a 5V logic level represents a 1, and 0V represents a 0. For a 3.3V ESP32, the threshold drops to 3.3V. When a datasheet tells you to write a specific value to a control register, it is asking you to set a specific combination of physical pins or internal transistor gates high or low simultaneously.

Base-10 (decimal) uses ten digits (0-9) and rolls over to the next place value at ten. Base-2 (binary) uses only two digits (0-1) and rolls over at two. Because microcontrollers process data in 8-bit, 16-bit, or 32-bit chunks, we group these 1s and 0s into bytes. An 8-bit byte can represent decimal values from 0 to 255. Mastering the mental translation between these two systems is what separates a maker who relies entirely on high-level Arduino library functions from one who can write bare-metal register code to achieve microsecond timing precision.

Step-by-Step: Decimal to Binary and Binary to Decimal Conversion

While there are multiple mathematical ways to convert bases, the "subtraction method" (using powers of 2) is the fastest for bench work because it maps directly to how memory registers are structured.

Worked Example 1: Decimal to Binary (Convert 154)

Write out the 8-bit place values from left to right: 128, 64, 32, 16, 8, 4, 2, 1.

  1. 128: Can we subtract 128 from 154? Yes. (154 - 128 = 26). Write a 1.
  2. 64: Can we subtract 64 from 26? No. Write a 0.
  3. 32: Can we subtract 32 from 26? No. Write a 0.
  4. 16: Can we subtract 16 from 26? Yes. (26 - 16 = 10). Write a 1.
  5. 8: Can we subtract 8 from 10? Yes. (10 - 8 = 2). Write a 1.
  6. 4: Can we subtract 4 from 2? No. Write a 0.
  7. 2: Can we subtract 2 from 2? Yes. (2 - 2 = 0). Write a 1.
  8. 1: Can we subtract 1 from 0? No. Write a 0.

Result: Decimal 154 = Binary 10011010.

Worked Example 2: Binary to Decimal (Convert 11010110)

Map each bit to its place value and add only the values where the bit is 1.

  • Bit 7 (1): 128
  • Bit 6 (1): 64
  • Bit 5 (0): 0
  • Bit 4 (1): 16
  • Bit 3 (0): 0
  • Bit 2 (1): 4
  • Bit 1 (1): 2
  • Bit 0 (0): 0

Calculation: 128 + 64 + 16 + 4 + 2 = 214.

Where You Meet This in Practice

You will encounter the need for decimal to binary and binary to decimal conversion in several specific hardware scenarios:

  • GPIO Direction Registers: When bypassing slow pinMode() functions on an ATmega328P, you write directly to the DDRx registers. Setting a bit to 1 makes that physical pin an output; 0 makes it an input.
  • I2C Addressing: I2C sensors use 7-bit addresses. If a datasheet lists an address as 0x48 (hex), you must convert this to binary (1001000) to understand how the address shifts when the read/write bit is appended.
  • DIP Switches on Motor Drivers: Stepper drivers like the TB6600 or DM542 use physical DIP switches to set microstepping and peak current. The manual provides a binary table; you must flip the switches to match the 1s and 0s for your desired amperage.
  • PWM Duty Cycle Registers: On 8-bit timers, a value of 255 (11111111) is 100% duty cycle, while 127 (01111111) is roughly 50%.

Real-World Scenario Walkthrough: Misconfiguring an ATmega328P GPIO Register

Abstract math is fine until it causes a short circuit on your bench. Here is a real-world failure mode involving direct port manipulation.

The Setup: A maker is driving a 12V relay bank via a ULN2803 Darlington array using an Arduino Uno. To achieve microsecond switching speeds for a high-frequency pulse valve, they bypass digitalWrite() and write directly to the PORTB register. They need pins 8, 9, and 10 HIGH. According to the ATmega328P datasheet, these map to PORTB bits 0, 1, and 2.

The Numbers: They want bits 0, 1, and 2 to be 1.
Binary: 00000111.
Decimal conversion: 4 + 2 + 1 = 7.
They write DDRB = 7; and PORTB = 7;. The relays click on perfectly.

The Outcome & What Went Wrong: Later, they decide to add pin 13 (the onboard LED, which is PORTB bit 5) to the same register write without turning off the relays. They need bits 0, 1, 2, and 5 to be 1.
Here, the maker makes a critical bench error: they confuse the bit index (5) with the decimal weight. They mistakenly calculate the decimal value of bit 5 as 16 (which is actually the weight of bit 4).
Their flawed math: 16 + 4 + 2 + 1 = 23.
They upload PORTB = 23;.
The binary for 23 is 00010111. This turns on bits 0, 1, 2, and 4 (Pin 12). Pin 13 stays off. Worse, Pin 12 was wired to a limit switch input on the relay bank. Forcing Pin 12 HIGH back-fed voltage into the limit switch sensor, frying the optocoupler on the driver board.

The Fix: Always map the bit index to its power-of-2 weight. Bit 5 is $2^5$, which is 32. The correct decimal math is 32 + 4 + 2 + 1 = 39 (Binary 00100111). Using binary literals in code (e.g., PORTB = B00100111;) prevents this specific mental math error entirely.

Quick Reference: 8-Bit Binary to Decimal Chart

Keep this table handy when debugging register values in a logic analyzer or oscilloscope capture.

Binary (8-Bit) Decimal Hexadecimal Common Bench Application
11111111 255 0xFF 100% PWM duty cycle / All pins OUTPUT
10000000 128 0x80 Only MSB (Bit 7) HIGH
01111111 127 0x7F ~50% PWM duty cycle
01010101 85 0x55 Alternating bits (often used for bus testing)
00111100 60 0x3C Common I2C address (e.g., LCD backpacks)
00010000 16 0x10 Only Bit 4 HIGH
00001010 10 0x0A Bits 1 and 3 HIGH
00000000 0 0x00 0% PWM / All pins INPUT (High-Z)

Frequently Asked Questions

Why do datasheets use hexadecimal instead of just binary or decimal?
Hexadecimal (base-16) is used because it maps perfectly to binary without the visual clutter. One hex digit represents exactly four binary bits (a nibble). For example, the 8-bit binary 11010110 is easily split into 1101 (D) and 0110 (6), resulting in 0xD6. It is much easier for a human to read 0xD6 than a long string of 1s and 0s, and it avoids the mental math required to convert directly to decimal. The ESP32 Technical Reference Manual relies heavily on hex for this exact reason.

How do I handle fractional decimal to binary conversion for ADCs?
For Analog-to-Digital Converters (ADCs), you are usually dealing with integer mappings (e.g., mapping 0-5V to 0-1023 on a 10-bit ADC). However, if you are configuring a fractional-N PLL or a DAC reference, fractional conversion involves multiplying the decimal fraction by 2 repeatedly and recording the integer part (1 or 0) until you reach your desired bit depth. For 99% of DIY microcontroller work, stick to integer conversion and let the compiler handle floating-point math.

Is there a difference between binary conversion and BCD (Binary-Coded Decimal)?
Yes, and confusing them will break your code. Standard binary converts the entire decimal number into base-2 (e.g., decimal 25 = 00011001). BCD encodes each individual decimal digit into its own 4-bit binary sequence. In BCD, decimal 25 becomes 0010 0101 (2 is 0010, 5 is 0101). BCD is heavily used in real-time clock (RTC) modules like the DS3231 to make displaying numbers on 7-segment displays easier, but it is mathematically distinct from standard base-2 conversion.