Introduction: Bridging Digital Logic and Physical Hardware
No money? No problem! Help us pay the cloud hosting bills without opening your wallet—just give
this ad link a click!😉💸
Every modern computer operates on binary arithmetic. While software engineers usually work with high-level numbers, microcontrollers process information exclusively through high (1) and low (0) voltage states.
In this article, you will explore how to build a 4-bit binary LED counter using an Arduino. Specifically, this project connects four light-emitting diodes (LEDs) to digital pins, turning abstract machine code into a physical, visible counter that cycles from decimal 0 to 15 ( to ).
Why Build This Project?
Before diving into the hardware, you should understand the motivation behind this build:
- Visualizing Binary Representation:
Most beginners struggle to conceptualize how bits combine into values. By assigning each LED to a binary exponent (), you observe binary addition happening in real time. - Mastering Bitwise Operators:
Instead of writing sixteen tediousif-elseconditions, the sketch uses fast bitwise operations (>>and&). Consequently, you learn how embedded systems manipulate individual bits inside a single byte. - Protecting Electronic Components:
Directly connecting LEDs to microcontroller pins will destroy both components through overcurrent. Therefore, this project implements current-limiting resistors to illustrate fundamental circuit safety.
What Components You Need
To replicate this project, gather the following parts referenced in the project README.md:
- 1x Arduino Uno or Nano (acts as the controller)
- 4x LEDs (any color)
- 4x 330Ω Resistors (current-limiting protection)
- 1x Solderless Breadboard
- Jumper Wires (male-to-male)
Understanding the Circuit Architecture
First, let us examine how electric current flows through the setup. The design utilizes four independent digital output channels and a single shared ground rail

Pin Mapping and Bit Significance
Each Arduino pin corresponds directly to a specific binary place value:
- Pin 13 → LED 1 (Bit 0 / Least Significant Bit – 20 = 1): This LED toggles on every single count increment.
- Pin 12 → LED 2 (Bit 1 – 21 = 2): This LED changes state every two counts.
- Pin 11 → LED 3 (Bit 2 – 22= 4): This LED changes state every four counts.
- Pin 10 → LED 4 (Bit 3 / Most Significant Bit – 23= 8): This LED illuminates only when the value reaches 8 or higher.
Next, you connect each pin to the anode (longer leg) of an LED through a resistor. Meanwhile, all LED cathodes (shorter legs) tie directly to the breadboard ground rail, completing the circuit back to the Arduino GND header.
Binary State Reference Table
Four bits provide distinct combinations. As a result, the circuit counts from 0 to 15 before looping back to the beginning:
beginning:
| Decimal Value | 4-Bit Binary | LED 4 (Pin 10 – MSB) | LED 3 (Pin 11) | LED 2 (Pin 12) | LED 1 (Pin 13 – LSB) |
|---|---|---|---|---|---|
| 0 | 0000 | OFF | OFF | OFF | OFF |
| 1 | 0001 | OFF | OFF | OFF | ON |
| 2 | 0010 | OFF | OFF | ON | OFF |
| 3 | 0011 | OFF | OFF | ON | ON |
| 4 | 0100 | OFF | ON | OFF | OFF |
| 5 | 0101 | OFF | ON | OFF | ON |
| 6 | 0110 | OFF | ON | ON | OFF |
| 7 | 0111 | OFF | ON | ON | ON |
| 8 | 1000 | ON | OFF | OFF | OFF |
| 9 | 1001 | ON | OFF | OFF | ON |
| 10 | 1010 | ON | OFF | ON | OFF |
| 11 | 1011 | ON | OFF | ON | ON |
| 12 | 1100 | ON | ON | OFF | OFF |
| 13 | 1101 | ON | ON | OFF | ON |
| 14 | 1110 | ON | ON | ON | OFF |
| 15 | 1111 | ON | ON | ON | ON |
Technical Code Breakdown
The program in binary-led.ino features clean, modular code. Let us walk through how the software directs the hardware.
1. Initialization in setup()
int led1 = 13;
int led2 = 12;
int led3 = 11;
int led4 = 10;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
}
First, the program declares four integer variables to store the pin assignments. Inside setup(), the pinMode() calls configure all four pins as low-impedance OUTPUT channels, enabling them to drive current through the LEDs.
2. The Main Counter Loop in loop()
void loop() {
for (int i = 0; i < 16; i++) {
writeLEDs(i);
delay(1000); // Wait for 1 second
}
}
Next, the loop() function runs an iterative for loop from index 0 to 15. For each iteration, the loop passes the current number into writeLEDs() and delays execution for 1000 milliseconds (one second). Consequently, the viewer clearly sees each step in the count.
3. Bit Extraction in writeLEDs()
void writeLEDs(int value) {
digitalWrite(led1, (value >> 0) & 1); // Write the least significant bit to led1
digitalWrite(led2, (value >> 1) & 1); // Write the second bit to led2
digitalWrite(led3, (value >> 2) & 1); // Write the third bit to led3
digitalWrite(led4, (value >> 3) & 1); // Write the fourth bit to led4
}
This helper function handles the core mathematical conversion. Instead of inspecting each possible number with conditionals, it applies two bitwise operations:
- Right Bit Shift (
>>): The expression(value >> n)shifts all bits invalueto the right bynpositions. As a result, the target bit lands in position 0. - Bitwise AND Mask (
& 1): The expression& 1masks off all higher bits, keeping only the lowest bit. Thus, the expression produces strictly0(interpreted asLOW/ 0 V) or1(interpreted asHIGH/ 5 V).
For instance, consider decimal value 11 (1011 in binary):
(11 >> 0) & 11→ Pin 13 drivesHIGH(LED 1 lights up).(11 >> 1) & 11→ Pin 12 drivesHIGH(LED 2 lights up).(11 >> 2) & 10→ Pin 11 drivesLOW(LED 3 stays dark).(11 >> 3) & 11→ Pin 10 drivesHIGH(LED 4 lights up).
How to Test and Run the System
- Launch your Arduino IDE and open
binary-led.ino. - Wire the hardware on your breadboard according to the circuit diagram.
- Connect your Arduino board via USB and select the appropriate board and COM port.
- Click Upload.
Immediately, your Arduino begins counting upwards in binary, cycling every second and resetting seamlessly after reaching 15!
Conclusion
In summary, this project combines digital circuit principles with efficient microcontroller programming. By utilizing bitwise right-shift and mask operations, the Arduino converts decimal values into hardware control signals with minimal computation. You can expand this project further by adding an 8-bit shift register (such as the 74HC595) or incorporating tactile buttons to step through values manually.