Wednesday, October 6, 2010

Arduino, PIR, and MP3 - oh my!

In this post, I'll try and explain as best I can how to use an Arduino to play a sound file from a hacked MP3 player.  The sound file will be triggered using a passive infrared sensor (PIR sensor) hooked up to the Arduino's output. 

Here are the parts I used:
Let's get started...



Coby MP3 Player
Here is a photo of the Coby MP3 player that I bought.  It was relatively cheap ($14.00) so I bought two.



Time to disassemble it.  Remove the two screws on the back and slide a thin flat blade screwdriver (or knife - be careful!) between the white plastic and black plastic body and pry up.  The two halves should pop apart.
 There are a few more screws to remove on the circuit board and then it should pop out of the case.

The object now is to determine how to simulate pressing one of the buttons.  Using a short wire, I touched the top left (or right) of the button (where it is soldered to the board - it is tiny!) to the bottom right (or left) of the same button.  This is the same as if you were to push the actual button - it completes the circuit.  Obviously, this process will depend on what make/model mp3 player you have, so YMMV.

Now on to the hard part (at least for this mp3 player) - soldering some extension wires that can be then hooked up to the Arduino. 

Since the circuit board is out of the case, the AAA battery won't stay between the two contacts.  I just added extension wires from the + and - contacts on the board and used electrical tape to hold the connection.  If you had a AAA battery case, you could use that.


I make no claims that I am very good at soldering (look at that?!).  As I said, the contact points are TINY and I had a hard time getting a good connection.  However, here's a picture of what you would theoretically want to do.  The button that the wires are soldered to is, of course, the play/pause button.
 You can test by simply touching the two wires together.  The mp3 player should start playing.  Touch them again, and it will pause. 

The Bad...
One thing you might notice is that the mp3 player goes to "sleep" after a few minutes of inactivity.  If you hold the wires together for more than a couple seconds, the LED on the board will blink 3 times and wake up.  Clearly, this isn't ideal for a prop which might be sitting idle waiting for a signal from a PIR sensor.  Also, I noticed that when the sound would play (or pause) it would fade in and out rather than just start (or stop) playing.  Again, not the ideal situation unless you are wanting to gradually scare someone.   Yah, I thought not.

The Good...
This is where I decided I would use the USB2M module instead.  I felt it necessary to keep the above instructions and photos in this blog as other mp3 players might not have this problem. 

USB2M Player
Here is a photo of the USB2M device.  No real need to disassemble anything other than removing it from the paper it comes attached to.


One other thing that I did do was to clip off the leads to the push button and install a 2 pin header so I could easily attach some wires to it.



Continuing on...

Building the circuit

Here is a photo of the completed circuit on the Arduino.  I'll step through where each wire should go.


  1. Connect a wire from one side of the relay coil to 5V on the Arduino (in the picture above, it is the brown wire in the lower right running diagonal).
  2. Insert the diode (cathode (-) towards 5V) from 5V on the Arduino to the other side of the relay coil.
  3. Connect a wire from the relay coil in step 2 to the collector of the transistor (in the picture above, it is the brown wire at the bottom running horizontal)
  4. Connect a wire from the base of the transistor to digital out 2 on the Arduino
  5. Connect a wire from the emitter of the transistor to ground on the Arduino.
  6. Connect a 1K ohm resistor from the base of the transistor to ground on the Arduino
  7. Connect one of the leads from the USB2M to the common pin of the relay (in picture above the common pin of the relay is the lower left corner of the relay and is the blue wire going out of frame in the bottom right).
  8. Connect the other lead from the USB2M to the normally open pin of the relay (in the picture above, it is the blue wire at the top of the relay going straight up out of frame - 4 holes from the right side of the breadboard).  NOTE:  Don't connect this to the normally closed pin (3 holes from the right side of the breadboard) or the USB2M will play the sound file continuously UNTIL the PIR is tripped - exactly opposite of what we want.
  9. On the back of the PIR, there are three pins: positive, negative and out.  Connect positive to 5V on the Arduino.  Connect negative to ground on the Arduino.  Connect out to digital out 3 on the Arduino.
  10. Done!
Arduino Sketch

The wonderful internet already had a sketch for hooking up a PIR to an Arduino so I used that and just tweaked it a bit to introduce another output pin (the mp3Pin).  The sketch is below (my additions are in red):


/*
 * //////////////////////////////////////////////////
 * //making sense of the Parallax PIR sensor's output
 * //////////////////////////////////////////////////
 *
 * Switches a LED according to the state of the sensors output pin.
 * Determines the beginning and end of continuous motion sequences.
 *
 * @author: Kristian Gohlke / krigoo (_) gmail (_) com / http://krx.at
 * @date:   3. September 2006
 *
 * kr1 (cleft) 2006
 * released under a creative commons "Attribution-NonCommercial-ShareAlike 2.0" license
 * http://creativecommons.org/licenses/by-nc-sa/2.0/de/
 *
 *
 * The Parallax PIR Sensor is an easy to use digital infrared motion sensor module.
 * (http://www.parallax.com/detail.asp?product_id=555-28027)
 *
 * The sensor's output pin goes to HIGH if motion is present.
 * However, even if motion is present it goes to LOW from time to time,
 * which might give the impression no motion is present.
 * This program deals with this issue by ignoring LOW-phases shorter than a given time,
 * assuming continuous motion is present during these phases.
 * 
 */

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 10;       

//the time when the sensor outputs a low impulse
long unsigned int lowIn;        

//the amount of milliseconds the sensor has to be low
//before we assume all motion has stopped
long unsigned int pause = 1000; 

boolean lockLow = true;
boolean takeLowTime; 

int pirPin = 3;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;
int mp3Pin = 2;


/////////////////////////////
//SETUP
void setup(){
  Serial.begin(38400);
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(mp3Pin, OUTPUT);  //set mp3Pin as an output
  digitalWrite(pirPin, LOW);
  digitalWrite(mp3Pin, LOW); //set mp3Pin to low ("off")

  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
    Serial.println(" done");
    Serial.println("SENSOR ACTIVE");
    delay(50);
  }

////////////////////////////
//LOOP
void loop(){

     if(digitalRead(pirPin) == HIGH){
       digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
       digitalWrite(mp3Pin, HIGH);  //send a signal on the mp3Pin to have the relay trigger the sound
       delay(5); //wait
       digitalWrite(mp3Pin,LOW);  //bring the mp3Pin back low so the relay closes and doesn't loop the sound
       if(lockLow){ 
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;           
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec");
         delay(50);
         }        
         takeLowTime = true;
       }

     if(digitalRead(pirPin) == LOW){      
       digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state
       digitalWrite(mp3Pin, LOW);
       if(takeLowTime){
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }
       //if the sensor is low for more than the given pause,
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){ 
           //makes sure this block of code is only executed again after
           //a new motion sequence has been detected
           lockLow = true;                       
           Serial.print("motion ended at ");      //output
           Serial.print((millis() - pause)/1000);
           Serial.println(" sec");
           delay(50);
           }
       }
  }



Testing it out

The USB2M has its own utility to load sounds onto the device.  You can download it from the 123Electronics website for free.  Simply insert the device into a USB port and browse for a file and click Record (high quality or low quality).

Fire up the Arduino and load the sketch.  After the calibration period (15 seconds or so) you should be able to wave your hand in front of the PIR and it should trigger the sound to play.  If it doesn't work, check your connections.

You can tweak the sketch as you see fit.  This is really just a basic quick how-to in order to get you started.  One tweak I can see as being useful would be to add a delay after the PIR is triggered.  This would be useful when you'd like the PIR to be tripped but let the victim walk a little further down the path before the sound triggers.

No comments:

Post a Comment