Mini Monster Box
This circuit is live in Circuit Canvas. Open it to explore every part and wire, or make your own copy to change values, swap parts and build your own version. Free, right in your browser.
Knock on the box, and a grumpy little monster pops out to see who's there.
I built this for Halloween when my daughter was two and didn't like scary things, so I wanted something cute and a little weird instead. The idea came from Brandon's monster box in the Ohmify community.
A microphone hears the knock, a one-transistor amplifier makes the signal big enough for an Arduino, and a servo opens the lid. The lid opens at a random speed, stays open for a random time and closes at a random speed. Sometimes the monster peeks out carefully, and sometimes it pops up and slams the lid. That randomness is what makes it feel alive.
Ideas for improvements:
- Give the monster a voice: a slow "peek-a-boo" for a slow opening, or "Hey, I'm sleeping here!"
- Shrink it down to run on an ATtiny85
Mini Monster Box Schematic
The circuit has four parts: microphone, amplifier, Arduino and servo.
Microphone An electret microphone needs a little power to work. R1 goes from its positive leg to 5V, and the other leg goes to GND. When you knock, the microphone outputs a tiny voltage wiggle, just a few millivolts, on top of a steady DC voltage.
Amplifier That signal is far too small for the Arduino. It would get lost in the small jumps you always see on an analog input. So it goes through a simple transistor amplifier:
- C1 blocks the steady DC part and lets only the sound wiggle through.
- R2 sends a small current into the base of the transistor, which turns it on.
- R3 and the transistor work like a voltage divider, where the transistor is the bottom "resistor." How much the transistor is turned on decides the voltage on the output.
When you knock, the tiny wiggle from the microphone pushes on the base of the transistor. Even a small push on the base makes a big change on the output.
The component values come from a similar circuit I found. They worked well for detecting a knock, so I kept them.
Arduino The Arduino reads the amplified signal on A0 and keeps a running average of the readings. Random noise doesn't move the average much, but a knock pushes it over the threshold. When that happens, it waits a moment and then runs the servo with a random opening speed, open time and closing speed.
Servo The servo moves the lid between closed (165°) and open (90°). To control the speed, the code moves it in small steps with a short pause between each one. Bigger steps make a faster lid.
My first version woke up when you said "hello," but a knock on the box itself was much easier to tell apart from other sounds.
Mini Monster Box Parts List
How to Build the Mini Monster Box
The amplifier only needs a handful of components, so it fits easily on a small piece of a breadboard next to the Arduino.
Things to watch out for:
- The electret microphone has polarity. The leg connected to its metal case is GND.
- Connect the amplifier output to A0 and the servo signal wire to pin [SERVO PIN].
- Connect the GND of the amplifier, the servo and the Arduino together.
I built the first version on a breadboard with an Arduino Uno. When it worked, I soldered the sound circuit onto a small board and swapped the Uno for [BOARD] so everything fit inside the box.
Code
#include <Servo.h>
#define RUNNING_AVG_SIZE 10
#define CLOSED_POSITION 165
#define OPEN_POSITION 90
Servo myservo;
const int servoPin = 9;
const int soundPin = A0;
float averaged_value = 0;
int pos = 0; // variable to store the servo position
void setup() {
Serial.begin(9600);
myservo.attach(servoPin); // attaches the servo on pin 9 to the servo object
closeLid(70);
}
void loop() {
int sensorValue = analogRead(soundPin);
// Averaging
float alpha = 0.1; // factor to tune
averaged_value = alpha * sensorValue + (1-alpha) * averaged_value;
Serial.print("sensor = ");
Serial.println(sensorValue);
Serial.print("averaged_value = ");
Serial.println(averaged_value);
if (averaged_value > 500) {
delay(1000);
openLid(random(1, 5));
delay(random(50, 2000));
closeLid(random(1, 5));
delay(2000);
averaged_value = 0;
}
}
void closeLid(int speed) {
for (int pos = 90; pos < CLOSED_POSITION; pos += speed) { // goes from 0 degrees to 180 degrees
// Make sure we don't go above CLOSED_POSITION:
pos = min(pos, CLOSED_POSITION);
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
void openLid(int speed) {
for (int pos = 160; pos > OPEN_POSITION; pos -= speed) { // goes from 180 degrees to 0 degrees
// Make sure we don't go below OPEN_POSITION:
pos = max(pos, OPEN_POSITION);
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
Make it your own
Every circuit here is a live project in Circuit Canvas, not just a picture. Copy this one and change a value, swap a part or move it to a stripboard: the schematic and the breadboard layout are linked, so a part added to one appears in the other.
Or start from a blank canvas and draw your own circuit, with thousands of ready-made parts.