Post pictures up of your Props, or a link to your prop gallery on Ghostbusters Fans.
By Link1985
#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:
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
    Uniform Tips

    Sorry for the triple post (you guys have gotten […]

    Proton Props???

    Ugly Little Spud, Did you actually get the pack?[…]

    Just seen this thread add me JudgeGerry to London

    Proton Props UK

    I would like to apologise to everyone for the dela[…]