- September 15th, 2017, 9:01 am#4898259
Hello. I'm working on a trap. I have the electronics together and programmed. I found the sound files for Ghostbusters one when they catch Slimer at the Sedgewick hotel. I just went through my code and commented most of the lines to describe what different lines do. I also linked in the components and where I found them; they are mostly from Adafruit. I will post it here so you can download it and use it as a template. Fair warning, I'm not a programmer, there is some extra stuff in there, and there are probably better/easier ways to do the stuff I did, but it should get you started on a working configuration. I plan on using the 3-D files put out by countspatula on Thingiverse: https://www.thingiverse.com/thing:1394492. I'm getting my 3-D printer early next year, so I'm pretty much at a stopping point until then.
Here's a demo video:
.
The sound is quiet because I had the speakers turned down, but it can get pretty loud.
Here is the code I use:
Here's a demo video:
.
The sound is quiet because I had the speakers turned down, but it can get pretty loud.
Here is the code I use:
Code: Select all
/***************************************************
This is an example for the Adafruit VS1053 Codec Breakout
Designed specifically to work with the Adafruit VS1053 Codec Breakout
----> https://www.adafruit.com/products/1381
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
//This is my code for the ghost trap. I will comment things to the best of my understanding and include component links so you can replicate my model if you want to.
// include SPI, MP3 and SD libraries. I'm using this sound shield: https://www.adafruit.com/product/1788
#include <SPI.h>
#include <Adafruit_VS1053.h> // The library can be found following the instructions at this link: https://learn.adafruit.com/adafruit-vs1053-mp3-aac-ogg-midi-wav-play-and-record-codec-tutorial/software
#include <SD.h>
#include <Servo.h> //this is the servo library built in to the arduino files.
#include <Wire.h>
#include <Adafruit_GFX.h> //this is part of the library for the light bar
#include "Adafruit_LEDBackpack.h" // this is the light bar and backpack I used: https://www.adafruit.com/product/1721
// there is a link on there to download the library files.
Adafruit_24bargraph bar = Adafruit_24bargraph(); // This defines the bargraph as 'bar' to be called later in the program.
Servo servoLeft; // This attaches the left servo. I'musing these servos: https://www.adafruit.com/product/2307
Servo servoRight; // This attaches the right servo. You can call them what you want, but left and right made sense to me.
// define the pins used. These aren't used in the shield configuration. I plan on deleting this to clean up the code, but I kept it in because this is from the example code that is available for the shield
//#define CLK 13 // SPI Clock, shared with SD card
//#define MISO 12 // Input data, from VS1053/SD card
//#define MOSI 11 // Output data, to VS1053/SD card
// Connect CLK, MISO and MOSI to hardware SPI pins.
// See http://arduino.cc/en/Reference/SPI "Connections"
// These are the pins used for the breakout example. The breakout mode is if you plugged it into a breakout board.
//#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)
// These are the pins used for the music maker shield. This is the configuration I use.
#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)
// These are common pins between breakout and shield
#define CARDCS 4 // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3 // VS1053 Data request, ideally an Interrupt pin
Adafruit_VS1053_FilePlayer musicPlayer =
// create breakout-example object!
//Adafruit_VS1053_FilePlayer(BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS); This call the variable pins defined in the breakout example above.
// create shield-example object!
Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS); // This is the configuration we use.
//starting the button counter code. The whole sequence runs on a button counter system. sometimes the button count in incremented by pressing the switch, other times
// it auto-increments in the code to get to the next step.
int counter = 0; // set the variable counter to 0 to start it. I'm using this switch: https://www.adafruit.com/product/818
int buttonstate = 0; // this variable has the current state, high or low, written to it.
int laststate = 0; // this variable has the last state, high or low, written to it.
int lightPin = 2; // This is the pin for the steady on white lights.
int yellowlight = A0; // This is the pin the yellow light next to the light bar is attached to.
int redlight = A1; // This is the pin the blinking red light at the back of the trap is attached to.
// I used an object oriented program solution to handle the multiple blinking lights without delay.
//There is an awesome tutorial I followed and adapted here: https://learn.adafruit.com/multi-tasking-the-arduino-part-1/a-classy-solution
class Flasher
{
int ledpin;
long ontime;
long offtime;
int ledstate;
unsigned long previousmillis;
public:
Flasher(int pin, long off, long on)
{
ledpin = pin;
pinMode(ledpin, OUTPUT);
ontime = on;
offtime = off;
ledstate = LOW;
previousmillis = 0;
}
void update() {
unsigned long currentmillis = millis();
if ((ledstate == HIGH) && (currentmillis - previousmillis >= ontime)) {
ledstate = LOW;
previousmillis = currentmillis;
digitalWrite(ledpin, ledstate);
}
else if ((ledstate == LOW) && (currentmillis - previousmillis >= offtime)) {
ledstate = HIGH;
previousmillis = currentmillis;
digitalWrite(ledpin, ledstate);
}
}
};
Flasher led8(8, 500, 50); //This is for the flashing white lights when the trap is open.
Flasher led1(A1, 244, 33); // this is for the red blinking light after the trap is closed. It is timed to approximately match the sound beeps.
void setup() {
musicPlayer.GPIO_pinMode(5, INPUT); //This is where the foot switch is connected and how to call the sound shield input pins for use.
//musicPlayer.GPIO_pinMode(6, OUTPUT);
Serial.begin(9600);
bar.begin(0x70); // pass in the address. This is super important. I was stuck for about a week because I forgot to put this line in here.
// This tells the arduino where to look for the bar graph so it will operate. It uses the variable 'bar' that we set in the beginning.
Serial.println("Adafruit VS1053 Simple Test");
if (! musicPlayer.begin()) { // initialise the music player
Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
while (1);
}
Serial.println(F("VS1053 found")); // This verifies the sound shield is working properly.
SD.begin(CARDCS); // initialise the SD card
// Set volume for left, right channels. lower numbers == louder volume! I'm using these speakers: https://www.adafruit.com/product/1669 //////////////////////////////////////////////////////////////////////
musicPlayer.setVolume(20,20);
// enable pull-up resistors on switch pins (analog inputs) // These are place holders in case I wanted to use them.
//musicPlayer.GPIO_digitalWrite(1, HIGH);
//musicPlayer.GPIO_digitalWrite(2, HIGH);
//musicPlayer.GPIO_digitalWrite(3, HIGH);
//musicPlayer.GPIO_digitalWrite(4, HIGH);
musicPlayer.GPIO_digitalWrite(5, LOW); //This pin was set to INPUT earlier, now we set the initial value. It doesn't have to be separated, and I will probably remove the unused lines later.
//musicPlayer.GPIO_digitalWrite(6, HIGH);
// Timer interrupts are not suggested, better to use DREQ interrupt!
//musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT); // timer int
// If DREQ is on an interrupt pin (on uno, #2 or #3) we can do background
// audio playing
musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT); // DREQ int. I'm not sure what this is, but it works like this so I'm pressing the 'I believe button.'
pinMode(lightPin, OUTPUT); // setting the pin modes for the constant on white lights we defined earlier.
digitalWrite(lightPin, LOW);
pinMode(yellowlight, OUTPUT); // setting the pin modes for the yellow light near the light bar.
digitalWrite(yellowlight, LOW);
pinMode(redlight, OUTPUT); // setting the pin modes for the red blinking light in the back.
digitalWrite(redlight, LOW);
servoLeft.attach(A2); // attaching the left servo to a pin
servoRight.attach(A3); // attaching the right servo to a pin
servoLeft.write(30); // setting the initial angle of the servo. For now, they are both set to the same.
servoRight.write(30); // setting the initial angle of the servo. Upon installation, they will be moving in different directions, so this is where the initial angles will be reset.
for (uint8_t b=0; b<13; b++) {
bar.setBar(b, LED_OFF);
bar.writeDisplay();
}
bar.writeDisplay();
} // This initializes the bargraph settings. I modified this from the sample code that is downloaded with the libraries.
void loop() {
//putstring("."); // uncomment this to see if the loop isnt running
buttonstate = musicPlayer.GPIO_digitalRead(5); // this is the start of the buttoncounting system.
if (buttonstate != laststate) {
if (buttonstate == HIGH) {
counter++; // increments the count from 0 to 1 and performs the following 'if' loop.
}
}
if (counter == 1){
digitalWrite(lightPin, HIGH); //constant on white lights turn on.
servoLeft.write(110); // servos move to the open angle. again, this is where you change the angle when they are installed and moving in different directions.
servoRight.write(110); // they are both set the same for troubleshooting and operation verification.
musicPlayer.playFullFile("track001.mp3"); //this is what I called the opening sound to keep it simple. Make sure the file is saved with the exact same name on the SD card.
// the playFullFile command playes the entire file before moving to the next line of code.
counter++; //auto increments counter from 1 to 2. This moves to the next 'if' statement to avoid the opening sound being played over and over again.
}
if (counter == 2){
led8.update(); // This begins the flashing white LEDs
servoLeft.detach(); // I detach the servos so they are not constantly getting power.
servoRight.detach(); // They have enough resistance even when off that the doors should stay open. This should conserve battery life.
} // The counter increments on the next foot switch press. The trap will hold this open mode until then.
if (counter == 3) {
digitalWrite(8, HIGH); // the white leds that were flashing turn constant on to give a brightening effect.
musicPlayer.startPlayingFile("track002.mp3"); // the ghost trapping and closing sound file is played. Here, I use the startPlayingFile command.
// This command will move to the next line of code while to music file is being played.
counter++;} // counter auto-increments from 3 to 4. This happens while the sound is playing because of the startPlayingFile command used.
if (counter == 4){
delay(3900); //This is timed to synch up the servos closing with the sound file.
servoLeft.attach(A2); //reattach the servos to close the doors.
servoRight.attach(A3);
delay(100); //provide a small delay for the servo attachment to process. this does not interfere with the sound file.
servoLeft.write(30); // servos move to closed position that they started in.
servoRight.write(30);
delay(100); // small delay to before detaching servos and allowing them time to move. Omitting this delay can cause reliability issues with the servos.
servoLeft.detach(); // detach the servos like before.
servoRight.detach();
digitalWrite(lightPin, LOW); //turn off all constant on white leds when the doors close.
digitalWrite(8, LOW); // turn off all constant on leds that were previously flashing when doors close.
delay(2930); // delay to synch up the light bar with the sound file.
for (uint8_t b=0; b<13; b++) {
bar.setBar(b, LED_YELLOW); // sets bar graph color to yellow
bar.writeDisplay();
delay(50); // sets the time between each segment lighting up. 50 ms seems about right with the sound file.
// bar.setBar(b, LED_OFF);
// bar.writeDisplay();
}
digitalWrite(yellowlight, HIGH); // yellow led turn on when the light bar loop is complete.
delay(1000); // delay to synch timing of red light with beeps.
counter ++; // counter auto increments from 4 to 5. This is so the light bar will stay on instead of sweeping full over and over again.
}
if (counter == 5){
led1.update(); // turns on the red flashing led using the flasher class we defined up at the top.
//button counter waits until the next switch press. The trap will stay in the current state until then.
}
if (counter == 6){
digitalWrite(yellowlight, LOW); // turns yellow light next to light bar off.
digitalWrite(A1, LOW); // turns red led off.
for (uint8_t b=0; b<13; b++) {
bar.setBar(b, LED_OFF);
bar.writeDisplay();
} // turns light bar off.
delay(100);
counter = 0; //sets button counter to 0 to start over again.
servoLeft.attach(A2); // reattach servos to start sequence again
servoRight.attach(A3);
delay(100); // processing delay.
} //this is a reset so the trap sequence is repeatable. The only limitation currently is I have to wait until the sound beeps stop to reset it.
// I could add some code to turn off the music player if I wanted to, but I'm happy enough with it.
}
Last edited by Kingpin on September 15th, 2017, 3:40 pm, edited 1 time in total.Reason: Added youtube code
grogking liked this