Skip to content

Instantly share code, notes, and snippets.

@mikedotalmond
Created April 9, 2016 01:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikedotalmond/d5fdd7110fa4114b54f1dfc5c5d73b95 to your computer and use it in GitHub Desktop.
Save mikedotalmond/d5fdd7110fa4114b54f1dfc5c5d73b95 to your computer and use it in GitHub Desktop.
PIR audio trigger
/*
*/
#include <WaveHC.h>
#include <WaveUtil.h>
const int minimumSoundInterval = 2000;
const int soundIntervalRange = 8000;
boolean playingSound = false;
int lastPlayed = 0;
SdReader card; // This object holds the information for the card
FatVolume vol; // This holds the information for the partition on the card
FatReader root; // This holds the information for the volumes root directory
FatReader file; // This object represent the WAV file
WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
/*
* Define macro to put error messages in flash memory
*/
#define error(msg) error_P(PSTR(msg))
#define FILE_COUNT 29
#define PIR_CALIBRATION_TIME 20000
#define DEBUG false
// PIR Sensor
int calibrationTime = PIR_CALIBRATION_TIME;
const int PIRPin = 6;
const int LEDPin = 7;
boolean takeLowTime;
boolean pirReady = false;
boolean motionDetected = false;
//
uint32_t lastT = 0;
//////////////////////////////////// SETUP
void setup() {
#if DEBUG
Serial.begin(9600);
#endif
randomSeed(analogRead(0));
pinMode(PIRPin, INPUT);
pinMode(LEDPin, OUTPUT);
calibratePIR();
setupAudio();
}
// call to (re)calibrate
void calibratePIR(){
digitalWrite(PIRPin, LOW);
digitalWrite(LEDPin, LOW);
calibrationTime = PIR_CALIBRATION_TIME;
pirReady = false;
}
void setupAudio(){
if (!card.init()) error("card.init");
// enable optimized read - some cards may timeout
card.partialBlockRead(true);
if (!vol.init(card)) error("vol.init");
if (!root.openRoot(vol)) error("openRoot");
indexFiles();
//
playByIndex(0);
}
//////////////////////////////////// LOOP
void loop() {
uint32_t t = millis();
uint32_t dt = t - lastT;
lastT = t;
bool hadMotion = motionDetected;
checkPIR(t, dt);
if(playingSound && !wave.isplaying) {
// playback ended
playingSound = false;
lastPlayed = 0;
wave.stop();
// check for play errors
sdErrorCheck();
} else {
lastPlayed += dt;
}
if(!playingSound && /* not playing? */
((!hadMotion && motionDetected) || /* new motion started */
(motionDetected && lastPlayed > minimumSoundInterval + random(soundIntervalRange)) /* old motion continued for a while */
)){
playByIndex(random(FILE_COUNT-1));
}
}
//
void checkPIR(uint32_t t, int dt) {
if(pirReady){
if(digitalRead(PIRPin) == HIGH){ // detected
digitalWrite(LEDPin, HIGH);
if(!motionDetected){
motionDetected = true;
#if DEBUG
Serial.println("---");
Serial.print("motion detected at ");
Serial.print(t/1000);
Serial.println(" sec");
#endif
}
} else {
if(motionDetected){
digitalWrite(LEDPin, LOW);
motionDetected = false;
#if DEBUG
Serial.print("motion ended at ");
Serial.print(millis()/1000);
Serial.println(" sec");
#endif
}
}
} else {
calibrationTime -= dt;
if(calibrationTime <= 0){
pirReady = true;
digitalWrite(LEDPin, LOW);
#if DEBUG
Serial.println("PIR Calibration complete");
#endif
}
}
}
/////////////////////////////////// HELPERS
/*
* print error message and halt
*/
void error_P(const char *str) {
#if DEBUG
PgmPrint("Error: ");
SerialPrint_P(str);
#endif
sdErrorCheck();
while(1);
}
/*
* print error message and halt if SD I/O error, great for debugging!
*/
void sdErrorCheck(void) {
if (!card.errorCode()) return;
#if DEBUG
PgmPrint("\r\nSD I/O error: ");
Serial.print(card.errorCode(), HEX);
PgmPrint(", ");
Serial.println(card.errorData(), HEX);
#endif
while(1);
}
char fileLetter[] = {
'0','1','2','3','4','5','6','7','8','9',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s'
};
// index of files in the root directory
uint16_t fileIndex[FILE_COUNT];
/*
* Find files and save file index. A file's index is is the
* index of it's directory entry in it's directory file.
*/
void indexFiles(void) {
char name[10];
// copy flash string to RAM
strcpy_P(name, PSTR("gary-x.wav"));
for (uint8_t i = 0; i < FILE_COUNT; i++) {
// Make file name
name[5] = fileLetter[i];
#if DEBUG
Serial.println(name);
#endif
// Open file by name
if (!file.open(root, name)) error("open by name");
// Save file's index (byte offset of directory entry divided by entry size)
// Current position is just after entry so subtract one.
fileIndex[i] = root.readPosition()/32 - 1;
}
#if DEBUG
PgmPrintln("Done");
#endif
}
/*
* Play file by index and print latency in ms
*/
void playByIndex(int i) {
if (!file.open(root, fileIndex[i])) error("open by index");
if (!wave.create(file)) error("wave.create");
wave.play();
playingSound = true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment