BLOG / TUTORIALS / 7 Segment Display Arduino Tutorial: Wiri…
Blog Post

7 Segment Display Arduino Tutorial: Wiring, Code, and Multi-Digit Control

Viktor Build ~10 min read

Wire and code a 7 segment display with Arduino. Covers single-digit wiring, multiplexing for 4-digit displays, and 74HC595 shift register control.

So you want to add numbers to your Arduino project. A 7 segment display is the simplest way to show digits — countdown timers, temperature readouts, game scores, or even a simple clock. But the wiring can be confusing when you first look at those 10 pins, and getting multiple digits working without burning through all your I/O pins takes a bit of planning.

This guide covers everything: how to wire a 7 segment display Arduino project, whether you have a common cathode or common anode part, how to write clean code that updates the display smoothly, and — most importantly — how to control multiple digits with multiplexing or a shift register. By the end, you’ll be able to add a reliable numeric display to any build.

Understanding 7 Segment Display Basics

A 7 segment display is really just eight LEDs arranged in a specific pattern: seven segments (labeled A through G) form the digit shape, plus an eighth LED for the decimal point (DP). Each segment has its own pin, and the other side of each LED is tied together in one of two configurations:

Configuration Common Pin Polarity Code Logic
Common Cathode Ground (GND) HIGH to turn segment ON digitalWrite(pin, HIGH) lights segment
Common Anode VCC (5V or 3.3V) LOW to turn segment ON digitalWrite(pin, LOW) lights segment

How do you know which one you have? Check the datasheet. If you bought a cheap bundle without documentation, use a multimeter in diode mode: touch the common pin (usually pin 3 or 8 on a standard 10-pin package) to GND, then probe each segment pin. If segments light when you probe, it’s common cathode. If they don’t, try connecting the common pin to VCC instead.

Most tutorials assume common cathode because the logic is more intuitive. I’ll include code for both.

Parts List for This Tutorial

  • Arduino Uno (or any compatible board)
  • 7 segment display (common cathode or common anode)
  • 8x 220Ω resistors (one per segment — never skip these)
  • Jumper wires and breadboard
  • Optional: 74HC595 shift register (for multi-digit setups)
  • Optional: push buttons for interactive examples

Wiring a Single 7 Segment Display to Arduino

The direct approach uses 8 digital pins on your Arduino — one per segment. For a simple project this is fine, but it leaves you with limited pins for sensors or buttons.

Common Cathode Wiring

Connect each segment pin (A–G, DP) through a 220Ω resistor to an Arduino digital pin. Connect the common cathode pin(s) directly to GND.

Standard pin mapping (looking at the display from the front, pins numbered counter-clockwise from the top-left notch):

  • Pin 1 (top-left) → Segment E → Arduino pin 7
  • Pin 2 (top-right) → Segment D → Arduino pin 6
  • Pin 3 → Common Cathode → GND
  • Pin 4 → Segment C → Arduino pin 5
  • Pin 5 → DP → Arduino pin 4
  • Pin 6 → Segment B → Arduino pin 3
  • Pin 7 → Segment A → Arduino pin 2
  • Pin 8 → Common Cathode → GND
  • Pin 9 → Segment F → Arduino pin 8
  • Pin 10 → Segment G → Arduino pin 9

Double-check your specific display’s pinout — the physical arrangement varies between manufacturers. A quick continuity test with a multimeter saves hours of frustration.

Common Anode Wiring

Same wiring, but the common pin(s) connect to 5V instead of GND, and your code logic inverts (LOW to light a segment, HIGH to turn it off).

Arduino Code: Displaying a Single Digit

Here’s the cleanest way to drive a 7 segment display. We define which segments light for each digit 0–9 using a lookup table, then write a function that takes a number and turns on the right segments.

// 7 Segment Display Arduino - Single Digit (Common Cathode)
// Segment pins connected to Arduino digital pins 2-9

// Map segment letters to Arduino pins
#define SEG_A 2
#define SEG_B 3
#define SEG_C 4
#define SEG_D 5
#define SEG_E 6
#define SEG_F 7
#define SEG_G 8
#define SEG_DP 9

// Segment activation pattern for digits 0-9 (common cathode)
// Order: DP, G, F, E, D, C, B, A
byte digitPatterns[10] = {
  0b00111111, // 0
  0b00000110, // 1
  0b01011011, // 2
  0b01001111, // 3
  0b01100110, // 4
  0b01101101, // 5
  0b01111101, // 6
  0b00000111, // 7
  0b01111111, // 8
  0b01101111  // 9
};

void setup() {
  // Set all segment pins as outputs
  for(int pin = 2; pin <= 9; pin++) {
    pinMode(pin, OUTPUT);
    digitalWrite(pin, LOW); // start with all segments off
  }
}

void loop() {
  // Count from 0 to 9
  for(int digit = 0; digit <= 9; digit++) {
    displayDigit(digit, false); // false = no decimal point
    delay(1000);
  }
}

void displayDigit(int num, bool showDP) {
  if(num < 0 || num > 9) return; // safety check
  
  byte pattern = digitPatterns[num];
  if(showDP) pattern |= 0b10000000; // set DP bit
  
  // Write each segment
  digitalWrite(SEG_A, pattern & 0x01);
  digitalWrite(SEG_B, pattern & 0x02);
  digitalWrite(SEG_C, pattern & 0x04);
  digitalWrite(SEG_D, pattern & 0x08);
  digitalWrite(SEG_E, pattern & 0x10);
  digitalWrite(SEG_F, pattern & 0x20);
  digitalWrite(SEG_G, pattern & 0x40);
  digitalWrite(SEG_DP, pattern & 0x80);
}

For common anode, change every digitalWrite in displayDigit() to invert the bit:

digitalWrite(SEG_A, !(pattern & 0x01)); // note the !
// ... repeat for all segments

Multi-Digit Displays: Why Direct Wiring Falls Apart

A two-digit display needs 16 pins (16 segments). A four-digit display needs 32 pins. Your Arduino Uno has only 14 digital I/O pins. You need a smarter approach.

Two standard solutions exist:

  1. Multiplexing — use 8 segment pins shared across all digits + one common pin per digit. You rapidly switch between digits faster than the eye can see.
  2. Shift registers — use a 74HC595 to drive all segment pins with only 3 Arduino pins, and still use separate pins for digit selection.

Multiplexing: The Time-Sharing Trick

Multiplexing works because of persistence of vision. You light one digit at a time, cycle through all digits in a few milliseconds, and the human eye blends them into a steady display.

Wiring for 4-Digit Multiplexed Display

  • Segment pins (A–G, DP) connect through resistors to Arduino pins 2–9 (shared)
  • Each digit’s common pin connects to an Arduino pin (10, 11, 12, 13) through an NPN transistor (e.g., 2N2222). This lets you sink enough current without damaging the Arduino.

Multiplexed Code

// 4-digit multiplexed 7 segment display (common cathode)
// Segment pins: 2-9
// Digit control pins: 10, 11, 12, 13 (each through NPN transistor to GND)

const int segmentPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
const int digitPins[] = {10, 11, 12, 13};
const int numDigits = 4;

byte digits[numDigits] = {1, 2, 3, 4}; // what to display

void setup() {
  for(int i = 0; i < 8; i++) pinMode(segmentPins[i], OUTPUT);
  for(int i = 0; i < numDigits; i++) {
    pinMode(digitPins[i], OUTPUT);
    digitalWrite(digitPins[i], LOW); // all digits off
  }
}

void loop() {
  // Refresh the display continuously
  for(int i = 0; i < numDigits; i++) {
    showDigit(i, digits[i]);
    delay(5); // 5ms per digit = 20ms cycle (50Hz refresh)
  }
}

void showDigit(int position, int value) {
  // Turn off all digits first
  for(int i = 0; i < numDigits; i++) {
    digitalWrite(digitPins[i], LOW);
  }
  
  // Set segment pattern
  byte pattern = digitPatterns[value]; // from earlier example
  for(int seg = 0; seg < 8; seg++) {
    digitalWrite(segmentPins[seg], pattern & (1 << seg));
  }
  
  // Enable the correct digit
  digitalWrite(digitPins[position], HIGH);
}

Key tuning parameter: the delay(5) value. Too fast (< 2ms) and segments may not reach full brightness. Too slow (> 10ms) and you’ll see flickering. I find 3–5ms per digit works well for most displays.

Using a Shift Register (74HC595)

The shift register method uses only three Arduino pins to control all segments, leaving the rest for sensors or other tasks. The 74HC595 is a serial-in, parallel-out shift register — you push data one bit at a time, and it outputs all 8 bits simultaneously.

Shift Register Wiring

  • 74HC595 pins 14 (DS) → Arduino pin 11 (data)
  • 74HC595 pin 12 (ST_CP) → Arduino pin 12 (latch)
  • 74HC595 pin 11 (SH_CP) → Arduino pin 13 (clock)
  • 74HC595 pins Q0–Q7 → 220Ω resistors → segment pins A–G, DP
  • 74HC595 pin 10 (MR) → 5V (master reset, tied high)
  • 74HC595 pin 13 (OE) → GND (output enable, tied low)

For multi-digit, keep the common cathode/anode pins on separate Arduino pins (or daisy-chain more shift registers).

Shift Register Code

// Single digit with 74HC595 shift register
// Data pin 11, Latch pin 12, Clock pin 13

const int dataPin = 11;
const int latchPin = 12;
const int clockPin = 13;

void setup() {
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
}

void loop() {
  for(int digit = 0; digit <= 9; digit++) {
    // Shift out the pattern (common cathode)
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, digitPatterns[digit]);
    digitalWrite(latchPin, HIGH);
    delay(1000);
  }
}

Daisy-Chaining for Multiple Digits

To drive four digits with shift registers, use two 74HC595s: one for segments (shared), one for digit selection. Feed the segment patterns to the first shift register, then the digit select pattern to the second — you can daisy-chain them by connecting the Q7S pin of the first to the DS pin of the second.

// Two daisy-chained 74HC595s: first for segments, second for digit select
void displayFourDigits(byte digits[4]) {
  for(int i = 0; i < 4; i++) {
    byte digitSelect = 1 << i; // one-hot: 1,2,4,8
    byte segmentPattern = digitPatterns[digits[i]];
    
    digitalWrite(latchPin, LOW);
    // Shift digit select first (it's further down the chain)
    shiftOut(dataPin, clockPin, MSBFIRST, digitSelect);
    // Then shift segment pattern
    shiftOut(dataPin, clockPin, LSBFIRST, segmentPattern);
    digitalWrite(latchPin, HIGH);
    
    delay(5);
  }
}

Real-World Example: Digital Temperature Display

Combine what you’ve learned with a TMP36 temperature sensor and display the reading on a 4-digit display using multiplexing. Here’s the core logic:

int readTemperature() {
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.0);
  return (voltage - 0.5) * 100; // TMP36: 10mV per °C, offset 0.5V
}

void loop() {
  int temp = readTemperature(); // e.g., 23°C
  digits[0] = temp / 10;        // tens digit
  digits[1] = temp % 10;        // ones digit
  digits[2] = 0x7F;             // show "°" by lighting segments A, B, F, G
  digits[3] = 0x63;             // show "C" (segments A, D, E, F)
  
  // ... multiplexing refresh loop from above
}

For the degree symbol, you can define a custom pattern: 0b01100011 lights segments F, G, B, C. The letter C is 0b00111001 (segments A, D, E, F).

Common Issues and Fixes

Problem Likely Cause Solution
Segments too dim Missing resistors or wrong resistor value Use 220Ω–330Ω, never below 100Ω
Segments glow when they shouldn't Floating common pin or code logic inverted Double-check common cathode vs anode
Flickering multiplexed display Refresh rate too low Keep digit on-time under 5ms
Display shows wrong digits Pin mapping wrong or wiring crossed Verify with a multimeter, check datasheet

Which Method Should You Use?

  • Single digit, learning project: direct wiring. Simple, reliable, easy to debug.
  • 2–4 digits, learning: multiplexing. Teaches you a core embedded technique.
  • 4+ digits, or I/O limited: shift register. Clean wiring, fewer pins, scales well.
  • Production or complex project: pre-built I2C driver module (TM1637 or MAX7219) — but that’s another tutorial.

The beauty of 7 segment displays is their simplicity — no complex initialization, no pixel math, just on or off. Once you master multiplexing and shift registers, you can add a numeric interface to any project without sacrificing sensor pins.

For deeper dives into display timing, check how the OLED Display Arduino handles pixel-level control, or look at How Capacitors Work when you start adding decoupling caps to your longer multi-display runs.

Join the Community on Discord

Ask questions, share your builds, and hang out with fellow makers.

Join Discord — it's free

Enjoying this tutorial?

Support the channel on Patreon and get early access to projects, build logs, and more.

Support on Patreon →