# Help with Catalex MP3 and Pir



## theundeadofnight (Aug 14, 2011)

Hi All ,

Need help with an Arduino sketch that uses a Pir as a trigger to play mp3 on Catalex player . I can get the Pir to work and I can get the Catalex to work , just not together  . Anybody have a sketch they want to share ?

Thanks ,
Tom


----------



## JeffHaas (Sep 7, 2010)

Hi Tom,

Here's my 3-Stage Timer code for the Arduino and a PIR, Catalex module and two relays. It's called a "3-Stage Timer" because there is an old DIY project that haunters used to make which allowed them to control a prop. I took the type of control it had and converted it to Arduino. The code is commented, so it should all be pretty easy to figure out. I've taught a couple of Make & Take workshops with it here in Northern California and people have had good success with it.

The connections are specified in the code, and you can open the Serial Monitor to see what's going on while it warms up and detects movement.

Jeff


```
/*
 * Northern California Haunters Group - 3-Stage Timer, for Make & Take workshop, March 2016
 * Based on AdaFruit example code, and EFX-Tek Prop-1 code
 * Works with a PIR and dual relay board
 * 8/13/2012 by Jeff Haas
 * Updated 9/16/2015 to deal with relays that are activated either HIGH or LOW (change Is_On and Is_Off below)
 */
// Allows an Arduino to act as a 3-Stage Timer and control two relays, with optional delay between relays.
// Includes blinking LED for PIR warmup, and easy to change Prop Timing variables.
//
// After uploading sketch, click the Serial Monitor button or press CTRL + SHIFT + M
// to see debug info on Serial Monitor.
// 
/////////////////////////////
//VARIABLES 
int pirPin = 7;                 // input pin for PIR sensor
int relay1 = 2;                // digital pin connected to relay1
int relay2 = 3;                // digital pin connected to relay2
int ledPin = 13;                // pin for the built-in LED

#define ARDUINO_RX A4    // (Optional) Connect to TX of the Catalex MP3 Player module 
#define ARDUINO_TX A5    //  Connect ANALOG 5 to RX of the Catalex - sends commands

//Prop Timing variables
int calibrationTime = 60;       // Set PIR calibration time.  Should be 60 seconds for good warmup.  Time in seconds.
int PropWait = 0;               // Pause before props go off after motion is detected.  Time in seconds.
int Rly1Run = 9;                // How long Relay1 runs.  Time in seconds.
int PropGap = 1;                // Time between first relay going off and second relay going off.  Time in seconds.
int Rly2Run = 1;                // How long Relay2 runs.  Time in seconds.
int ResetTime = 2;             // Run time of prop + PIR cool down + desired wait time for next trigger.  Time in seconds.


//  CONSTANTS - Relay configuration
const byte Is_Off = 0;                 // For relays that work the opposite way (HIGH is Off) change this to 1
const byte Is_On = 1;                  // For relays that work the opposite way (LOW is On) change this to 0

// PIR tracking
int pirState = LOW;             // we start, assuming no motion detected
int PirVal = 0;                 // variable for reading the pin status
int TIMER = 0;                  // For tracking PIR debounce

// Catalex MP3 board needs the following for communication and commands
#include <SoftwareSerial.h>
SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);

static int8_t Send_buf[8] = {0} ;
#define CMD_SEL_DEV 0X09      // Catalex commands
#define DEV_TF 0X02
#define CMD_PLAY_W_VOL 0X22



/////////////////////////////
//SETUP 
void setup() {

  // Needed for Catalex board
  mySerial.begin(9600);
  delay(500);                               //Wait for chip initialization to complete
  sendCommand(CMD_SEL_DEV, DEV_TF);         //select the TF card  
  delay(200);                               //wait for 200ms
  
  pinMode(pirPin, INPUT);       // declare PIR sensor as input
  pinMode(relay1, OUTPUT);      // declare relay1 as output
  pinMode(relay2, OUTPUT);      // declare relay2 as output
  pinMode(ledPin, OUTPUT);      // declare LED as output
 
  Serial.begin(9600);           // Use Serial Monitor to debug

  digitalWrite(relay1, Is_Off);            // Turn relay1 OFF
  digitalWrite(relay2, Is_Off);            // Turn relay2 OFF
    
//Give the PIR sensor some time to calibrate
  Serial.print("Calibrating sensor");  
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
        digitalWrite(ledPin, HIGH);  // Blink LED while PIR is calibrating
        delay (500);
        digitalWrite(ledPin, LOW);
        delay (500);
      }
    Serial.println("done.");
    Serial.println("SENSOR ACTIVE");
    delay(50); 
}

////////////////////////////
//LOOP 
void loop(){
                                      // Use EFX-Tek debounce code to read button press
  PirVal = digitalRead(pirPin);       // Read input value
  TIMER = TIMER + 5 * PirVal;         // PIR debounce code
//  Serial.println(TIMER);            // Show value of TIMER for setting sensitivity of debounce
  if (TIMER > 100) {                  // Wait for 0.1 sec input
  
  Serial.println("Motion detected");   
    if (pirState == LOW) {          // The PIR has just turned on, but the variable for the PIR's state is LOW...
      pirState = HIGH;              // ...so change the value to HIGH.  Print only on the output change, not state.
    }

// Now turn everything on to trigger the props!

    for(int j = 0; j < PropWait; j++){    // Delay before the first relay is triggered  
      Serial.print(".");
      delay(1000);
      }
  
    Serial.println("Relay 1!");
    
    sendCommand(CMD_PLAY_W_VOL, 0X0F01);      //play the first MP3 with volume 15 class

    
    digitalWrite(ledPin, HIGH);           // Turn LED ON for a visual indicator
    digitalWrite(relay1, Is_On);           // Turn relay1 ON

      for(int j = 0; j < Rly1Run; j++){   // Time Relay1 runs
      Serial.print(".");
      delay(1000);
      }
    
    digitalWrite(relay1, Is_Off);            // Turn relay1 OFF

      for(int j = 0; j < PropGap; j++){  // Delay between triggering Relay1 and Relay2
      Serial.print(".");
      delay(1000);
      }

    Serial.println("Relay 2!");       

    digitalWrite(relay2, Is_On);           // Turn relay2 ON

      for(int j = 0; j < Rly2Run; j++){   // Time Relay2 runs
      Serial.print(".");
      delay(1000);
      }

    digitalWrite(ledPin, LOW);      // Turn LED OFF
    digitalWrite(relay2, Is_Off);      // Turn relay2 OFF

    TIMER = 0;                      // Reset TIMER byte
    
    Serial.print("Reset");          // Prop reset time.
             
    for(int j = 0; j < ResetTime; j++){  
      Serial.print(".");
      delay(1000);
      }

  } else {
    if (pirState == HIGH){     // We have just turned off, so pirState is HIGH
      Serial.println("Ready"); // We only want to print on the output change, not state
      pirState = LOW;          // Reset variable that tracks the PIR's state.
    }
  }
  delay(5);        // Brief pause on the checking loop.  Acts as debounce delay.
}

void sendCommand(int8_t command, int16_t dat)  // For sending commands to Catalex
{
  delay(20);
  Send_buf[0] = 0x7e; //starting byte
  Send_buf[1] = 0xff; //version
  Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
  Send_buf[3] = command; //
  Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback
  Send_buf[5] = (int8_t)(dat >> 8);//datah
  Send_buf[6] = (int8_t)(dat); //datal
  Send_buf[7] = 0xef; //ending byte
  for(uint8_t i=0; i<8; i++)//
  {
    mySerial.write(Send_buf[i]) ;
  }
}
```


----------



## theundeadofnight (Aug 14, 2011)

Hi Jeff ,

Thanks very much for the quick reply and the sketch .The comments were very helpful . I changed the pin numbers to match my set up and everything works great .

I need to have the animation stop at the same time as the audio track , fairly sure I can do that by changing the relay run times ?

I will be replacing the relays with a DC motor / H Bridge eventually , hopefully no surprises . I already had the H Bridge and PIR working separately but I could never get it to work with the audio . Fingers crossed 

Tom


----------



## JeffHaas (Sep 7, 2010)

Just time the length of the mp3 you want to play and then update the relay run times to match. You can test it without connecting to a prop, just watch the relays turn on and off with headphones plugged into the Catalex.


----------

