Dave VanderWekke
Published © GPL3+

Bringing Darth Vader to life with Lights and Sounds

My favorite Star Wars prop is my full-size Darth Vader that stands in my living room. I've wanted to add lights and sounds for a while now.

IntermediateFull instructions provided20 hours2,030
Bringing Darth Vader to life with Lights and Sounds

Things used in this project

Hardware components

Photon
Particle Photon
×1
Adafruit VS1053 Codec + MicroSD Breakout - MP3/WAV/MIDI/OGG Play + Record - v4
×1
Adafruit Stereo 2.8W Class D Audio Amplifier - TS2012
×1
4-Channel 5V Relay Module
×1
Speaker: 3W, 4 ohms
Speaker: 3W, 4 ohms
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1
Particle Shield Shield
×1

Story

Read more

Schematics

Breadboard Layout

This is a rough Fritzing Breadboard Layout of the Darth Vader Sound Project

Schematic Layout

This is a rough Schematic of the Darth Vader Sound Project

Darth Vader Sound Clips to match the Software Image

These are the mp3 files that match the Software image. Most are randomly played however there is an Init sound clip and a secondary function that plays the Imperial March.

Code

vs1053-sound-player.ino

C/C++
The Particle Photon Sketch to play MP3 files using a VS1503 Breakout.
// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_VS1053_Photon_Beta/Adafruit_VS1053_Photon_Beta.h"

#include "application.h"

#include "string.h"

// define the pins used
#define CLK     D4//13       // SPI Clock, shared with SD card
#define MISO    D3//12       // Input data, from VS1053/SD card
#define MOSI    D2//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
#define BREAKOUT_RESET  A4//9      // VS1053 reset pin (output)
#define BREAKOUT_CS     D5//10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    A5//8      // VS1053 Data/command select pin (output)

// These are common pins between breakout and shield
#define CARDCS  D6//4              // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ    WKP//3             // VS1053 Data request, ideally an Interrupt pin

// For triggering to play the file:
#define RANDOMPIN A1
#define MARCHPIN A0

// For controlling external relays
#define RELAY_1 D0           // Relay 1 Pin
#define RELAY_2 D1           // Relay 2 Pin

int randomState = 0;
int marchState = 0;

Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(MOSI, MISO, CLK, BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS);

bool playing = false;

char dirInfo[1024];

bool breathing = false;
bool blinking = false;

void setup() {
    
    pinMode(RANDOMPIN, INPUT);
    pinMode(MARCHPIN, INPUT);
    
    pinMode(RELAY_1, OUTPUT);
    pinMode(RELAY_2, OUTPUT);
    
    digitalWrite(RELAY_1, HIGH);
    digitalWrite(RELAY_2, HIGH);
    
    //Serial.begin(9600);
    
    if (!SD.begin(MOSI, MISO, CLK, CARDCS)) { // initialize the SD card
        //Serial.println(F("SD failed, or not present"));
        Particle.process();
    }
    //Serial.println("SD OK!");    
    
    Spark.function("play", playSound);
    Spark.function("randomPlay", playRandomSound);
    Spark.function("toggleRelay1", toggleRelayBreathe);
    Spark.function("toggleRelay2", toggleRelayLights);

    // list files
    printDirectory(SD.open("/"), 0); 
    
    Spark.variable("listFiles", dirInfo);

    
    delay(1000); //to allow user to start up serial com.
    
    if (! musicPlayer.begin()) { // initialize the music player
      //Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    } else {
      //Serial.println(F("VS1053 found"));

      // Set volume for left, right channels. lower numbers == louder volume!
      musicPlayer.setVolume(15,15);

      // Play one file, don't return until complete
      //Serial.println(F("Playing vaderbreath"));
      playing = true;
      //musicPlayer.playFullFile("/Init/vaderbr.mp3");
      musicPlayer.playFullFile("ysmaster.mp3");

    }    

}

int playSound(String args) {
 
    if (args != "" ) {
      // Play one file, don't return until complete

      //Serial.println("Playing Track " + args + ".mp3");
      args = args + ".mp3";

      char inData[30];
      args.toCharArray(inData,30);
      
      digitalWrite(RELAY_1, HIGH);
      musicPlayer.playFullFile(inData);
      if (breathing = true)
      {
          digitalWrite(RELAY_1, LOW);
      }

      args = "";
      
      return 1;
      
    }
    
}

int playRandomSound(String args) {
    
    File path = SD.open("/");
    File results;
    char* MP3 = selectRandomFileFrom(path, results);
    delay(100);

    digitalWrite(RELAY_1, HIGH);
    musicPlayer.playFullFile(MP3);
    if (breathing = true)
    {
     digitalWrite(RELAY_1, LOW);
    }
}

int toggleRelayBreathe(String args) {
    
    if (args != "") {
        
        if (args.startsWith("ENABLE"))
        {
            blinking = true;
            digitalWrite(RELAY_1, LOW);
        }
        
        if (args.startsWith("DISABLE"))
        {
            blinking = false;
            digitalWrite(RELAY_1, HIGH);
        }
        
    }
    
}

int toggleRelayLights(String args) {
    
    if (args != "") {
        
        if (args.startsWith("ENABLE"))
        {
            breathing = true;
            digitalWrite(RELAY_2, LOW);
        }
        
        if (args.startsWith("DISABLE"))
        {
            breathing = false;
            digitalWrite(RELAY_2, HIGH);
        }
        
    }
    
}

void loop() {
    // File is playing in the background
    if ((musicPlayer.stopped()) && playing) {
        //Serial.println("Done playing music");
        playing = false;
    }

    delay(100);

    int randomNewState = digitalRead(RANDOMPIN);
    int marchNewState = digitalRead(MARCHPIN);
    
    if (randomNewState == 0 && randomState == 1) {

        // put your main code here, to run repeatedly:
        File path = SD.open("/");
        File results;
        char* MP3 = selectRandomFileFrom(path, results);
        delay(100);

        musicPlayer.playFullFile(MP3);

    }
    
    randomState = randomNewState;
    
    if (marchNewState == 0 && marchState == 1) {
        musicPlayer.playFullFile("/Music/imperial.mp3");
    }
    
    marchState = marchNewState;    

}

// Function to select random mp3
char* selectRandomFileFrom( File dir, File result ) {
    File entry;
    int count = 0;

    dir.rewindDirectory();

    while ( entry = dir.openNextFile() ) {
        if (random( count ) == 0) {
        //Serial.println(entry.name());
        result = entry;
    }
    entry.close();
    count++;
    }
    return result.name();   // returns the randomly selected file name
}

/// File listing helper
void printDirectory(File dir, int numTabs) {
    String sFiles;
    while(true) {
     
        File entry =  dir.openNextFile();
        if (! entry) {
            // no more files
            //Serial.println("**nomorefiles**");
            break;
        }
        for (uint8_t i=0; i<numTabs; i++) {
            //Serial.print('\t');
        }
        //Serial.print(entry.name());
        if (entry.isDirectory()) {
            //Serial.println("/");
            //printDirectory(entry, numTabs+1);
        } else {
            // files have sizes, directories do not
            //Serial.print("\t\t");
            //Serial.println(entry.size(), DEC);
            String f = entry.name();
            f.replace(".MP3","");
            sFiles = sFiles + f + "|";
        }
        entry.close();
    }
    sFiles.toCharArray(dirInfo, 1024);
}

Adafruit VS1053 Photon

This is a library for the Adafruit VS1053 Codec Breakout. Adapted for Spark Core by Paul Kourany, Nov 24, 2014. Tweaks by myself to work with my project.

ParticleNET/ParticleSDK

Darth Vader Windows 10 Universal Application to control Particle Photon

This is the source for a Windows 10 Universal Application to remotely control a Particle Photon for MP3 playing.

Credits

Dave VanderWekke

Dave VanderWekke

1 project • 1 follower
Engineer, Blogger, Foodie, Tinkerer, Techie

Comments