Hi developers, I am using Argon Particle, I am unable to record and save Wav files, Kindly assist troubleshoot this
// declare implemented functionality
void redButtonPressed();
void blackButtonPressed();
void intializeRTC();
void adjustRTC_Time();
void displayRecordingStartup();
void displayRecording();
void displayStopRecording();
void displayFailedSDCardMsg();
void configureFile_and_Microphone();
void microphoneRecord();
void recordingNextClip();
bool openNewFile();
void dateTime(uint16_t* date, uint16_t* time);
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);
void setup(){
Wire.begin();
//SdFile::dateTimeCallback(dateTime);
//set pin modes
pinMode(D19, OUTPUT);
digitalWrite(D19,LOW);
pinMode(A5, OUTPUT);
digitalWrite(A5,HIGH);
//set REDButton and BLACKButton pins as INPUT (i.e., read pins)
//both input pins are pulled LOW by default using 10k resistors
pinMode(REDButton, INPUT);
pinMode(BLACKButton, INPUT);
//attach an interrupt to each button. If the state of the button CHANGEs (i.e., is momentarily pressed)
//invoke interrupt processing function - redButtonPressed() for REDButton and
//blackButtonPressed() for BLACKButton
attachInterrupt(REDButton, redButtonPressed, CHANGE);
attachInterrupt(BLACKButton, blackButtonPressed, CHANGE);
//configure SD file structure and PDM microphone parameters
configureFile_and_Microphone();
//start OLED screen
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever :)
}
displayRecordingStartup();
intializeRTC(); //initalize real time clock
adjustRTC_Time(); //correct real-time clock setting
//delay(7200000); //wait for 2 hours before starting
}
//confugure SD file structure and PDM microphone
void configureFile_and_Microphone(){
// Save files in the top-level audio directory (created if needed)
// Files are 000000.wav, 000001.wav, ...
sequentialFile
.withDirName("audio")
.withNamePattern("%06d.wav");
int err = Microphone_PDM::instance()
.withOutputSize(Microphone_PDM::OutputSize::SIGNED_16)
.withRange(Microphone_PDM::Range::RANGE_2048)
.withSampleRate(16000)
.init();
if (err) {
Log.error("pdmDecoder.init err=%d", err);
}
err = Microphone_PDM::instance().start();
if (err) {
Log.error("pdmDecoder.start err=%d", err);
}
}
void loop() {
switch(state) {
case STATE_WAITING:
// Waiting for the user to press the RED button. The setup button handler
// will bump the state into STATE_WAITING_FOR_NOISE
break;
//case STATE_WAITING_FOR_NOISE:
//Waiting for noise before recording starts
//state = STATE_OPEN_FILE
// break;
case STATE_OPEN_FILE:
// Open and prep file
if (openNewFile()) {
Log.info("starting");
displayRecording();
recordingStart = millis(); //set recording start time
state = STATE_RUNNING;
}
else {
displayFailedSDCardMsg();
state = STATE_WAITING;
}
break;
case STATE_RUNNING:
Microphone_PDM::instance().noCopySamples([](void *pSamples, size_t numSamples) {
curFile.write((uint8_t *)pSamples, Microphone_PDM::instance().getBufferSizeInBytes());
});
if (millis() - recordingStart >= RECORDING_TIME) {
state = STATE_FINISH;
}
break;
case STATE_FINISH:
Log.info("stopping");
// Write the actual length to the wave file header
wavWriter.updateHeaderFromLength(&curFile);
// Close file
curFile.close();
totalClipsRecorded++;
state = STATE_WAITING;
//stop recording or continue to next clip
if((recordingInterrupted==1)||(totalClipsRecorded==150)){
displayStopRecording();
}
else{
delay(120000); //wait 2 minutes before recording next clip
//1 min = 60000 milliseconds
state=STATE_OPEN_FILE;
}
break;
}
}
// button handler for the SETUP button, used to toggle recording on and off
void redButtonPressed() {
switch(state) {
case STATE_WAITING:
state = STATE_OPEN_FILE;
break;
}
}
void blackButtonPressed(){
if(recordingInterrupted==0)
{
recordingInterrupted = 1;
state= STATE_FINISH;
}
}
bool openNewFile() {
bool success = false;
Log.info("generating sequential file!");
// Open the next sequential file
if (sequentialFile.openFile(&curFile, true)) {
char name[14];
curFile.getName(name, sizeof(name));
if (wavWriter.startFile(&curFile)) {
Log.info("file opened successfully %s", name);
success = true;
}
else {
Log.info("could not write header");
}
}
else {
Log.info("file open failed");
}
return success;
}
void displayRecordingStartup(){
display.clearDisplay();
display.setTextSize(1); //Normal 1:1 pixel scale
display.setTextColor(WHITE);
display.setCursor(0,20);
display.println(F("Press RED button to"));
display.println(F("start recording 20s"));
display.println(F("clips every 2 mins"));
// OLED display library initializes this with an Adafruit splash screen.
display.display(); //this function must be called at the end of display statements
delay(2000);
}
void displayFailedSDCardMsg(){
display.clearDisplay(); //clears OLED screen
display.setTextSize(1); //Normal 1:1 pixel scale
display.setTextColor(WHITE);
display.setCursor(0,20);
display.println(F("Failed to open file"));
display.println(F("please check that you"));
display.println(F("have a valid SD card"));
display.println(F("in card slot"));
display.display();
}
void displayRecording(){
DateTime now = rtc.now();
display.clearDisplay(); //clears OLED screen
display.setTextSize(1); //Normal 1:1 pixel scale
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print(F("Clips recorded: "));
display.println(totalClipsRecorded);
display.println("================");
display.println(F("Recording next clip"));
display.println(F("2 min between clips"));
display.print(F("Time: "));
display.print(now.hour(), DEC);
display.print(':');
display.print(now.minute(), DEC);
display.print(':');
display.println(now.second(), DEC);
display.println(F("Press BLACK button to"));
display.println(F("STOP recording"));
display.display();
}
void displayStopRecording(){
display.clearDisplay(); //clears OLED screen
display.setTextSize(1); //Normal 1:1 pixel scale
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print(F("Clips recorded: "));
display.println(totalClipsRecorded);
display.println("------------");
display.println(F(""));
display.println(F("Recording completed "));
display.println(F(""));
display.println(F("Press RED button to"));
display.println(F("record new clip"));
display.display();
}
//initialize real-time clock
void intializeRTC(){
//start real-time clock
if (! rtc.begin()) {
display.println("Couldn't find RTC");
display.display();
while (1) delay(10);
}
}
//adjust or correct real-time clock time
void adjustRTC_Time(){
//rtc.adjust(DateTime(2025, 1, 12, 12, 52, 00));
if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
}
// call back for file timestamps
void dateTime(uint16_t* date, uint16_t* time) {
DateTime now = rtc.now();
// return date using FAT_DATE macro to format fields
*date = FAT_DATE(now.year(), now.month(), now.day());
// return time using FAT_TIME macro to format fields
*time = FAT_TIME(now.hour(), now.minute(), now.second());
}