Lit button on an Arduino Uno
A 30 mm arcade button with an LED inside: the lamp breathes while it waits, goes full bright while held, and every press is counted. The whole build, an Arduino Uno and 1 more part, 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.
Beginner About 10 minutes to build and run. Runs in your browser. Free, and no account needed.
The parts retail for about $30. On Mokxi they're free.
What you'll learn
- Reading a button with
INPUT_PULLUP - Why a pressed button reads LOW
- Dimming a lamp with PWM
- A short debounce using
millis() - Counting presses
- Difficulty: Beginner
- Time: About 10 minutes
- Board: Arduino Uno R3
- Parts: 2
How it works
An arcade button has two separate halves: a microswitch and a lamp. Pressing the button does not light the lamp, so the sketch does that itself.
The switch goes to pin 7 and ground, and it is read with the pin's own pull-up, so a press reads LOW. The lamp goes to pin 5. It has its resistor built in, so a 5 V lamp connects straight to the pin.
While the button waits, the lamp breathes on PWM, with a two-second cycle. While you hold it, the lamp goes to full brightness. Each press is counted and printed.
Parts list
2 parts, plus the jumper wires. They retail for about $30; on Mokxi they're free.
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 |
|---|---|
| LED arcade button pin 1 | Arduino Uno R3 pin GND |
| LED arcade button pin 2 | Arduino Uno R3 pin 7 |
| LED arcade button pin L+ | Arduino Uno R3 pin 5 |
| LED arcade button pin L- | Ground |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Lit button: a 30 mm arcade button with an LED inside. The lamp breathes
// while the button waits, goes full bright while it is held, and each press
// is counted.
//
// button 2 -> pin 7, 1 -> GND (the microswitch)
// L+ -> pin 5, L- -> GND (the lamp, a 5 V one)
//
// The two halves of the button are separate: pressing it does not light it.
// The switch is read with the pin's own pull-up, so a press reads LOW. The
// lamp has its resistor built into the holder, so a 5 V lamp goes straight
// on a pin; a red one draws about 19 mA, inside what a pin can give, and
// analogWrite() dims it with PWM.
//
// Things to try. Hold the button and let go. Then open the button's
// properties and change the color: a white or blue lamp drops more voltage
// than a red one, so on the same 5 V it is dimmer.
const int BUTTON_PIN = 7;
const int LAMP_PIN = 5;
bool wasDown = false;
unsigned long presses = 0;
unsigned long lastChange = 0;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LAMP_PIN, OUTPUT);
Serial.println("Lit button ready");
}
void loop() {
bool down = digitalRead(BUTTON_PIN) == LOW;
unsigned long now = millis();
// A microswitch barely bounces, but 10 ms of patience costs nothing.
if (down != wasDown && now - lastChange > 10) {
wasDown = down;
lastChange = now;
if (down) {
presses++;
Serial.print("Press ");
Serial.println(presses);
}
}
if (wasDown) {
analogWrite(LAMP_PIN, 255);
} else {
// A two second breath: up for a second, down for a second.
int phase = (now / 4) % 500;
int level = phase < 250 ? phase : 499 - phase;
analogWrite(LAMP_PIN, level / 2 + 4);
}
delay(5);
}
Code walkthrough
The key functions of the sketch, and what each one does.
setup sketch.ino
It opens serial at 9600, then sets BUTTON_PIN (pin 7) as INPUT_PULLUP so no outside resistor is needed. LAMP_PIN (pin 5) is made an output. It prints "Lit button ready".
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LAMP_PIN, OUTPUT);
Serial.println("Lit button ready");
}loop sketch.ino
It reads the button, where LOW means down, and ignores changes closer than 10 ms. A new press adds one to presses and prints it. While held, analogWrite sends 255 to the lamp. Otherwise it works out a slow up-and-down level from millis() and writes that, so the lamp breathes.
void loop() {
bool down = digitalRead(BUTTON_PIN) == LOW;
unsigned long now = millis();
// A microswitch barely bounces, but 10 ms of patience costs nothing.
if (down != wasDown && now - lastChange > 10) {
wasDown = down;
lastChange = now;
if (down) {
presses++;
Serial.print("Press ");
Serial.println(presses);
}
}
if (wasDown) {
analogWrite(LAMP_PIN, 255);
} else {
// A two second breath: up for a second, down for a second.
int phase = (now / 4) % 500;
int level = phase < 250 ? phase : 499 - phase;
analogWrite(LAMP_PIN, level / 2 + 4);
}
delay(5);
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- The lamp never changes, or is always on This project
Check the lamp pins: L+ to pin 5 and L- to ground. The switch pins 1 and 2 are a separate circuit. - Presses do not register This project
One switch pin goes to pin 7 and the other to GND. Without ground, the pulled-up pin never reads LOW. - The button lamp never lights or burns out quickly. LED arcade button
The lamp is an LED with its own pins, separate from the switch. Match it to its rating (5 V or 12 V version) and check polarity. If your supply is different, add a resistor sized for it. - The switch reads random values. LED arcade button
The switch is just a contact. Wire one tab to ground and the other to an input with INPUT_PULLUP, or use an external pull-up resistor of about 10k. Do not leave the pin floating. - 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. - Pins misbehave or the board resets when you power motors or servos from it. Arduino Uno R3
Each I/O pin gives about 20 mA, 40 mA max. Power motors and servos from their own supply and join its ground to the Uno's GND.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.