This Arduino project is a throwback to several carnival and novelty arcade games from when I was a kid. I’ve done many Arduino projects, but this is my first project that was my own design. Prior to this, I generally followed someone else’s design or idea.
My main motivation was to try to understand using the Adafruit Wave shield. Someday I would like to have the Arduino also control the servo that controls the skull, but for this project the talking skull portion was a kit. There are other talking skulls available (Talking thru Boris, a halloween decoration that can be found on auction sites).
I also wanted to build this as inexpensively as possible & use parts that are either things I already had on hand, or parts that are plentiful & cheap.
Using this approach often makes the finished project more unique.
A note about the video: I removed the glass to make the project more visible in the video.
Step 1: Parts list
-Arduino
-Wave shield & SD card(Adafruit)
-Talking skull (I got mine from Nuts & Volts)
-potentiometer (Radio Shack)
-coin op mechanism (Adafruit)
-inexpensive computer speakers (Thrift store)
-LED strip lights (online supplier)
-UV LED lights(online supplier)
-Windshield wiper motor (salvage)
-11X14 frame
-Mirror window tint
-3/4" plywood
-1/2 doors
-flocked paper
I will try to point out helpful parts throughout the instructable but slight alterations in the design should make it easier to utilize parts you already have.
Step 2: Skull housing construction
Once the box was constructed, I lined the inside of the box with black paper on all sides except for the bottom. Fuzzy, flocked paper works best, but ordinary black construction paper will be fine, or even painting the inside of the box. I cut a piece of plywood that fits just inside the bottom of the box when stood upright. This is what we'll mount the bracket that holds the skull to.
I used flat steel bracket stock to make the bracket. After deciding approximately how high I wanted the skull, I cut & bent the bracket accordingly, being sure to allow enough surface area to mount the skull securely. Once I'd bent the bracket, I mounted the skull on it. In my case, I cut two small notches in the hole at the base of the skull, which were large enough to insert the bracket. I also added a bolt for the skull to rest on. Now put the whole assembly together & line it up in the box, confirming that the skull is where you want it. Confirm the bend is at the right place & that the skull has enough clearance at the front & the back, since you do not want the spinning disc rubbing up against the skull or the skull touching the glass. Mark where you want your mounting holes for the bracket & remove everything so you can drill your pilot holes into the base. Remove everything from the bracket temporarily, and make any necessary adjustments to the bracket. Once you have the bracket perfect, heat the bracket with a plumbers torch until it's red hot. Then drop it into a pan of water to cool it quickly. This will set your bend & make it springy & rigid. Cover your plywood base with black paper & cut out your pilot holes with a craft knife.
I rolled some paper over a piece of a florescent tube protector & taped it with some black tape to conceal the bracket.
Drill a hole large enough to fit the ends to all your power & audio cables into at the base of the bracket. You want your tube to be able to conceal this. NOTE: this hole needs to be big enough to stuff the cables through, while also having other wires running through it. Mount your bracket using large screws & washers or lag bolts. I used a stiff piece of wire to fish all the cables through the hole & the tube.
Your finished base should look something like the final picture in this step.
Step 3: Preparing the frame
I used mirror privacy tint on the glass, which can be purchased at a hardware store or done by a pro at an auto tint service. I had mine done at an auto-tinter because I didn't see the need to buy a whole roll of tint just so I could use a couple of feet of it.
When you typically buy frames at a hobby store, they are just the frame, so I used strips of 1/8" plywood that were cut on the table saw. I predrilled the holes for the screws & lined it all up on the frame. I predrilled holes in the frame also, using a scrap piece of plexiglas instead of the glass as a spacer. In my project, I used a matte board border to frame the skull & help conceal the lights. Since this sits right next to the glass, I slipped a piece of this next to the plexiglas before drilling my pilot holes.
When drilling your pilot holes, mark one spot on each strip on both the strip & the frame with something distinct. This is so you will not get the pieces mixed up when you reassemble them. I drew a line on one, an x on the next one, a 0 on the third one and a black dot on the final one. This way, when or if you take it apart, you can easily reassemble it by aligning the symbols, so that all you pilot holes will match up.
Mounting a piano hinge is usually easier than using separate hinges. Just line it up so that it’s even along the frame from the edge. Drill a pilot hole for a screw on the middle of the hinge and put a screw in it. Re-align so that you’re sure it’s where you want it & drill a pilot hole for one of the end screws. Then put a screw in it. It should be held in place good enough that you can drill all the other pilot holes. The other side is easy because it should just line up with the outside edge of the box.
Once assembled, the whole box & frame should resemble a very deep medicine cabinet.
Step 4:
I mounted the LED light strips onto some drywall corner protector. This material already has adhesive strips on them. I was able to peel adhesive off of the LEDs & the adhesive off the corner protector to make a really good bond. I then used screws to mount the corner protector to the inside front of the box, just inside where the frame is. On this project, I also wanted to use some UV LEDs, but I couldn't find any lightstrips that were UV so I made my own with single LEDs & some spare strips of thin plastic.
I cut a piece of 1/2 inch plywood to fit inside the groove on the back of the box. This is what we will mount the windshield wiper motor to. I also mounted the Arduino electronics to this, but if I did it again I probably wouldn't do it that way. When mounting the motor, be sure that you mount it securely because over time, vibration from the motor might work it loose. I made the support sturdier by using a metal plate on the inside. Make sure that you put the screw heads on the inside so that you'll have enough clearance for your spinning disc. Since the skull sits right in the middle of the spinning disc, it isn't necessary to cover up the mounting bolt to the motor because it won't be visible.
Step 5: Cutting the disc
Gently flex the plex along the cut edge, so that it snaps along where you've made your cut. This is the best method I've used to cut from plex, because using a saw heats the plastic & melts it. I glued my spiral to the disc using craft glue. The example shown isn't the same size disc that I used in the final project, it's just an example I made to show this technique.
Step 6:
The LED light strips are 12v, so they are controlled using IRF510 mosfets using a signal sent from the Arduino. These lights flicker/strobe, which creates the illusion that the spinning disc is moving slower than it actually is. The motor is also 12V & is just turned on via mosfet. I used a separate power source to avoid any interference to the Arduino.
Lining the area where the back cover meets the box with craft foam sheets cut into strips will dampen any noise caused by the vibration of the motor. Using a layer of foam between the motor & the back cover will help as well.
The mosfets could all be soldered to the same board, but I just used one that I had created prior to this project. Since the motor & the LEDs are only on briefly, a heat sink isn't needed. Although if you alter the sketch to where they’re always on, a heat sink would be a good idea, especially for the motor mosfet.
Step 7:
Since I was going to make this coin operated, I needed a compartment that would be easily accessible. I made three shelves that were the same size: One for the box to sit on and to be the top of the compartment, one for the lower part of the compartment, and one shelf for the bottom that also helps stabilize the whole project. I also attached a hinged door to the middle shelf. This will be the access point to collect the coins. I was also able to install a lock on the door, which is just a simple lock that you put a key in and turns. A little strip of metal slides into a groove & keeps the whole compartment locked.
The interior of the compartment contains the potentiometer, the amplifier, the speakers, & the coin op mechanism. The coin op mechanism is programmable. Once it is powered up, you push a button on the top of the unit. Then, you would drop 30 of same coin you'd like it to accept. After this, the light goes out & from then on it will only accept that coin, unless you repeat the programming process. From then on, any time someone drops the proper coin in, it sends a 5v signal out which is read by the Arduino. I made it 5 cents because I wanted to make it cheap, but didn't want to have to beg the bank to take my pennies. The potentiometer had an extraordinarily long shaft, so I mounted the pot to a piece of bracket stock & mounted the bracket stock to the machine.
The front side has the knob, the coin op slot, and the grills for the speakers. I routed the slots in the plywood & mounted the speakers behind them. I wanted there to be some depth to the front plate, so I copied my designs (5 cents/mood meter) to some shrink plastic & shrunk them down. They were then attached to the unit using screws. Shrink plastic shrinks down to a third of it's size, so calculate accordingly if you use this method.
Step 8: The Arduino sketch
You'll need the wave shield, the Arduino, and an SD card. You'll also need to install the library for WaveHC. There are instructions on the Adafruit website on how to properly convert your audio files to the proper format for the Wave shield. I used Audacity for this, since there are lots of options for changing the sound of the files in Audacity, and also because I didn't really want the fortune teller to sound like me.
There are only a few digital pins available because the wave shield needs some of the pins to communicate with the Arduino. In my sketch, I used pins 6,7,8,& 9, as well as analog pin 5. The sketch uses noise from analog pin 0 for a more random audio selection. My project uses two different light sources. In the sketch, these are leduvPin & ledstrobePin. It also uses a pin for motor control (pin 9) & a pin for the coin slot (pin 8), labeled button in the sketch. The pot is wired to analog pin 5.
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
int ledstrobePin = 7;
int leduvPin = 6;
int delayPeriod = 20;
SdReader card; // This object holds the information for the card
FatVolume vol; // This holds the information for the partition on the card
FatReader root; // This holds the information for the filesystem on the card
FatReader f; // This holds the information for the file we're play
WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
#define MOTOR 9
#define BUTTON 8
#define LED 13
int val = 0;
int potvalue = 0;
long randNum;
// this handy function will return the number of bytes currently free in RAM, great for debugging!
int freeRam(void)
{
extern int __bss_end;
extern int *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__bss_end);
}
else {
free_memory = ((int)&free_memory) - ((int)__brkval);
}
return free_memory;
}
void sdErrorCheck(void)
{
if (!card.errorCode()) return;
putstring("\n\rSD I/O error: ");
Serial.print(card.errorCode(), HEX);
putstring(", ");
Serial.println(card.errorData(), HEX);
while(1);
}
void setup() {
// set up serial port
Serial.begin(9600);
pinMode(BUTTON, INPUT);
pinMode(LED, OUTPUT);
pinMode(leduvPin, OUTPUT);
pinMode(ledstrobePin, OUTPUT);
randomSeed(analogRead(0));
digitalWrite (BUTTON,HIGH);
pinMode(MOTOR, OUTPUT);
putstring("Free RAM: "); // This can help with debugging, running out of RAM is bad
Serial.println(freeRam()); // if this is under 150 bytes it may spell trouble!
// Set the output pins for the DAC control. This pins are defined in the library
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
// if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
if (!card.init()) { //play with 8 MHz spi (default faster!)
putstring_nl("Card init. failed!"); // Something went wrong, lets print out why
sdErrorCheck();
while(1); // then 'halt' - do nothing!
}
// enable optimize read - some cards may timeout. Disable if you're having problems
card.partialBlockRead(true);
// Now we will look for a FAT partition!
uint8_t part;
for (part = 0; part < 5; part++) { // we have up to 5 slots to look in
if (vol.init(card, part))
break; // we found one, lets bail
}
if (part == 5) { // if we ended up not finding one :(
putstring_nl("No valid FAT partition!");
sdErrorCheck(); // Something went wrong, lets print out why
while(1); // then 'halt' - do nothing!
}
// Lets tell the user about what we found
putstring("Using partition ");
Serial.print(part, DEC);
putstring(", type is FAT");
Serial.println(vol.fatType(),DEC); // FAT16 or FAT32?
// Try to open the root directory
if (!root.openRoot(vol)) {
putstring_nl("Can't open root dir!"); // Something went wrong,
while(1); // then 'halt' - do nothing!
}
// Whew! We got past the tough parts.
putstring_nl("Ready!");
/* TCCR2A = 0;
TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
//Timer2 Overflow Interrupt Enable
TIMSK2 |= 1<<TOIE2;
*/
}
void loop()
{
val = digitalRead(BUTTON);
potvalue = analogRead(5);
Serial.println(potvalue, DEC);
if (val == HIGH && potvalue >= 0 && potvalue <= 4)
{
randNum = random(1, 14);
delay(1000);
switch (randNum)
{
case 1:
Serial.println(1);
playcomplete("1.WAV");
break;
case 2:
Serial.println(2);
playcomplete("2.WAV");
break;
case 3:
Serial.println(3);
playcomplete("3.WAV");
break;
case 4:
Serial.println(4);
playcomplete("4.WAV");
break;
case 5:
Serial.println(5);
playcomplete("5.WAV");
break;
case 6:
Serial.println(6);
playcomplete("6.WAV");
break;
case 7:
Serial.println(7);
playcomplete("7.WAV");
break;
case 8:
Serial.println(8);
playcomplete("8.WAV");
break;
case 9:
Serial.println(9);
playcomplete("9.WAV");
break;
case 10:
Serial.println(10);
playcomplete("10.WAV");
break;
case 11:
Serial.println(11);
playcomplete("11.WAV");
break;
case 12:
Serial.println(12);
playcomplete("12.WAV");
break;
case 13:
Serial.println(13);
playcomplete("13.WAV");
break;
case 14:
Serial.println(14);
playcomplete("14.WAV");
break;
default:
break;
}
}
if (val == HIGH && potvalue >= 5 && potvalue <= 15)
{
randNum = random(15, 29);
delay(1000);
switch (randNum)
{
case 15:
Serial.println(15);
playcomplete("15s.WAV");
break;
case 16:
Serial.println(16);
playcomplete("16s.WAV");
break;
case 17:
Serial.println(17);
playcomplete("17s.WAV");
break;
case 18:
Serial.println(18);
playcomplete("18s.WAV");
break;
case 19:
Serial.println(19);
playcomplete("19s.WAV");
break;
case 20:
Serial.println(20);
playcomplete("20s.WAV");
break;
case 21:
Serial.println(21);
playcomplete("21s.WAV");
break;
case 22:
Serial.println(22);
playcomplete("22s.WAV");
break;
case 23:
Serial.println(23);
playcomplete("23s.WAV");
break;
case 24:
Serial.println(24);
playcomplete("24s.WAV");
break;
case 25:
Serial.println(25);
playcomplete("25s.WAV");
break;
case 26:
Serial.println(26);
playcomplete("26s.WAV");
break;
case 27:
Serial.println(27);
playcomplete("27s.WAV");
break;
case 28:
Serial.println(28);
playcomplete("28s.WAV");
break;
case 29:
Serial.println(29);
playcomplete("29s.WAV");
break;
default:
break;
}
}
if (val == HIGH && potvalue >= 16 && potvalue <= 22)
{
randNum = random(30, 44);
delay(1000);
switch (randNum)
{
case 30:
Serial.println(30);
playcomplete("30m.WAV");
break;
case 31:
Serial.println(31);
playcomplete("31m.WAV");
break;
case 32:
Serial.println(32);
playcomplete("32m.WAV");
break;
case 33:
Serial.println(33);
playcomplete("33m.WAV");
break;
case 34:
Serial.println(34);
playcomplete("34m.WAV");
break;
case 35:
Serial.println(35);
playcomplete("35m.WAV");
break;
case 36:
Serial.println(36);
playcomplete("36m.WAV");
break;
case 37:
Serial.println(37);
playcomplete("37m.WAV");
break;
case 38:
Serial.println(38);
playcomplete("38m.WAV");
break;
case 39:
Serial.println(39);
playcomplete("39m.WAV");
break;
case 40:
Serial.println(40);
playcomplete("40m.WAV");
break;
case 41:
Serial.println(41);
playcomplete("41m.WAV");
break;
case 42:
Serial.println(42);
playcomplete("42m.WAV");
break;
case 43:
Serial.println(43);
playcomplete("43m.WAV");
break;
case 44:
Serial.println(44);
playcomplete("44m.WAV");
break;
default:
break;
}
}
if (val == HIGH && potvalue >= 23 && potvalue <= 1023)
{
randNum = random(45, 60);
delay(1000);
switch (randNum)
{
case 45:
Serial.println(45);
playcomplete("45.WAV");
break;
case 46:
Serial.println(46);
playcomplete("46e.WAV");
break;
case 47:
Serial.println(47);
playcomplete("47e.WAV");
break;
case 48:
Serial.println(48);
playcomplete("48e.WAV");
break;
case 49:
Serial.println(49);
playcomplete("49e.WAV");
break;
case 50:
Serial.println(50);
playcomplete("50e.WAV");
break;
case 51:
Serial.println(51);
playcomplete("51e.WAV");
break;
case 52:
Serial.println(52);
playcomplete("52e.WAV");
break;
case 53:
Serial.println(53);
playcomplete("53e.WAV");
break;
case 54:
Serial.println(54);
playcomplete("54e.WAV");
break;
case 55:
Serial.println(55);
playcomplete("55e.WAV");
break;
case 56:
Serial.println(56);
playcomplete("56e.WAV");
break;
case 57:
Serial.println(57);
playcomplete("57e.WAV");
break;
case 58:
Serial.println(58);
playcomplete("58e.WAV");
break;
case 59:
Serial.println(59);
playcomplete("59e.WAV");
break;
case 60:
Serial.println(60);
playcomplete("60e.WAV");
break;
default:
break;
}
}
}
// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
// call our helper to find and play this name
playfile(name);
while (wave.isplaying) {
digitalWrite (MOTOR, HIGH);
flash (20, delayPeriod);
digitalWrite (MOTOR, LOW);
// do nothing while its playing
}
// now its done playing
}
void flash (int numFlashes, int d)
{
for (int i = 0; i < numFlashes; i ++)
{
digitalWrite (ledstrobePin, HIGH);
digitalWrite (leduvPin, LOW);
delay (d);
digitalWrite (ledstrobePin, LOW);
digitalWrite (leduvPin, HIGH);
delay (d);
digitalWrite (ledstrobePin, LOW);
digitalWrite (leduvPin, LOW);
}
}
void playfile(char *name) {
// see if the wave object is currently doing something
if (wave.isplaying) {
flash (20, delayPeriod);// already playing something, so stop it!
wave.stop(); // stop it
}
// look in the root directory and open the file
if (!f.open(root, name)) {
putstring("Couldn't open file "); Serial.print(name); return;
}
// OK read the file and turn it into a wave object
if (!wave.create(f)) {
putstring_nl("Not a valid WAV"); return;
}
// ok time to play! start playback
wave.play();
}
Step 9:
Step 10:
The final picture is the back view with the panels installed.
Step 11: Finishing
Milk paint dries differently than other paints. It shrinks as it dries, so if it's painted over another painted surface, it'll crack & bunch up in some areas, yet adhere well in others. This gives a look similar to something that has been painted & repainted over a long period of time. It's easy to use, has no fumes, is durable, and lasts a long time. Once the paint was dry, I applied a liquid beeswax protectant to protect the paint from dirt.
























































Visit Our Store »
Go Pro Today »




The skeleton head is very simple in its operation. If there's sound, it drives the servo in it designated rotation, and if there isn't sound, it returns to the start position. It isn't perfect but works pretty well. If your recording sounds for it you'd want to avoid any sounds that aren't audible enough to drive the servo (typically "S" sounds).
There is no such thing as a dumb question to me, I'm not really much of a technical person, I just figure out a way to do what I want to do.
The "thing" is cool.......and so is the Instructable!!