This project started with an e-mail from a friend of mine. It was a video of a very similar project and I have wanted to get into some electronics projects and this seemed like a good start.
We ended up doing two boxes. One for each of us. I needed to replace a portion of my fence so it seemed like a good time to get some old looking wood. We had enough for his box but not enough for mine. Another technique I was interested in trying was aging old wood. A bit of vinegar with some steel wool was put in a jar for three days and I gave everything a first coat before building the box. I waited a few months for the second coat which in hindsight was a bit late. The steel wool had rusted so I got an look that was a bit more orange than I would have preferred.
I added three stencils once the box was fully aged. This included a 'Danger' sign on the top, a 'Do Not Feed' on the front and a 'This Side Up" sign on the back. I'm more of a precise woodworker then a Disney imagineer so all of my stencils were very neat. For the other box he just held it roughly and spray painted quickly. I think it made his look a bit more natural. The bars and hinges were all given a coat of black spray paint meant to look like black metal and I added chains and a lock. The handles were braced rope. Now it was time for the electronics.
I'll lay out all the electronic bits and include precise model numbers where I can. This is a pretty straight forward Arduino project and doesn't have to be perfect to still be scary.
Bouncing Lid - The lid bounces via a wooden wheel with randomly spaced cogs. It runs off a windshield wiper motor and uses a high voltage motor shield. I also had to add a few springs to get the lid moving up and down.
Lid Lights - The lights for the lid are LED stick on lights that require a 9v power supply. If you're going to get into electronics I recommend you keep every power supply you've ever owned. They are all different voltages and you can cut off the end and use them for a lot of projects. (Susay® Waterproof Red LED 3528 SMD 300LED 5M Flexible Light Strip 12V 2A 24W 60LED/M) I used a relay to allow me to turn them off and on. (SainSmart 4-Channel Relay Module)
LED Eyes - The eyes are just two simple LEDs. These are slightly brighter than your average LEDs but were easy to install and program.
Sound - The sound shield we used was the standard one for Arduino and allows us to directly connect speakers. This was attempted but in the end I went with a set with a subwoofer from Walmart. Only $30 and gave much louder sound with good bass. (http://www.robotshop.com/ca/
Lid Sensor - The lid sensor is a door bell. Simple but effective. (Almost. More on that later.)
Remote - The remote was a Gikfun IC2262/2272 4 Channel Wireless Remote Control. It has four buttons and allows me to have various 'scenes' from just lights to full on lid lifting.
Lock - We got a very authentic looking lock for only $20. You can probably find cheaper but this was solid metal. (2 of Deco 79 01101 Metal Brass Lock and Keys Wall Hanging, 4" x 2.5")
I have made note of a few things for next Halloween that weren't quite working. The range for the remote is very short. Will either need to find something more powerful or create a better antenna. The lid sensor works but doesn't stay turned on long enough. I started to experiment with slowing the motor down a bit before trying to see if the lid was closed but didn't get it working in time.
This was a fun project and here is the video of it in action. The very simple code is below that.
#include <SoftwareSerial.h>
// ------------------------------------------------------------------
// Include Sound drivers.
// ------------------------------------------------------------------
#include <CytronEZMP3.h>
CytronEZMP3 mp3;
// ------------------------------------------------------------------
// Pin Designations
// ------------------------------------------------------------------
// Remote Input Pins
const int remoteInputA = 11;
const int remoteInputB = 13;
const int remoteInputC = 12;
const int remoteInputD = 10;
// Sounds Shield
const int soundReceivePin = 2;
const int soundTransmitPin = 3;
// Motor Pins
const int motorDirPin = 4;
const int motorSpeedPin = 5;
// Park Pin
const int parkPin = 7;
// Lid Lights
const int lidPin = 8;
// Eyes
const int eyePin = 9;
// ------------------------------------------------------------------
// Random Variables
// ------------------------------------------------------------------
int debugMode = true;
int park = true;
int remoteReadState = 0;
int monsterVolume = 75;
int monsterFrequency = 5000;
// ------------------------------------------------------------------
// One Time Setup Code
// ------------------------------------------------------------------
void setup() {
// Initiate the debug window.
Serial.begin(9600);
// Setup Remote
pinMode(remoteInputA, INPUT);
pinMode(remoteInputB, INPUT);
pinMode(remoteInputC, INPUT);
pinMode(remoteInputD, INPUT);
digitalWrite(remoteInputA, LOW);
digitalWrite(remoteInputA, LOW);
digitalWrite(remoteInputA, LOW);
digitalWrite(remoteInputA, LOW);
// Setup Eyes
pinMode(eyePin, OUTPUT);
// Setup Lid
pinMode(lidPin, OUTPUT);
digitalWrite(lidPin, LOW);
// Set up Parking Switch
pinMode(parkPin, INPUT);
// Set up the sounds
if(!mp3.begin(soundReceivePin, soundTransmitPin))
{
Serial.println("Init failed");
//while(1);
}
mp3.setVolume(monsterVolume);
// Set up the motor. Make sure it's going in the right direction.
pinMode(motorSpeedPin, OUTPUT);
pinMode(motorDirPin, OUTPUT);
digitalWrite(motorDirPin, LOW);
digitalWrite(motorSpeedPin, LOW);
}
// ------------------------------------------------------------------
// Listening Loop
// ------------------------------------------------------------------
void loop() {
// Testing
testMonster();
// Weak Monster
if (digitalRead(remoteInputA) == HIGH)
{
executeWeakMonster();
}
// Mild Monster
if (digitalRead(remoteInputB) == HIGH)
{
executeMildMonster();
}
// Crazy Monster
if (digitalRead(remoteInputC) == HIGH)
{
executeCrazyMonster();
}
// Random Monster
if (digitalRead(remoteInputD) == HIGH)
{
executeRandomMonster();
}
}
// ------------------------------------------------------------------
// Debug and Testing Methods
// ------------------------------------------------------------------
void debugPrintLn(char* debugMessage) {
if(debugMode == true)
{
Serial.println(debugMessage);
}
}
void testMonster()
{
debugPrintLn("TESTING");
delay(5000);
executeWeakMonster();
delay(1000);
executeMildMonster();
delay(5000);
executeWeakMonster();
delay(1000);
executeCrazyMonster();
delay(monsterFrequency);
}
// ------------------------------------------------------------------
// Monster Eye Actions
// ------------------------------------------------------------------
void turnEyesOn()
{
debugPrintLn("TURNING EYES ON");
digitalWrite(eyePin, HIGH);
}
void turnEyesOff()
{
debugPrintLn("TURNING EYES OFF");
digitalWrite(eyePin, LOW);
}
void executeGlowingEyes()
{
debugPrintLn("MAKING EYES GLOW");
for(int brightnessCount=0; brightnessCount <= 255; brightnessCount++){
analogWrite(eyePin, brightnessCount);
delay(10);
}
for(int brightnessCount=255; brightnessCount >= 0; brightnessCount--){
analogWrite(eyePin, brightnessCount);
delay(10);
}
}
// ------------------------------------------------------------------
// Monster Growling Actions
// ------------------------------------------------------------------
void lowGrowlOne()
{
debugPrintLn("LOW GROWL ONE");
mp3.playTrack(1);
}
void lowGrowlTwo()
{
debugPrintLn("LOW GROWL TWO");
mp3.playTrack(2);
}
void lowGrowlThree()
{
debugPrintLn("LOW GROWL THREE");
mp3.playTrack(3);
}
void mediumGrowlOne()
{
debugPrintLn("MEDIUM GROWL ONE");
mp3.playTrack(5);
}
void mediumGrowlTwo()
{
debugPrintLn("MEDIUM GROWL TWO");
mp3.playTrack(5);
}
void mediumGrowlThree()
{
debugPrintLn("MEDIUM GROWL THREE");
mp3.playTrack(6);
}
void crazyGrowlOne()
{
debugPrintLn("CRAZY GROWL ONE");
mp3.playTrack(7);
}
void crazyGrowlTwo()
{
debugPrintLn("CRAZY GROWL TWO");
mp3.playTrack(8);
}
void crazyGrowlThree()
{
debugPrintLn("CRAZY GROWL THREE");
mp3.playTrack(9);
}
// ------------------------------------------------------------------
// Monster Lid Light Actions
// ------------------------------------------------------------------
void turnLidLightsOn()
{
debugPrintLn("TURNING LID LIGHTS ON");
digitalWrite(lidPin, LOW);
delay(750);
}
void turnLidLightsOff()
{
debugPrintLn("TURNING LID LIGHTS OFF");
digitalWrite(lidPin, HIGH);
}
// ------------------------------------------------------------------
// Monster Lid Lifting Actions
// ------------------------------------------------------------------
void startSlowMotor()
{
debugPrintLn("STARTING SLOW MOTOR");
analogWrite(motorSpeedPin, 255);
}
void startFastMotor()
{
debugPrintLn("STARTING FAST MOTOR");
analogWrite(motorSpeedPin, 255);
}
void stopMotor()
{
debugPrintLn("STOPPING MOTOR");
analogWrite(motorSpeedPin, 0);
}
void parkMonster()
{
debugPrintLn("ATTEMPTING TO PARK MONSTER");
int parkCounter = 0;
while (digitalRead(parkPin) == LOW)
{
parkCounter = parkCounter + 1;
if (parkCounter == 2000)
{
break;
}
}
debugPrintLn("PARKING MONSTER");
stopMotor();
}
// ------------------------------------------------------------------
// Monster Definitions
// ------------------------------------------------------------------
void executeWeakMonster() {
debugPrintLn("CALLING WEAK MONSTER");
int randomNumber = random(0,3);
if(randomNumber == 0)
{
int eyeCounter = 0;
while (eyeCounter < 5)
{
eyeCounter = eyeCounter + 1;
executeGlowingEyes();
}
}
else if(randomNumber == 1)
{
int eyeCounter = 0;
while (eyeCounter < 20)
{
eyeCounter = eyeCounter + 1;
turnEyesOn();
delay(100);
turnEyesOff();
delay(100);
}
}
else if(randomNumber == 2)
{
int eyeCounter = 0;
while (eyeCounter < 1)
{
eyeCounter = eyeCounter + 1;
executeGlowingEyes();
turnEyesOn();
delay(100);
turnEyesOff();
delay(100);
turnEyesOn();
delay(100);
turnEyesOff();
delay(100);
turnEyesOn();
delay(100);
turnEyesOff();
delay(100);
}
}
}
void executeMildMonster()
{
debugPrintLn("CALLING MILD MONSTER");
int randomNumber = random(0,3);
if(randomNumber == 0)
{
turnLidLightsOn();
mediumGrowlOne();
executeGlowingEyes();
turnLidLightsOff();
}
else if(randomNumber == 1)
{
turnLidLightsOn();
mediumGrowlTwo();
int eyeCounter = 0;
while (eyeCounter < 10)
{
eyeCounter = eyeCounter + 1;
turnEyesOn();
delay(100);
turnEyesOff();
delay(100);
}
turnLidLightsOff();
}
else if(randomNumber == 2)
{
turnLidLightsOn();
mediumGrowlThree();
int eyeCounter = 0;
while (eyeCounter < 1)
{
eyeCounter = eyeCounter + 1;
turnEyesOn();
delay(100);
turnEyesOff();
delay(100);
turnEyesOn();
delay(100);
turnEyesOff();
delay(100);
executeGlowingEyes();
}
turnLidLightsOff();
}
}
void executeCrazyMonster()
{
debugPrintLn("CALLING CRAZY MONSTER");
int randomNumber = random(1,2);
if(randomNumber == 0)
{
crazyGrowlOne();
executeGlowingEyes();
turnLidLightsOn();
turnEyesOn();
delay(500);
turnLidLightsOff();
turnEyesOff();
delay(500);
turnLidLightsOn();
turnEyesOn();
delay(500);
turnLidLightsOff();
turnEyesOff();
delay(500);
turnLidLightsOn();
turnEyesOn();
delay(500);
turnLidLightsOff();
turnEyesOff();
delay(500);
turnLidLightsOn();
turnEyesOn();
delay(500);
turnLidLightsOff();
turnEyesOff();
executeGlowingEyes();
}
else if(randomNumber == 1)
{
crazyGrowlTwo();
executeGlowingEyes();
turnLidLightsOn();
turnEyesOn();
startFastMotor();
delay(3000);
stopMotor();
turnLidLightsOff();
executeGlowingEyes();
startFastMotor();
turnLidLightsOn();
delay(3000);
startSlowMotor();
delay(1000);
parkMonster();
turnLidLightsOff();
turnEyesOff();
executeGlowingEyes();
}
}
void executeRandomMonster()
{
debugPrintLn("CALLING RANDOM MONSTER");
int randomNumber = random(0,3);
if(randomNumber == 0)
{
executeWeakMonster();
}
else if(randomNumber == 1)
{
executeMildMonster();
}
else if(randomNumber == 2)
{
executeCrazyMonster();
}
}