Hi guys,
I'm working on building a wedding phone where messages can be recorded by guests. I am building this project based on the following video:
I think a lot of people here have been working to build the same project.
My code below:
It appears that program is correctly switching to the startRecording() function as I can see the "Actually started record" line on the serial monitor, but the program does not appear to be creating a file on my sd card (I checked and there are no files on it). Additionally, it seems to then go into a weird mode where it doesn't register any change in the hook switch being replaced, and restarts after about 5 seconds. I've scoured a lot of the forum and am having a hard time troubleshooting this issue.
Any ideas why this isn't working? I believe I am using the correct library for the SD card (Using library SD at version 2.0.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SD) as show in the verbose info below. Also, if you see any glaring issues in the code please let me know. Any help is appreciated!
Multiple libraries were found for "SD.h"
Used: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SD
Not used: C:\Program Files (x86)\Arduino\libraries\SD
Using library Bounce in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Bounce (legacy)
Using library Audio at version 1.3 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio
Using library SPI at version 1.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SPI
Using library SD at version 2.0.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SD
Using library SdFat at version 2.1.2 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SdFat
Using library SerialFlash at version 0.5 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SerialFlash
Using library Wire at version 1.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Wire
Using library Time at version 1.6.1 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Time
C:\Program Files (x86)\Arduino\hardware\teensy/../tools/teensy_post_compile -file=AudioGuestbook.ino -path=C:\Users\jakew\AppData\Local\Temp\arduino_build_166691 -tools=C:\Program Files (x86)\Arduino\hardware\teensy/../tools -board=TEENSY40 -reboot -port=usb:0/140000/0/4 -portlabel=hid#vid_16c0&pid_0478 Bootloader -portprotocol=Teensy
I'm working on building a wedding phone where messages can be recorded by guests. I am building this project based on the following video:
My code below:
Code:
#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <TimeLib.h>
//DEFINES
//Define pins used by Teensy Audio Shield
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
//And those used for inputs
#define HOOK_PIN 0
#define PLAYBACK_BUTTON_PIN 1
//GLOBALS
//Audio initialization code can be generated using the GUI interface at *insert link Alister puts in”*
//Inputs
AudioSynthWaveform waveform1; // To create the “beep” sfx
AudioInputI2S i2s2; // I2S input from microphone on audio shield
AudioPlaySdRaw playRaw1; // Play.RAW audio files saved on SD card
AudioPlaySdWav playWav1; // Play 44.1 kHz 16-bit PCM greeting WAV file
//Outputs
AudioRecordQueue queue1; // Creating and audio buffer in memory before saving to SD
AudioMixer4 mixer; // Allows merging several inputs to same output
AudioOutputI2S i2s1; //I2S interface to Speaker/Line Out on Audio Shield
//Connections
AudioConnection patchCord1(waveform1, 0, mixer, 0); // wave to mixer
AudioConnection patchCord2(playRaw1, 0, mixer, 1); // raw audio to mixer
AudioConnection patchCord3(playWav1, 0, mixer, 2); // wav file to playback mixer
AudioConnection patchCord4(mixer, 0, i2s1, 0); // mixer output to speaker (L)
AudioConnection patchCord5(i2s2, 0, queue1, 0); // mic input to queue (L)
AudioControlSGTL5000 sgt15000_1;
//Filename to save audio recording on SD card
char filename(15);
//The file object itself
File frec;
//Use ling 40ms debounce time on hook switch
Bounce buttonRecord = Bounce(HOOK_PIN, 40);
Bounce buttonPlay = Bounce(PLAYBACK_BUTTON_PIN, 8);
// Keep track of current state of the device
enum Mode {Initialising, Ready, Prompting, Recording, Playing};
Mode mode = Mode::Initialising;
void setup() {
// Note that Serial.begin() is not required for Teensy -
// By default it initializes serial communication at full USB speed
// See https://www.prjc.com/teensy/td_serial.html
// Serial.begin()
Serial.println(__FILE__ __DATE__);
// Configure the input pins
pinMode(HOOK_PIN, INPUT_PULLUP);
pinMode(PLAYBACK_BUTTON_PIN, INPUT_PULLUP);
// Audio connections require memory, and the record queue
// uses this memory to buffer incoming audio.
AudioMemory(60);
// Enable the audio shield, select input, and enable output
sgt15000_1.enable();
// Define which input on the audio shield to use (AUDIO_INPUT_LINEIN / AUDIO_INPUT_MIC)
sgt15000_1.inputSelect(AUDIO_INPUT_MIC);
sgt15000_1.volume(0.5);
// Play a beep to indicate system is online
waveform1.begin(WAVEFORM_SINE);
waveform1.frequency(440);
waveform1.amplitude(0.9);
wait(250);
waveform1.amplitude(0);
delay(1000);
//Initialise the SD card
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
//stop here if no SD card, but print a message
while (1) {
Serial.println("Unable to access the SD card");
delay(1000);
}
}
//Calue in dB
sgt15000_1.micGain(15);
//Synchronize the Time object used in the program code with the RTC time provider
//See https.//github.com/PaulStofferegen/Time
setSyncProvider(getTeensy3Time);
//Define a callback that will assign the correct datetime for any file system operations
// (i.e. saving a new audio recording onto the SD card)
FsDateTime::setCallback(dateTime);
mode = Mode::Ready;
}
void loop() {
//First, read the buttons
buttonRecord.update();
buttonPlay.update();
switch (mode) {
case Mode::Ready:
//Rising edge occurs when the handset is lifted
if (buttonRecord.risingEdge()) {
Serial.println("Handset lifted");
mode = Mode::Prompting;
}
else if (buttonPlay.fallingEdge()) {
playAllRecordings();
}
break;
case Mode::Prompting:
//Wait a second for users to put the handset to their ear
wait(2000);
Serial.println("Starting Playing");
//Play the greeting inviting them to record their message
playWav1.play("greeting.wav");
delay(4); //allow time for audio interrupt
//Wait until the message has finished playing
while (playWav1.isPlaying()) {
//Check whether the handset is replaced
buttonRecord.update();
//Handset is replaced
if (buttonRecord.fallingEdge()) {
playWav1.stop();
mode = Mode::Ready;
return;
}
}
//Debug message
Serial.println("Starting Recording");
//Play the tone sound effect
waveform1.frequency(440);
waveform1.amplitude(0.5);
wait(250);
waveform1.amplitude(0);
delay(1000);
//Start the recording function
startRecording();
break;
case Mode::Recording:
//Handset is replaced
if (buttonRecord.fallingEdge()){
//Debug log
Serial.println("Stopped Recording");
//Stop recording
stopRecording();
//Play audio tone to confirm recording has ended
waveform1.frequency(523.25);
waveform1.amplitude(0.9);
wait(50);
waveform1.amplitude(0);
wait(50);
waveform1.amplitude(0.9);
wait(50);
waveform1.amplitude(0);
}
else {
continueRecording();
}
break;
case Mode::Playing:
break;
}
}
void startRecording() {
//Find the first available file number
Serial.println("Actually started recording");
for (uint8_t i = 0; i < 9999; i++) {
//Format the counter as a five-digit number with leading zeros, followed by file extension
snprintf(filename, 11, " %05d.RAW", i);
//Create if does not exist, do not open existing, write, sync after write
Serial.println(filename);
if (!SD.exists(filename)) {
break;
}
}
frec = SD.open(filename, FILE_WRITE);
if (frec) {
Serial.print("Recording to ");
Serial.println(filename);
queue1.begin();
mode = Mode::Recording;
}
else {
Serial.println("Couldn't open file to record!");
}
}
void continueRecording() {
//Check if there is data in the queue
if (queue1.available() >= 2) {
byte buffer[512];
//Fetch 2 blocks from the audio library and copy
//into a 512 byte buffer. The Arduino SD library
//is the most efficient when full 512 byt sector size
//writes are used
memcpy(buffer, queue1.readBuffer(), 256);
queue1.freeBuffer();
memcpy(buffer + 256, queue1.readBuffer(), 256);
queue1.freeBuffer();
//Write all 512 bytes to the SD card
frec.write(buffer, 512);
}
}
void stopRecording() {
//Stop adding any new data to the queue
Serial.println("Actually stopped recording");
queue1.end();
//Flush all existing remaining data from the queue
while (queue1.available() > 0) {
//Save to open file
frec.write((byte*)queue1.readBuffer(), 256);
queue1.freeBuffer();
}
//Close the file
frec.close();
mode = Mode::Ready;
}
void playAllRecordings() {
//Recording files are saved in the root directory
File dir = SD.open("/");
while (true) {
File entry = dir.openNextFile();
if (!entry) {
//no more files
entry.close();
break;
}
int8_t len = strlen(entry.name());
if (strstr(strlwr(entry.name() + (len - 4)), ".raw")) {
Serial.print("Now playing ");
Serial.println(entry.name());
//Play a short beep before each message
waveform1.amplitude(0.5);
wait(250);
waveform1.amplitude(0);
//Play the file
playRaw1.play(entry.name());
mode = Mode::Playing;
}
entry.close();
while (playRaw1.isPlaying()) {
buttonPlay.update();
buttonRecord.update();
//Button us pressed again
if (buttonPlay.risingEdge() || buttonRecord.fallingEdge()) {
playRaw1.stop();
mode = Mode::Ready;
return;
}
}
}
//All files have been played
mode = Mode::Ready;
}
//Retrieve the current time from Teensy built-in RTC
time_t getTeensy3Time() {
return Teensy3Clock.get();
}
//Callback to assign timestamps for file system operations
void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {
//Return date using FS_DATE macro to format fields.
*date = FS_DATE(year(), month(), day());
//Return time using FS_TIME macro to format fields.
*time = FS_TIME(hour(), minute(), second());
//Return low time bits in units of 10ms.
*ms10 = second() & 1 ? 100 : 0;
}
// Non-blocking delay, which pauses execution of main program logic,
// but while still listening for input
void wait(unsigned int milliseconds) {
elapsedMillis msec = 0;
while (msec <= milliseconds) {
buttonRecord.update();
buttonPlay.update();
if (buttonRecord.fallingEdge()) Serial.println("Button (pin 0) Press");
if (buttonPlay.fallingEdge()) Serial.println("Button (pin 1) Press");
if (buttonRecord.risingEdge()) Serial.println("Button (pin 0) Release");
if (buttonPlay.risingEdge()) Serial.println("Button (pin 1) Release");
}
}
Any ideas why this isn't working? I believe I am using the correct library for the SD card (Using library SD at version 2.0.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SD) as show in the verbose info below. Also, if you see any glaring issues in the code please let me know. Any help is appreciated!
Multiple libraries were found for "SD.h"
Used: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SD
Not used: C:\Program Files (x86)\Arduino\libraries\SD
Using library Bounce in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Bounce (legacy)
Using library Audio at version 1.3 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio
Using library SPI at version 1.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SPI
Using library SD at version 2.0.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SD
Using library SdFat at version 2.1.2 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SdFat
Using library SerialFlash at version 0.5 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SerialFlash
Using library Wire at version 1.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Wire
Using library Time at version 1.6.1 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Time
C:\Program Files (x86)\Arduino\hardware\teensy/../tools/teensy_post_compile -file=AudioGuestbook.ino -path=C:\Users\jakew\AppData\Local\Temp\arduino_build_166691 -tools=C:\Program Files (x86)\Arduino\hardware\teensy/../tools -board=TEENSY40 -reboot -port=usb:0/140000/0/4 -portlabel=hid#vid_16c0&pid_0478 Bootloader -portprotocol=Teensy