Created
November 29, 2016 12:38
-
-
Save velophonic/3eab6d4c64d7ac6dcc6235d1799f09b4 to your computer and use it in GitHub Desktop.
Arduino code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Knock Sensor sound | |
This sketch reads a piezo element to detect a knocking sound. | |
It reads an analog pin and compares the result to a set threshold. | |
If the result is greater than the threshold, it writes | |
"knock" to the serial port, and toggles the LED on pin 13. | |
This example plays every .WAV file it finds on the SD card when piezo is "knocked" | |
*/ | |
#include <FatReader.h> | |
#include <SdReader.h> | |
#include <avr/pgmspace.h> | |
#include <WaveHC.h> | |
#include <WaveUtil.h> | |
SdReader card; // This object holds the information for the card | |
FatVolume vol;// This holds the information for the partition on the card | |
FatReader root; | |
FatReader f; // This holds the information for the volumes root directory | |
WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time | |
uint8_t dirLevel; // indent level for file/dir names (for prettyprinting) | |
dir_t dirBuf; // buffer for directory reads | |
//Define macro to put error messages in flash memory | |
#define error(msg) error_P(PSTR(msg)) | |
// Function definitions (we define them here, but the code is below) | |
void play(FatReader &dir); | |
// these constants won't change: | |
const int ledPin = 13; // led connected to digital pin 13 | |
const int knockSensor1 = A0; // the piezo is connected to analog pin 0 | |
const int knockSensor2 = A1; // the piezo is connected to analog pin 0 | |
const int knockSensor3 = A2; // the piezo is connected to analog pin 0 | |
const int knockSensor4 = A3; // the piezo is connected to analog pin 0 | |
const int threshold = 50; // threshold value to decide when the detected sound is a knock or not | |
// these variables will change: | |
int sensorReading1 = 0; // variable to store the value read from the sensor pin | |
int sensorReading2 = 0; | |
int sensorReading3 = 0; | |
int sensorReading4 = 0; | |
int ledState = LOW; // variable used to store the last LED status, to toggle the light | |
//////////////////////////////////// SETUP | |
void setup() { | |
pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT | |
Serial.begin(9600); // use the serial port | |
putstring_nl("\nWave test!"); // say we woke up! | |
putstring("Free RAM: "); // This can help with debugging, running out of RAM is bad | |
Serial.println(FreeRam()); | |
// if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you | |
if (!card.init()) { //play with 8 MHz spi (default faster!) | |
error("Card init. failed!"); // Something went wrong, lets print out why | |
} | |
// enable optimize read - some cards may timeout. Disable if you're having problems | |
card.partialBlockRead(true); | |
// Now we will look for a FAT partition! | |
uint8_t part; | |
for (part = 0; part < 5; part++) { // we have up to 5 slots to look in | |
if (vol.init(card, part)) | |
break; // we found one, lets bail | |
} | |
if (part == 5) { // if we ended up not finding one :( | |
error("No valid FAT partition!"); // Something went wrong, lets print out why | |
} | |
// Lets tell the user about what we found | |
putstring("Using partition "); | |
Serial.print(part, DEC); | |
putstring(", type is FAT"); | |
Serial.println(vol.fatType(), DEC); // FAT16 or FAT32? | |
// Try to open the root directory | |
if (!root.openRoot(vol)) { | |
error("Can't open root dir!"); // Something went wrong, | |
} | |
// Whew! We got past the tough parts. | |
putstring_nl("Files found (* = fragmented):"); | |
// Print out all of the files in all the directories. | |
root.ls(LS_R | LS_FLAG_FRAGMENTED); | |
} | |
//////////////////////////////////// LOOP | |
void loop() { | |
// read the sensors and store it in the variable sensorReading: | |
sensorReading1 = analogRead(knockSensor1); | |
sensorReading2 = analogRead(knockSensor2); | |
sensorReading3 = analogRead(knockSensor3); | |
sensorReading4 = analogRead(knockSensor4); | |
// if the sensor reading is greater than the threshold: | |
if (sensorReading1 >= threshold) { | |
//play sound | |
playcomplete("DO.WAV"); | |
// toggle the status of the ledPin: | |
ledState = !ledState; | |
// update the LED pin itself: | |
digitalWrite(ledPin, ledState); | |
// send the string "Knock!" back to the computer, followed by newline | |
Serial.println("Knock1!"); | |
} | |
if (sensorReading2 >= threshold) { | |
//play sound | |
playcomplete("RE.WAV"); | |
// toggle the status of the ledPin: | |
ledState = !ledState; | |
// update the LED pin itself: | |
digitalWrite(ledPin, ledState); | |
// send the string "Knock!" back to the computer, followed by newline | |
Serial.println("Knock2!"); | |
} | |
if (sensorReading3 >= threshold) { | |
//play sound | |
playcomplete("MI.WAV"); | |
// toggle the status of the ledPin: | |
ledState = !ledState; | |
// update the LED pin itself: | |
digitalWrite(ledPin, ledState); | |
// send the string "Knock!" back to the computer, followed by newline | |
Serial.println("Knock3!"); | |
} | |
if (sensorReading4 >= threshold) { | |
//play sound | |
playcomplete("FA.WAV"); | |
// toggle the status of the ledPin: | |
ledState = !ledState; | |
// update the LED pin itself: | |
digitalWrite(ledPin, ledState); | |
// send the string "Knock!" back to the computer, followed by newline | |
Serial.println("Knock4!"); | |
} | |
delay(10); // delay to avoid overloading the serial port buffer | |
} | |
/////////////////////////////////// HELPERS | |
/* | |
* print error message and halt | |
*/ | |
void error_P(const char *str) { | |
PgmPrint("Error: "); | |
SerialPrint_P(str); | |
sdErrorCheck(); | |
while(1); | |
} | |
/* | |
* print error message and halt if SD I/O error, great for debugging! | |
*/ | |
void sdErrorCheck(void) { | |
if (!card.errorCode()) return; | |
PgmPrint("\r\nSD I/O error: "); | |
Serial.print(card.errorCode(), HEX); | |
PgmPrint(", "); | |
Serial.println(card.errorData(), HEX); | |
while(1); | |
} | |
/* | |
* play recursively - possible stack overflow if subdirectories too nested | |
*/ | |
void play(FatReader &dir) { | |
FatReader file; | |
while (dir.readDir(dirBuf) > 0) { // Read every file in the directory one at a time | |
// Skip it if not a subdirectory and not a .WAV file | |
if (!DIR_IS_SUBDIR(dirBuf) | |
&& strncmp_P((char *)&dirBuf.name[8], PSTR("WAV"), 3)) { | |
continue; | |
} | |
Serial.println(); // clear out a new line | |
for (uint8_t i = 0; i < dirLevel; i++) { | |
Serial.write(' '); // this is for prettyprinting, put spaces in front | |
} | |
if (!file.open(vol, dirBuf)) { // open the file in the directory | |
error("file.open failed"); // something went wrong | |
} | |
if (file.isDir()) { // check if we opened a new directory | |
putstring("Subdir: "); | |
printEntryName(dirBuf); | |
Serial.println(); | |
dirLevel += 2; // add more spaces | |
// play files in subdirectory | |
play(file); // recursive! | |
dirLevel -= 2; | |
} | |
else { | |
// Aha! we found a file that isnt a directory | |
putstring("Playing "); | |
printEntryName(dirBuf); // print it out | |
if (!wave.create(file)) { // Figure out, is it a WAV proper? | |
putstring(" Not a valid WAV"); // ok skip it | |
} else { | |
Serial.println(); // Hooray it IS a WAV proper! | |
wave.play(); // make some noise! | |
uint8_t n = 0; | |
while (wave.isplaying) {// playing occurs in interrupts, so we print dots in realtime | |
putstring("."); | |
if (!(++n % 32))Serial.println(); | |
delay(100); | |
} | |
sdErrorCheck(); // everything OK? | |
// if (wave.errors)Serial.println(wave.errors); // wave decoding errors | |
} | |
} | |
} | |
} | |
// Plays a full file from beginning to end with no pause. | |
void playcomplete(char *name) { | |
// call our helper to find and play this name | |
playfile(name); | |
while (wave.isplaying) { | |
// do nothing while its playing | |
} | |
// now its done playing | |
} | |
void playfile(char *name) { | |
// see if the wave object is currently doing something | |
if (wave.isplaying) {// already playing something, so stop it! | |
wave.stop(); // stop it | |
} | |
// look in the root directory and open the file | |
if (!f.open(root, name)) { | |
putstring("Couldn't open file "); Serial.print(name); return; | |
} | |
// OK read the file and turn it into a wave object | |
if (!wave.create(f)) { | |
putstring_nl("Not a valid WAV"); return; | |
} | |
// ok time to play! start playback | |
wave.play(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment