Stopwatch: four-digit display, digits on 10 to 13, on an Arduino Uno
A four-digit seven-segment display with segments a to dp on pins 2 to 9 and digits 1 to 4 on pins 10 to 13 counts minutes and seconds, lighting one digit at a time faster than the eye can follow. The whole build, an Arduino Uno and 9 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Advanced About 30 minutes to build and run. Runs in your browser. Free, and no account needed.
The parts retail for about $33. On Mokxi they're free.
What you'll learn
- Multiplexing a four-digit display
- Segment patterns stored as bytes
- Common cathode: LOW selects a digit
- Splitting time into minutes and seconds with
/and%
- Difficulty: Advanced
- Time: About 30 minutes
- Board: Arduino Uno R3
- Parts: 11
How it works
The four digits of the display share their segment lines, so only one digit can be on at a time. The sketch lights digit 1, then 2, then 3, then 4, 3 ms each, over and over. That is too fast to see, so all four look lit.
The segments a to dp go through 220 ohm resistors to pins 2 to 9. The digit pins are 10 to 13. It is a common cathode display, so setting a digit pin LOW turns that digit on.
The time comes from millis. The first two digits are minutes, the third and fourth are seconds, and a point after the second digit separates them. Minutes wrap at 100.
Parts list
11 parts, plus the jumper wires. They retail for about $33; on Mokxi they're free.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Full-size breadboard
- 1 × Four-digit seven segment, multiplexed
- 8 × Resistor, 220 ΩIn Starter Kit, Claw Machine Kit, Halloween Prop Kit.
Kits that can build it
These 8 starter kits have every part in the circuit. Each kit's page lists what else it can build.
Wiring table
Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.
| Part and pin | Connects to |
|---|---|
| Four-digit seven segment, multiplexed pin DIG4 | Arduino Uno R3 pin 13 |
| Four-digit seven segment, multiplexed pin DIG3 | Arduino Uno R3 pin 12 |
| Four-digit seven segment, multiplexed pin DIG2 | Arduino Uno R3 pin 11 |
| Four-digit seven segment, multiplexed pin DIG1 | Arduino Uno R3 pin 10 |
| Resistor, 220 Ω (8) pin 1 | Arduino Uno R3 pin 9 |
| Resistor, 220 Ω (7) pin 1 | Arduino Uno R3 pin 8 |
| Resistor, 220 Ω (6) pin 1 | Arduino Uno R3 pin 7 |
| Resistor, 220 Ω (5) pin 1 | Arduino Uno R3 pin 6 |
| Resistor, 220 Ω (4) pin 1 | Arduino Uno R3 pin 5 |
| Resistor, 220 Ω (3) pin 1 | Arduino Uno R3 pin 4 |
| Resistor, 220 Ω (2) pin 1 | Arduino Uno R3 pin 3 |
| Resistor, 220 Ω (1) pin 1 | Arduino Uno R3 pin 2 |
| Resistor, 220 Ω (5) pin 2 | Four-digit seven segment, multiplexed pin E |
| Resistor, 220 Ω (4) pin 2 | Four-digit seven segment, multiplexed pin D |
| Resistor, 220 Ω (8) pin 2 | Four-digit seven segment, multiplexed pin DP |
| Resistor, 220 Ω (3) pin 2 | Four-digit seven segment, multiplexed pin C |
| Resistor, 220 Ω (7) pin 2 | Four-digit seven segment, multiplexed pin G |
| Resistor, 220 Ω (2) pin 2 | Four-digit seven segment, multiplexed pin B |
| Resistor, 220 Ω (6) pin 2 | Four-digit seven segment, multiplexed pin F |
| Resistor, 220 Ω (1) pin 2 | Four-digit seven segment, multiplexed pin A |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// A stopwatch on a four-digit display: minutes and seconds.
//
// segments a, b, c, d, e, f, g, dp -> 220 ohm each -> pins 2 to 9
// digit 1 -> pin 10 digit 2 -> pin 11 digit 3 -> pin 12 digit 4 -> pin 13
//
// The four digits share their segment lines, so only one digit can show at a
// time. The sketch lights digit 1, then 2, then 3, then 4, a few milliseconds
// each, over and over: too fast to see, so all four look lit. It is a common
// cathode display, so a digit pin LOW turns its digit on.
const int SEGMENTS[8] = {2, 3, 4, 5, 6, 7, 8, 9};
const int DIGIT_PINS[4] = {10, 11, 12, 13};
const byte PATTERNS[10] = {
0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110,
0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111,
};
void showDigit(int position, int value, bool dot) {
byte bits = PATTERNS[value] | (dot ? 0b10000000 : 0);
for (int s = 0; s < 8; s++) digitalWrite(SEGMENTS[s], (bits >> s) & 1);
digitalWrite(DIGIT_PINS[position], LOW);
delay(3);
digitalWrite(DIGIT_PINS[position], HIGH);
}
void setup() {
for (int s = 0; s < 8; s++) pinMode(SEGMENTS[s], OUTPUT);
for (int d = 0; d < 4; d++) {
pinMode(DIGIT_PINS[d], OUTPUT);
digitalWrite(DIGIT_PINS[d], HIGH);
}
Serial.begin(9600);
Serial.println("Mokxi Uno: stopwatch, minutes and seconds");
}
void loop() {
unsigned long seconds = millis() / 1000;
int minutes = (seconds / 60) % 100;
int secs = seconds % 60;
showDigit(0, minutes / 10, false);
showDigit(1, minutes % 10, true);
showDigit(2, secs / 10, false);
showDigit(3, secs % 10, false);
}
Code walkthrough
The key functions of the sketch, and what each one does.
showDigit sketch.ino
showDigit builds the pattern for a number, adding the point if asked. It writes the eight segment pins, pulls that digit's pin LOW for 3 ms to light it, then sets it HIGH again.
void showDigit(int position, int value, bool dot) {
byte bits = PATTERNS[value] | (dot ? 0b10000000 : 0);
for (int s = 0; s < 8; s++) digitalWrite(SEGMENTS[s], (bits >> s) & 1);
digitalWrite(DIGIT_PINS[position], LOW);
delay(3);
digitalWrite(DIGIT_PINS[position], HIGH);
}setup sketch.ino
setup makes all segment and digit pins outputs, sets the digit pins HIGH so every digit starts off, and starts serial.
void setup() {
for (int s = 0; s < 8; s++) pinMode(SEGMENTS[s], OUTPUT);
for (int d = 0; d < 4; d++) {
pinMode(DIGIT_PINS[d], OUTPUT);
digitalWrite(DIGIT_PINS[d], HIGH);
}
Serial.begin(9600);
Serial.println("Mokxi Uno: stopwatch, minutes and seconds");
}loop sketch.ino
loop works out minutes and seconds from millis, then calls showDigit four times, once per digit. It runs constantly so each digit gets lit many times a second.
void loop() {
unsigned long seconds = millis() / 1000;
int minutes = (seconds / 60) % 100;
int secs = seconds % 60;
showDigit(0, minutes / 10, false);
showDigit(1, minutes % 10, true);
showDigit(2, secs / 10, false);
showDigit(3, secs % 10, false);
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- The digits are in the wrong order. This project
DIG1 goes to pin 10, DIG2 to 11, DIG3 to 12 and DIG4 to 13. - Segments light in the wrong places. This project
Segments A to DP go to pins 2 to 9 through the resistors, in that order. - The display flickers. This project
Every pass ofloopmust draw all four digits. Adding long delays makes it blink. - Digits look dim, flicker, or show ghosts of other digits. Four-digit seven segment
Refresh each digit quickly in a loop, at least 100 Hz for the whole set. Turn all segments off before switching digits. Do not use delay() for long pauses while displaying. - Segments burn out or the pins are overloaded. Four-digit seven segment
Use a resistor of about 220 ohms on each segment line. Check whether the display is common cathode or common anode, since that sets which level turns a segment on. - The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure. - A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground. - Upload fails or nothing runs after wiring pins 0 and 1 to a module. Arduino Uno R3
Pins 0 and 1 are the USB serial port. Move the module to other pins, or unplug it while uploading. Also check the right board is selected.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.