Jump-scare box on an Arduino Uno
A radar inside a box sees someone walk up: a servo throws the lid open, a DFPlayer screams and two red eyes flicker, then it shuts and rearms. 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.
Intermediate Runs in your browser. Free, and no account needed.
Build it as the Halloween Prop Kit: the parts in numbered bags and a booklet that checks every step. Free.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Jump-scare box: someone walks up to the box on the porch, the lid bursts
// open with a scream and two red eyes flicker inside. Then it shuts, rests,
// and waits for the porch to clear before it arms again.
//
// RCWL-0516 VIN -> 5 V GND -> GND OUT -> pin 2 (high while it sees movement)
// servo PWM -> pin 9, VCC -> 5 V, GND -> GND (the arm that lifts the lid)
// DFPlayer VCC -> 5 V GND -> GND TX -> pin 10 RX <- 1 k <- pin 11
// a small speaker on SPK_1 and SPK_2; track 001.mp3 is the scream
// eyes two red LEDs on pins 5 and 6, each through 220 ohms to GND
//
// Why a radar: the RCWL-0516 sees movement through a thin plastic or cardboard
// wall, so it can hide inside the box. It also sees through doors and thin
// walls, so aim it away from the house. A PIR sensor works too, on the same
// pin, but it needs a hole to look out of.
//
// The sketch never waits in delay(). It keeps one state, ARMED, SCARING or
// RESTING, and the time it entered it, so the eyes can flicker while the lid
// is open and the sensor is read the whole time.
//
// On the bench: give the servo its own 5 V supply (a USB power bank works)
// with its ground joined to the Uno's. A servo that jumps hard can pull the
// Uno's 5 V down far enough to reset it, right at the scary moment.
//
// Things to try. Click the radar to walk up. Change LID_OPEN for a bigger
// throw, or SCARE_MS for a longer scream. Put a second track on the card and
// pick one with random(1, 3) so repeat visitors get a surprise.
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <Servo.h>
const int SENSOR_PIN = 2;
const int LID_PIN = 9;
const int EYE_LEFT = 5;
const int EYE_RIGHT = 6;
const int LID_SHUT = 10; // degrees, lid resting on the box
const int LID_OPEN = 110; // degrees, lid thrown open
const int EYE_IDLE = 12; // a faint glow while armed
const unsigned long SCARE_MS = 3000; // how long the lid stays open
const unsigned long REST_MS = 8000; // quiet time before it can fire again
SoftwareSerial link(10, 11); // RX, TX
DFRobotDFPlayerMini player;
Servo lid;
bool haveSound = false;
enum State { ARMED, SCARING, RESTING };
State state = ARMED;
unsigned long since = 0;
unsigned long nextFlicker = 0;
unsigned int scares = 0;
void eyes(int level) {
analogWrite(EYE_LEFT, level);
analogWrite(EYE_RIGHT, level);
}
void setup() {
Serial.begin(9600);
link.begin(9600);
pinMode(SENSOR_PIN, INPUT);
lid.attach(LID_PIN);
lid.write(LID_SHUT);
haveSound = player.begin(link);
if (haveSound) {
player.volume(28);
} else {
Serial.println("No DFPlayer answered: the box will scare in silence");
}
eyes(EYE_IDLE);
Serial.println("Armed");
}
void loop() {
unsigned long now = millis();
bool someone = digitalRead(SENSOR_PIN) == HIGH;
switch (state) {
case ARMED:
if (someone) {
state = SCARING;
since = now;
scares++;
lid.write(LID_OPEN);
if (haveSound) player.play(1);
Serial.print("BOO! Scare ");
Serial.println(scares);
}
break;
case SCARING:
if (now - since >= SCARE_MS) {
lid.write(LID_SHUT);
eyes(0);
state = RESTING;
since = now;
Serial.println("Lid shut, resting");
} else if (now >= nextFlicker) {
// A candle-like flicker: a random level, held for a random moment.
eyes(random(40, 256));
nextFlicker = now + random(30, 90);
}
break;
case RESTING:
// Rearm only once the rest is over and nobody is standing there, so
// one visitor gets one scare.
if (now - since >= REST_MS && !someone) {
state = ARMED;
eyes(EYE_IDLE);
Serial.println("Armed");
}
break;
}
}
Parts list
11 parts, plus the jumper wires. Every one is in the editor's parts bin.
- 1 × Arduino Uno R3
- 1 × Full-size breadboard
- 1 × DFPlayer Mini MP3 module
- 1 × Resistor, 1k Ω
- 2 × Resistor, 220 Ω
- 2 × LED, red
- 1 × Microwave motion sensor
- 1 × Hobby servo
- 1 × Speaker, 8 ohm
How it is wired
13 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Arduino Uno R3 pin 11; Resistor, 1k Ω pin 1
- Arduino Uno R3 pin 10; DFPlayer Mini MP3 module pin TX
- Arduino Uno R3 pin 9; Hobby servo pin PWM
- Arduino Uno R3 pin 6; Resistor, 220 Ω (2) pin 1
- Arduino Uno R3 pin 5; Resistor, 220 Ω (1) pin 1
- Arduino Uno R3 pin 2; Microwave motion sensor pin OUT
- Arduino Uno R3 pin 5V; DFPlayer Mini MP3 module pin VCC; Microwave motion sensor pin VIN; Hobby servo pin VCC
- Ground: Arduino Uno R3 pin GND; DFPlayer Mini MP3 module pin GND; LED, red (1) pin C; LED, red (2) pin C; Microwave motion sensor pin GND; Hobby servo pin GND
- DFPlayer Mini MP3 module pin RX; Resistor, 1k Ω pin 2
- DFPlayer Mini MP3 module pin SPK_1; Speaker, 8 ohm pin 1
- DFPlayer Mini MP3 module pin SPK_2; Speaker, 8 ohm pin 2
- Resistor, 220 Ω (1) pin 2; LED, red (1) pin A
- Resistor, 220 Ω (2) pin 2; LED, red (2) pin A
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.