Grabbing candy bowl on an Arduino Uno
An HC-SR04 watches across the top of a candy bowl: when a hand reaches in, a piezo cackles and a servo swings a rubber hand down to grab it. 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.
Beginner 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.
// Grabbing candy bowl: reach in for a treat and the bowl cackles at you while
// a rubber hand swings down to grab yours.
//
// HC-SR04 VCC -> 5 V GND -> GND TRIG -> pin 7 ECHO -> pin 8
// servo PWM -> pin 9, VCC -> 5 V, GND -> GND (the arm under the hand)
// piezo pin 4 -> piezo -> GND (a passive piezo, so tone() sets the note)
//
// Mount the ranger on the rim so it looks across the top of the bowl, not
// down into it: aimed into the bowl it would see the candy and never rest.
// Anything closer than GRAB_CM is a hand.
//
// Two readings in a row have to agree before the hand moves. An ultrasonic
// ranger now and then hears a stray echo, and one bad reading should not
// set off the prop.
//
// The grab itself is a short, fixed show, so it is written as plain steps
// with delay(). After it, the bowl waits for the hand to leave and then
// rests a moment, so one reach gets one grab.
//
// On the bench: a hobby servo's start-up surge can sag the Uno's 5 V, so give
// it a separate 5 V supply with its ground joined to the Uno's. Pad the
// rubber hand's swing so it bumps, never pinches.
//
// Things to try. Drag the ranger's slider under 12 cm. Change the cackle's
// notes. Swap the piezo for a DFPlayer and a speaker for a real recorded
// laugh, as the jump-scare box does.
#include <Servo.h>
const int TRIG_PIN = 7;
const int ECHO_PIN = 8;
const int HAND_PIN = 9;
const int PIEZO_PIN = 4;
const int GRAB_CM = 12; // a hand is closer than this
const int CLEAR_CM = 20; // the hand has gone once it is past this
const int HAND_UP = 20; // degrees, hand raised and hidden
const int HAND_DOWN = 150; // degrees, hand over the bowl
Servo hand;
int closeReadings = 0;
unsigned int grabs = 0;
// Distance in centimeters, or 999 when nothing answers.
int distanceCm() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
unsigned long echo = pulseIn(ECHO_PIN, HIGH, 30000UL);
if (echo == 0) return 999;
return echo / 58; // sound goes there and back, about 58 us per cm
}
void cackle() {
// "Heh heh heh heh-heeeh": short notes falling in pitch, then a long one.
const int notes[] = {880, 784, 698, 622};
for (int i = 0; i < 4; i++) {
tone(PIEZO_PIN, notes[i], 90);
delay(150);
}
tone(PIEZO_PIN, 1047, 400);
}
void grab() {
grabs++;
Serial.print("Grab ");
Serial.println(grabs);
hand.write(HAND_DOWN); // as fast as the servo can go
cackle();
delay(700);
// Lift slowly, which looks far creepier than snapping back.
for (int angle = HAND_DOWN; angle >= HAND_UP; angle -= 5) {
hand.write(angle);
delay(25);
}
}
void setup() {
Serial.begin(9600);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
hand.attach(HAND_PIN);
hand.write(HAND_UP);
Serial.println("Candy bowl ready");
}
void loop() {
int cm = distanceCm();
closeReadings = cm < GRAB_CM ? closeReadings + 1 : 0;
if (closeReadings >= 2) {
grab();
// Wait for the hand to leave, then rest a moment.
while (distanceCm() < CLEAR_CM) {
delay(60);
}
Serial.println("Hand gone");
delay(1500);
closeReadings = 0;
}
delay(60);
}
Parts list
5 parts, plus the jumper wires. Every one is in the editor's parts bin.
- 1 × Arduino Uno R3
- 1 × Half breadboard
- 1 × Ultrasonic ranger
- 1 × Hobby servo
- 1 × Piezo speaker
How it is wired
6 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 9; Hobby servo pin PWM
- Arduino Uno R3 pin 8; Ultrasonic ranger pin ECHO
- Arduino Uno R3 pin 7; Ultrasonic ranger pin TRIG
- Arduino Uno R3 pin 4; Piezo speaker pin 1
- Arduino Uno R3 pin 5V; Ultrasonic ranger pin VCC; Hobby servo pin VCC
- Ground: Arduino Uno R3 pin GND; Ultrasonic ranger pin GND; Hobby servo pin GND; Piezo speaker pin 2
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.