Madam K Skeleton Fortune Teller
by gg2inc in Circuits > Arduino
4187 Views, 46 Favorites, 0 Comments
Madam K Skeleton Fortune Teller
The fortune teller is unlike most fortune teller machines in that it will insult you. When trick-or-treaters knock on the door, they are always drawn to the skeleton fortune teller. I change the dispensed fortunes and the fortune show to be age appropriate during Halloween. The fortune teller is controlled by two Arduino microcontrollers and a Pololu Maestro USB servo controller. I also use a PicoVolt controller to operate the arm side to side motion so that it appears that she is waving her hand over the crystal ball. The arm will rise upward with the help of a Firgelli linear actuator. When the fortune reading is complete, a fortune will be dispensed. The cards are just business cards that I print at home. The fortunes provide a "Joke of the Day" along with other fun facts. I listed a few examples in the construction document. The document is 58 pages and provides everything including cabinet construction. You can also download a complete set of electrical drawings in .pdf format to accompany the construction document. Since some of the spoken fortunes have jokes that are less than appropriate, the other videos can be viewed at www.guarnero.com
The code listing for the Arduino's and the Pololu Maestro is located int he Construction document.
Madam K Providing a Reading
Control Components
Audio/Animation/Lighting Request
Arduino Uno R3 Controller (Audio Player)
Proto-Screwshield R3 Kit for Arduino
Arduino MP3 Music Maker Shield
Audio Tracks
Pololu Maestro Servo Controller
Pololu RC Switch With Relay
Coin Acceptor
PicoVolt
Arm Side to Side Motor
Arm Side Motor Linkage
Forearm Actuator
Audio Amplifier
Speakers
Star Field
Electrical Component Mounting
Control Panel Layout
Electrical Wiring
Forearm Actuator
Skeleton Body Parts
Fortune Teller Accessories
Fortune Teller Clothing
Fortune Teller Jewelry
Cabinet Construction
Construction Detail
Door Detail
Side & Front Detail
Speaker Cutout
Coin Acceptor Cutout
Fortune Dispenser Cutout / Mounting
Polycarbonate AR Sheets
Stickers
Paint
Fortunes
Program Listing- Arduino Uno R3 (Coin Acceptor)
The Arduino Uno R3 reads when the coin inserted input is connected to ground. The Arduino Uno R3 also determines the show animation and audio file to play and sends a 4 digit binary code to the Audio Player Arduino Uno R3 that represents the desired audio file to be played. In addition to sending the 4 digit binary code, it also requests a subroutine to be played to the Maestro. Refer to the electrical drawings for hookup information. Currently, I am only issuing three different shows but I have the ability to issue 15 different shows based on the binary code available. The Arduino code is listed below.
//serial to maestro config
#include
#define txPin 6
#define rxPin 7
SoftwareSerial mySerial(rxPin, txPin);
void setup()
{
// Serial.begin(9600); Enable For Local Serial Port Debugging
//Serial to maestro config
Serial.begin(9600);
//Delay on power up to avoid trigger of effect
delay(10000);
//Set pin 3 as the input from the ADAFruit Art Controller relay. Relay triggered by coin mech.
pinMode(3, INPUT_PULLUP);
//define pins for software serial
pinMode(txPin, OUTPUT);
pinMode(rxPin, INPUT);
//define pins to send to music maker arduino
pinMode(14, OUTPUT); //for binary, pin 22 is 1,pin 24 is 2,pin 28 is 4,pin 30 is 8
pinMode(15, OUTPUT); //for binary, pin 22 is 1,pin 24 is 2,pin 28 is 4,pin 30 is 8
pinMode(16, OUTPUT); //for binary, pin 22 is 1,pin 24 is 2,pin 28 is 4,pin 30 is 8
pinMode(17, OUTPUT); //for binary, pin 22 is 1,pin 24 is 2,pin 28 is 4,pin 30 is 8
//set pins low
digitalWrite (14, LOW); // 1 2 4 8
digitalWrite (15, LOW); // 1 2 4 8
digitalWrite (16, LOW); // 1 2 4 8
digitalWrite (17, LOW); // 1 2 4 8
//Serial.println("John Guarnero Madam K Fortune Teller Coin Mech Arduno");
}
// show number to play on maestro and audio;
int ShowNumber = 1;
int Coin_Memory = 0;
int Allow_Run = 1; //added alow run since when a relay de-energized, it would sometimes initate a trigger like a coin was inserted. This resolved any inductive kick issues.
int Coin_Detected_Debounce = 0;
void loop()
{
int Coin_Detected = digitalRead(3);
if (Coin_Detected == 0 )
{
Coin_Detected_Debounce = Coin_Detected_Debounce + 1;
Serial.println(Coin_Detected_Debounce);
}
if (Coin_Detected == 1 )
{
Coin_Detected_Debounce = 0;
}
if (Coin_Detected_Debounce >= 150 && Allow_Run == 1)
{
Coin_Memory = 1;
delay (1000);
}
{
if (ShowNumber == 1 && Coin_Memory == 1)
{
Allow_Run = 0;
if (mySerial.available())
Serial.write(mySerial.read());
if (Serial.available())
mySerial.write(Serial.read());
mySerial.write(0xA7); //run subroutine 1
mySerial.write((byte)0x00); //device id
//Send Value of Binary 1 To Uno to Play WAV File S1
digitalWrite (14, HIGH); // 1 2 4 8
digitalWrite (15, LOW); // 1 2 4 8
digitalWrite (16, LOW); // 1 2 4 8
digitalWrite (17, LOW); // 1 2 4 8
delay (500);
digitalWrite (14, LOW); // 1 2 4 8
digitalWrite (15, LOW); // 1 2 4 8
digitalWrite (16, LOW); // 1 2 4 8
digitalWrite (17, LOW); // 1 2 4 8
delay (30000); delay (30000); delay (30000); delay (5000);
Coin_Memory = 0;
Allow_Run = 1;
ShowNumber = ShowNumber + 1;
}
if (ShowNumber == 2 && Coin_Memory == 1)
{
Allow_Run = 0;
if (mySerial.available())
Serial.write(mySerial.read());
if (Serial.available())
mySerial.write(Serial.read());
mySerial.write(0xA7); //run subroutine 2
mySerial.write((byte)0x01); //device id
//Send Value of Binary 2 To Uno to Play WAV File S2
digitalWrite (14, LOW); // 1 2 4 8
digitalWrite (15, HIGH); // 1 2 4 8
digitalWrite (16, LOW); // 1 2 4 8
digitalWrite (17, LOW); // 1 2 4 8
delay (500);
digitalWrite (14, LOW); // 1 2 4 8
digitalWrite (15, LOW); // 1 2 4 8
digitalWrite (16, LOW); // 1 2 4 8
digitalWrite (17, LOW); // 1 2 4 8
delay (30000); delay (30000); delay (30000); delay (5000);
Coin_Memory = 0;
Allow_Run = 1;
ShowNumber = ShowNumber + 1;
}
if (ShowNumber == 3 && Coin_Memory == 1)
{
Allow_Run = 0;
if (mySerial.available())
Serial.write(mySerial.read());
if (Serial.available())
mySerial.write(Serial.read());
mySerial.write(0xA7); //run subroutine 3
mySerial.write((byte)0x02); //device id
//Send Value of Binary 3 To Uno to Play WAV File S3
digitalWrite (14, HIGH); // 1 2 4 8
digitalWrite (15, HIGH); // 1 2 4 8
digitalWrite (16, LOW); // 1 2 4 8
digitalWrite (17, LOW); // 1 2 4 8
delay (500);
digitalWrite (14, LOW); // 1 2 4 8
digitalWrite (15, LOW); // 1 2 4 8
digitalWrite (16, LOW); // 1 2 4 8
digitalWrite (17, LOW); // 1 2 4 8
delay (30000); delay (30000); delay (30000); delay (5000);
Coin_Memory = 0;
Allow_Run = 1;
ShowNumber = 1;
}
}
}
Program Listing- Arduino Uno R3 (Audio Player)
The Arduino Uno R3 audio player reads a 4 digit binary value from the Coin Acceptor Arduino Uno R3 and plays an audio file associated with the binary value.
#include
#include
#include
#define BREAKOUT_RESET 9 // VS1053 reset pin (output)
#define BREAKOUT_CS 10 // VS1053 chip select pin (output)
#define BREAKOUT_DCS 8 // VS1053 Data/command select pin (output)
#define SHIELD_RESET -1 // VS1053 reset pin (unused!)
#define SHIELD_CS 7 // VS1053 chip select pin (output)
#define SHIELD_DCS 6 // VS1053 Data/command select pin (output)
#define CARDCS 4 // Card chip select pin
#define DREQ 3 // VS1053 Data request, ideally an Interrupt pin
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
//int val;
//Define weighted binary values used for input mapping
int Binary1 = 0;
int Binary2 = 0;
int Binary4 = 0;
int Binary8 = 0;
void setup()
{
//Define pins used for inputs sent from the other Arduino
pinMode(14, INPUT_PULLUP); // sets the analog pin A0 as input
pinMode(15, INPUT_PULLUP); // sets the analog pin A1 as input
pinMode(16, INPUT_PULLUP); // sets the analog pin A2 as input
pinMode(17, INPUT_PULLUP); // sets the analog pin A3 as input
Serial.begin(9600);
// initialise the music player
if (! musicPlayer.begin())
{ // initialise the music player
Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
while (1);
}
if (!SD.begin(CARDCS))
{
}
// Set volume for left, right channels. Lower numbers == louder volume!
//This is if you purchase unit with amplifier built in
musicPlayer.setVolume(20,20);
if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
Serial.println(F("DREQ pin is not an interrupt pin"));
}
void loop()
{
// Start playing a file, then we can do stuff while waiting for it to finish
if (musicPlayer.stopped())
{
delay(1);
}
{
Binary1 = digitalRead(14); // Binary 1
Binary2 = digitalRead(15); // Binary 2
Binary4 = digitalRead(16); // Binary 4
Binary8 = digitalRead(17); // Binary 8
//Show 1 Detected - Binary 1
if (Binary1 == HIGH && Binary2 == LOW && Binary4 == LOW && Binary8 == LOW)// 1 2 4 8
{
Serial.println("Show 1");
(musicPlayer.startPlayingFile("s1.mp3"));
delay (1000);
}
//Show 2 Detected - Binary 2
if (Binary1 == LOW && Binary2 == HIGH && Binary4 == LOW && Binary8 == LOW)// 1 2 4 8
{
Serial.println("Show 2");
(musicPlayer.startPlayingFile("s2.mp3"));
delay (2000);
}
//Show 3 cents Detected - Binary 3
if (Binary1 == HIGH && Binary2 == HIGH && Binary4 == LOW && Binary8 == LOW)// 1 2 4 8
{
Serial.println("Show 3");
(musicPlayer.startPlayingFile("s3.mp3"));
delay (2000);
}
}
}
Program Listing- Pololu Maestro
The Pololu Maestro controls the RC relays for the Crystal Ball, Star Ceiling, PicoVolt trigger, and Fortune dispenser trigger. The Pololu Maestro also controls the Firgelli actuator.
The fortune teller is powered all of the time. To extend the life of the head servos, a RC relay is also controlled by the Maestro to only provide power to the relays when a show is active. Since a PicoTalk provides power to the servos and the PicoTalk is always powered on, a 12” extension for each servo was added and the power wire routed through the RC switch. The PicoTalk power is left on all of the time since it also controls the LED eyes and I wanted this to always be active.
Refer to the electrical drawings for hookup information.
#John Guarnero
#November 2014
#Madam K Maestro Control For Servo Relays and Firgelli actuator
#Pololu RC Switch(6), Firgelli Actuator
#6000 center, 4000 min, 8000 max
4000 0 servo #projector
4000 1 servo #Spare
4000 2 servo #Turn Off PicoVolt Arm Sweep
4000 3 servo #Crystal Ball
4000 4 servo #Dispense Fortune
4000 5 servo #Head Servos
8000 17 servo #Forearm (8000 is down)
500 delay
sub Subroutine_1
#Show 1 detected
4000 0 servo #projector
4000 1 servo #Spare
4000 2 servo #Turn off PicoVolt Arm Sweep
4000 3 servo #Crystal Ball
4000 4 servo #Dispense Fortune
4000 5 servo #Head Servos
8000 17 servo #Forearm (8000 is down)
500 delay
8000 0 servo #projector
4000 1 servo #Spare
4000 2 servo #Turn off PicoVolt Arm Sweep
4000 3 servo #Crystal Ball
4000 4 servo #Dispense Fortune
8000 5 servo #Head Servos
11000 delay
5500 17 servo #Forearm (5500 is up)
4000 delay
8000 5 servo #Head Servos
8000 0 servo #projector
4000 1 servo #Spare
8000 2 servo #Turn off PicoVolt Arm Sweep
8000 3 servo #Crystal Ball
500 delay
4000 2 servo #Turn off PicoVolt Arm Sweep
30000 delay
22500 delay
4000 3 servo #Crystal Ball
8000 17 servo #Forearm (8000 is down)
15000 delay
8000 4 servo #Dispense Fortune
1500 delay
4000 4 servo #Dispense Fortune
4000 5 servo #Head Servos
4000 0 servo #projector
8000 17 servo #Forearm (8000 is down)
quit
sub Subroutine_2
#Show 2 detected
4000 0 servo #projector
4000 1 servo #Spare
4000 2 servo #Turn off PicoVolt Arm Sweep
4000 3 servo #Crystal Ball
4000 4 servo #Dispense Fortune
4000 5 servo #Head Servos
8000 17 servo #Forearm (8000 is down)
500 delay
8000 0 servo #projector
4000 1 servo #Spare
4000 2 servo #Turn off PicoVolt Arm Sweep
4000 3 servo #Crystal Ball
4000 4 servo #Dispense Fortune
8000 5 servo #Head Servos
8000 17 servo #Forearm (8000 is down)
23000 delay
5500 17 servo #Forearm (5500 is up)
4000 delay
8000 5 servo #Head Servos
8000 0 servo #projector
4000 1 servo #Spare
8000 2 servo #Turn on PicoVolt Arm Sweep
8000 3 servo #Crystal Ball
500 delay
4000 2 servo #Turn off PicoVolt Arm Sweep
30000 delay
22500 delay
4000 3 servo #Crystal Ball
8000 17 servo #Forearm (8000 is down)
10000 delay
8000 4 servo #Dispense Fortune
1500 delay
4000 4 servo #Dispense Fortune
4000 5 servo #Head Servos
4000 0 servo #projector
8000 17 servo #Forearm (8000 is down)
quit
sub Subroutine_3
#Show 3 detected
4000 0 servo #projector
4000 1 servo #Spare
4000 2 servo #Turn off PicoVolt Arm Sweep
4000 3 servo #Crystal Ball
4000 4 servo #Dispense Fortune
4000 5 servo #Head Servos
8000 17 servo #Forearm (8000 is down)
500 delay
8000 0 servo #projector
4000 1 servo #Spare
4000 2 servo #Turn off PicoVolt Arm Sweep
4000 3 servo #Crystal Ball
4000 4 servo #Dispense Fortune
8000 5 servo #Head Servos
13000 delay
5500 17 servo #Forearm (5500 is up)
4000 delay
8000 5 servo #Head Servos
8000 0 servo #projector
4000 1 servo #Spare
8000 2 servo #Turn off PicoVolt Arm Sweep
8000 3 servo #Crystal Ball
500 delay
4000 2 servo #Turn Off PicoVolt Arm Sweep
30000 delay
22500 delay
4000 3 servo #Crystal Ball
8000 17 servo #Forearm (8000 is down)
15000 delay
8000 4 servo #Dispense Fortune
1500 delay
4000 4 servo #Dispense Fortune
4000 5 servo #Head Servos
4000 0 servo #projector
8000 17 servo #Forearm (8000 is down)
quit