Electronic dice on an Arduino Uno
A button rolls a die and an Uno tumbles the number onto a seven-segment display. The whole build, an Arduino Uno and 3 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.
Intermediate About 20 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.
Step by step, with the wiring and the common mistakes: Arduino 7 Segment Display: an Electronic Die
What you'll learn
- Seven-segment patterns stored as bits
- Common-cathode wiring and a shared resistor
- Internal pull-up on a button input
- Random numbers and a slowing-down animation
- Difficulty: Intermediate
- Time: About 20 minutes
- Board: Arduino Uno R3
- Parts: 5
How it works
A pushbutton on pin 9 rolls the die. The pin uses the internal pull-up, so it reads LOW while the button is pressed. Seven pins, 2 to 8, drive segments a to g of a common-cathode display, and a single 220 ohm resistor on the common pin returns the current to ground.
When you press the button, the sketch picks a random face from 1 to 6 fourteen times in a row, with a delay that grows each time. That makes the number look like it is tumbling and slowing down. The last face stays on the display and is printed to the serial monitor.
Because all segments share one resistor, a lit 8 is dimmer than a lit 1.
Parts list
5 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 × Seven segment display
- 1 × Resistor, 220 ΩIn Starter Kit, Claw Machine Kit, Halloween Prop Kit.
- 1 × PushbuttonIn Starter Kit, Christmas Lights Kit, Logic Lab 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 |
|---|---|
| Resistor, 220 Ω pin 2 | Arduino Uno R3 pin GND |
| Pushbutton pin 2a | Arduino Uno R3 pin GND |
| Pushbutton pin 1a | Arduino Uno R3 pin 9 |
| Seven segment display pin G | Arduino Uno R3 pin 8 |
| Seven segment display pin F | Arduino Uno R3 pin 7 |
| Seven segment display pin E | Arduino Uno R3 pin 6 |
| Seven segment display pin D | Arduino Uno R3 pin 5 |
| Seven segment display pin C | Arduino Uno R3 pin 4 |
| Seven segment display pin B | Arduino Uno R3 pin 3 |
| Seven segment display pin A | Arduino Uno R3 pin 2 |
| Resistor, 220 Ω pin 1 | Seven segment display pin COM1 |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Electronic dice: press the button, watch it tumble, read the number.
//
// segment a b c d e f g -> pins 2 3 4 5 6 7 8
// the common cathode -> 220 ohm to GND
// pin 9 -> the roll button, to GND, internal pull-up
//
// The display is common cathode, so a segment lights when its pin goes HIGH
// and all the return current leaves through the one resistor on the common
// pin. That is the cheap way to wire one: the more segments are lit the less
// current each gets, so an 8 is dimmer than a 1. Seven resistors, one per
// segment, is the right way.
//
// SEGMENTS[] is the usual seven-segment font, one bit per segment, bit 0 = a.
// The tumble is just the roll repeated with a delay that grows each step, which
// reads as the die slowing down and settling.
const int SEG_PINS[] = {2, 3, 4, 5, 6, 7, 8};
const int BUTTON = 9;
// bit 0 a, 1 b, 2 c, 3 d, 4 e, 5 f, 6 g
const uint8_t DIGITS[] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
};
static void show(uint8_t mask) {
for (int i = 0; i < 7; i++) {
digitalWrite(SEG_PINS[i], (mask >> i) & 1 ? HIGH : LOW);
}
}
static bool pressed() { return digitalRead(BUTTON) == LOW; }
void setup() {
for (int i = 0; i < 7; i++) {
pinMode(SEG_PINS[i], OUTPUT);
}
pinMode(BUTTON, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("Mokxi Arduino Uno: press the button to roll");
show(DIGITS[6]);
}
void loop() {
if (!pressed()) {
delay(10);
return;
}
int face = 1;
unsigned long step = 40;
for (int i = 0; i < 14; i++) {
face = (int)random(1, 7);
show(DIGITS[face]);
delay(step);
step += step / 4 + 5;
}
Serial.print("rolled ");
Serial.println(face);
while (pressed()) {
delay(10);
}
}
Code walkthrough
The key functions of the sketch, and what each one does.
show sketch.ino
Takes a byte where each bit stands for one segment, bit 0 for a up to bit 6 for g. It loops over the seven pins in SEG_PINS and writes HIGH for each bit that is 1. That is how one number from DIGITS becomes a lit digit.
static void show(uint8_t mask) {
for (int i = 0; i < 7; i++) {
digitalWrite(SEG_PINS[i], (mask >> i) & 1 ? HIGH : LOW);
}
}pressed sketch.ino
Returns true when the button pin reads LOW. Because the pin uses INPUT_PULLUP, a press connects it to ground and pulls it low.
static bool pressed() { return digitalRead(BUTTON) == LOW; }loop sketch.ino
Waits quietly until the button is pressed. Then it runs 14 rounds: pick a random face with random(1, 7), show it, wait step milliseconds, and make step a bit longer. It prints the final face, then waits for the button to be released.
void loop() {
if (!pressed()) {
delay(10);
return;
}
int face = 1;
unsigned long step = 40;
for (int i = 0; i < 14; i++) {
face = (int)random(1, 7);
show(DIGITS[face]);
delay(step);
step += step / 4 + 5;
}
Serial.print("rolled ");
Serial.println(face);
while (pressed()) {
delay(10);
}
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- No segments light This project
The common pin must go through the 220 ohm resistor to GND. Check that each segment pin matches a to g on pins 2 to 8. - The button does nothing This project
The button goes between pin 9 and GND. The sketch reads LOW as pressed. - Segments stay dark, or light when they should be off. Seven segment display
Check whether the display is common cathode or common anode. Common cathode: common pin to GND, drive segments HIGH. Common anode: common pin to VCC, drive segments LOW. - One segment is very bright or the LEDs burn out. Seven segment display
Each segment is an LED, so it needs its own resistor, about 220 ohm to 330 ohm on 5 V. One resistor on the common pin makes brightness change with the number of lit segments. - 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. - The input reads random HIGH and LOW when the button is not pressed. Pushbutton
A floating pin picks up noise. Add a 10 k pull-down or pull-up resistor, or use INPUT_PULLUP and wire the button between the pin and GND. Then pressed reads LOW. - The button seems always pressed, or never changes. Pushbutton
A 4-leg tactile switch has legs joined in pairs. Place it across the breadboard center gap so the pairs sit on different rows. Wired along one side, the legs are already connected.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.