GNSS and Record Audio at the same time?
-
I am using the Arduino Spresense libraries. When I try to do GNSS and record Audio at the same time, it fails. But with the same sketch code, If I disable either the GNSS or Audio code, the remaining GNSS or Audio works fine. Can someone post an arduino example of this working? I get errors like below, once a second, then after 10 times they stop, but no audio is saved.
16:51:05.971 -> main_setup() initializing logFile logfile.log
16:51:05.971 -> file_setup() start
16:51:06.006 -> audio_setup() Initializing the Audio Library...
16:51:07.382 -> Setting up the Recorder...
16:51:07.382 -> Writing the WAV File Header...
16:51:07.382 -> Start Recording
16:51:07.418 -> audio_setup() done
16:51:07.418 ->
16:51:09.029 -> gnss_setup() Initializing GNSS...
16:51:09.096 -> Attention: module[4][0] attention id[1]/code[6] (objects/media_recorder/audio_recorder_sink.cpp L84)
16:51:09.132 -> Audio_Attention_CB() info/warn code=0x1
16:51:12.025 -> SpGnss : begin in
16:51:12.919 -> SpGnss : begin out
16:51:12.919 -> SpGnss : start in
16:51:12.919 -> mode = COLD_START
16:51:13.328 -> SpGnss : start out
16:51:13.328 -> Gnss setup OK
16:51:13.328 -> gnss_setup() done
16:51:13.328 ->
16:51:13.328 ->
16:51:13.328 -> Setup Complete
16:51:13.328 ->16:51:14.326 -> up_assert: Assertion failed at file:components/capture/capture_component.cpp line: 801 task: capture0
16:51:14.359 -> up_registerdump: R0: 00000001 0d05392c 000000e0 0d055e2c 0d05392c 0d06abb8 0d055fcc 0d061258
16:51:14.359 -> up_registerdump: R8: 0d03c4fc 00000321 0d06a270 00000000 00000000 0d06abb8 0d01da95 0d01e08c
16:51:14.359 -> up_registerdump: xPSR: 61000000 BASEPRI: 000000e0 CONTROL: 00000004
16:51:14.359 -> up_registerdump: EXC_RETURN: ffffffe9
16:51:14.359 -> up_dumpstate: sp: 0d06abb8
16:51:14.359 -> up_dumpstate: IRQ stack:
16:51:14.392 -> up_dumpstate: base: 0d054200
16:51:14.392 -> up_dumpstate: size: 00000800
16:51:14.392 -> up_dumpstate: used: 000000f0
16:51:14.392 -> up_dumpstate: User stack:
16:51:14.392 -> up_dumpstate: base: 0d06ac18
16:51:14.392 -> up_dumpstate: size: 000007fc
16:51:14.392 -> up_dumpstate: used: 00000248
16:51:14.392 -> up_stackdump: 0d06aba0: 00000000 0d06ac18 0d06abb8 0d055fcc 0d06a41c 0d01dbd9 000000e0 00000004
16:51:14.392 -> up_stackdump: 0d06abc0: 00000000 00000000 0d06abb8 0d01da95 0d01e08c 00000000 00000000 0d061258
16:51:14.426 -> up_stackdump: 0d06abe0: 00000000 0d007173 000fd400 000fe880 0d06a270 0d0071dd 0d0071bb 0d016c63
16:51:14.426 -> up_stackdump: 0d06ac00: 00000000 00000000 00000000 00000000 00000000 00000000 deadbeef fb528c48
16:51:14.426 -> up_taskdump: Idle Task: PID=0 Stack Used=0 of 0
16:51:14.426 -> up_taskdump: hpwork: PID=1 Stack Used=576 of 2028
16:51:14.426 -> up_taskdump: lpwork: PID=2 Stack Used=352 of 2028
16:51:14.426 -> up_taskdump: lpwork: PID=3 Stack Used=352 of 2028
16:51:14.426 -> up_taskdump: lpwork: PID=4 Stack Used=352 of 2028
16:51:14.461 -> up_taskdump: cxd56_pm_task: PID=6 Stack Used=352 of 996
16:51:14.461 -> up_taskdump: <pthread>: PID=7 Stack Used=736 of 1020
16:51:14.461 -> up_taskdump: init: PID=8 Stack Used=1112 of 8172
16:51:14.461 -> up_taskdump: audio_manager: PID=9 Stack Used=704 of 2044
16:51:14.461 -> up_taskdump: media_player0: PID=10 Stack Used=344 of 3068
16:51:14.461 -> up_taskdump: media_player1: PID=11 Stack Used=344 of 3068
16:51:14.461 -> up_taskdump: out_mixer: PID=12 Stack Used=344 of 3068
16:51:14.497 -> up_taskdump: renderer0: PID=13 Stack Used=344 of 2044
16:51:14.497 -> up_taskdump: renderer1: PID=14 Stack Used=344 of 2044
16:51:14.497 -> up_taskdump: front_end: PID=15 Stack Used=568 of 2044
16:51:14.497 -> up_taskdump: media_recorder: PID=16 Stack Used=792 of 2044
16:51:14.497 -> up_taskdump: capture0: PID=17 Stack Used=584 of 2044
16:51:14.497 -> up_taskdump: alarm_daemon: PID=18 Stack Used=328 of 2044 -
Hi @m-Lewis,
Below I put the code in which Spresense records Audio and reads positions from GNSS:
#include <SDHCI.h> #include <Audio.h> #define RECORD_FILE_NAME "Sound.mp3" SDClass theSD; AudioClass *theAudio; File myFile; bool ErrEnd = false; /* include the GNSS library */ #include <GNSS.h> #define STRING_BUFFER_SIZE 128 /**< %Buffer size */ #define RESTART_CYCLE (60 * 5) /**< positioning test term */ static SpGnss Gnss; /**< SpGnss object */ /** * @enum ParamSat * @brief Satellite system */ enum ParamSat { eSatGps, /**< GPS World wide coverage */ eSatGlonass, /**< GLONASS World wide coverage */ eSatGpsSbas, /**< GPS+SBAS North America */ eSatGpsGlonass, /**< GPS+Glonass World wide coverage */ eSatGpsBeidou, /**< GPS+BeiDou World wide coverage */ eSatGpsGalileo, /**< GPS+Galileo World wide coverage */ eSatGpsQz1c, /**< GPS+QZSS_L1CA East Asia & Oceania */ eSatGpsGlonassQz1c, /**< GPS+Glonass+QZSS_L1CA East Asia & Oceania */ eSatGpsBeidouQz1c, /**< GPS+BeiDou+QZSS_L1CA East Asia & Oceania */ eSatGpsGalileoQz1c, /**< GPS+Galileo+QZSS_L1CA East Asia & Oceania */ eSatGpsQz1cQz1S, /**< GPS+QZSS_L1CA+QZSS_L1S Japan */ }; /* Set this parameter depending on your current region. */ static enum ParamSat satType = eSatGps; /** * @brief Turn on / off the LED0 for CPU active notification. */ static void Led_isActive(void) { static int state = 1; if (state == 1) { ledOn(PIN_LED0); state = 0; } else { ledOff(PIN_LED0); state = 1; } } /** * @brief Turn on / off the LED1 for positioning state notification. * * @param [in] state Positioning state */ static void Led_isPosfix(bool state) { if (state) { ledOn(PIN_LED1); } else { ledOff(PIN_LED1); } } /** * @brief Turn on / off the LED3 for error notification. * * @param [in] state Error state */ static void Led_isError(bool state) { if (state) { ledOn(PIN_LED3); } else { ledOff(PIN_LED3); } } /** * @brief %Print position information. */ static void print_pos(SpNavData *pNavData) { char StringBuffer[STRING_BUFFER_SIZE]; /* print time */ snprintf(StringBuffer, STRING_BUFFER_SIZE, "%04d/%02d/%02d ", pNavData->time.year, pNavData->time.month, pNavData->time.day); Serial.print(StringBuffer); snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d:%02d:%02d.%06d, ", pNavData->time.hour, pNavData->time.minute, pNavData->time.sec, pNavData->time.usec); Serial.print(StringBuffer); /* print satellites count */ snprintf(StringBuffer, STRING_BUFFER_SIZE, "numSat:%2d, ", pNavData->numSatellites); Serial.print(StringBuffer); /* print position data */ if (pNavData->posFixMode == FixInvalid) { Serial.print("No-Fix, "); } else { Serial.print("Fix, "); } if (pNavData->posDataExist == 0) { Serial.print("No Position"); } else { Serial.print("Lat="); Serial.print(pNavData->latitude, 6); Serial.print(", Lon="); Serial.print(pNavData->longitude, 6); } Serial.println(""); } /** * @brief %Print satellite condition. */ static void print_condition(SpNavData *pNavData) { char StringBuffer[STRING_BUFFER_SIZE]; unsigned long cnt; /* Print satellite count. */ snprintf(StringBuffer, STRING_BUFFER_SIZE, "numSatellites:%2d\n", pNavData->numSatellites); Serial.print(StringBuffer); for (cnt = 0; cnt < pNavData->numSatellites; cnt++) { const char *pType = "---"; SpSatelliteType sattype = pNavData->getSatelliteType(cnt); /* Get satellite type. */ /* Keep it to three letters. */ switch (sattype) { case GPS: pType = "GPS"; break; case GLONASS: pType = "GLN"; break; case QZ_L1CA: pType = "QCA"; break; case SBAS: pType = "SBA"; break; case QZ_L1S: pType = "Q1S"; break; case BEIDOU: pType = "BDS"; break; case GALILEO: pType = "GAL"; break; default: pType = "UKN"; break; } /* Get print conditions. */ unsigned long Id = pNavData->getSatelliteId(cnt); unsigned long Elv = pNavData->getSatelliteElevation(cnt); unsigned long Azm = pNavData->getSatelliteAzimuth(cnt); float sigLevel = pNavData->getSatelliteSignalLevel(cnt); /* Print satellite condition. */ snprintf(StringBuffer, STRING_BUFFER_SIZE, "[%2d] Type:%s, Id:%2d, Elv:%2d, Azm:%3d, CN0:", cnt, pType, Id, Elv, Azm ); Serial.print(StringBuffer); Serial.println(sigLevel, 6); } } /** * @brief Audio attention callback * * When audio internal error occurc, this function will be called back. */ static void audio_attention_cb(const ErrorAttentionParam *atprm) { puts("Attention!"); if (atprm->error_code >= AS_ATTENTION_CODE_WARNING) { ErrEnd = true; } } /** * @brief Setup recording of mp3 stream to file * * Select input device as microphone <br> * Initialize filetype to stereo mp3 with 48 Kb/s sampling rate <br> * Open RECORD_FILE_NAME file in write mode */ /* Recording time[second] */ static const int32_t recoding_time = 10; /* Recording bit rate * Set in bps. * Note: 96kbps fixed */ static const int32_t recoding_bitrate = 96000; /* Bytes per second */ static const int32_t recoding_byte_per_second = (recoding_bitrate / 8); /* Total recording size */ static const int32_t recoding_size = recoding_byte_per_second * recoding_time; /** * @brief Activate GNSS device and start positioning. */ void gnss_setup() { /* put your setup code here, to run once: */ int error_flag = 0; /* Set serial baudrate. */ Serial.begin(115200); /* Wait HW initialization done. */ sleep(3); /* Turn on all LED:Setup start. */ ledOn(PIN_LED0); ledOn(PIN_LED1); ledOn(PIN_LED2); ledOn(PIN_LED3); /* Set Debug mode to Info */ Gnss.setDebugMode(PrintInfo); int result; /* Activate GNSS device */ result = Gnss.begin(); if (result != 0) { Serial.println("Gnss begin error!!"); error_flag = 1; } else { /* Setup GNSS * It is possible to setup up to two GNSS satellites systems. * Depending on your location you can improve your accuracy by selecting different GNSS system than the GPS system. * See: https://developer.sony.com/develop/spresense/developer-tools/get-started-using-nuttx/nuttx-developer-guide#_gnss * for detailed information. */ switch (satType) { case eSatGps: Gnss.select(GPS); break; case eSatGpsSbas: Gnss.select(GPS); Gnss.select(SBAS); break; case eSatGlonass: Gnss.select(GLONASS); break; case eSatGpsGlonass: Gnss.select(GPS); Gnss.select(GLONASS); break; case eSatGpsBeidou: Gnss.select(GPS); Gnss.select(BEIDOU); break; case eSatGpsGalileo: Gnss.select(GPS); Gnss.select(GALILEO); break; case eSatGpsQz1c: Gnss.select(GPS); Gnss.select(QZ_L1CA); break; case eSatGpsQz1cQz1S: Gnss.select(GPS); Gnss.select(QZ_L1CA); Gnss.select(QZ_L1S); break; case eSatGpsBeidouQz1c: Gnss.select(GPS); Gnss.select(BEIDOU); Gnss.select(QZ_L1CA); break; case eSatGpsGalileoQz1c: Gnss.select(GPS); Gnss.select(GALILEO); Gnss.select(QZ_L1CA); break; case eSatGpsGlonassQz1c: default: Gnss.select(GPS); Gnss.select(GLONASS); Gnss.select(QZ_L1CA); break; } /* Start positioning */ result = Gnss.start(COLD_START); if (result != 0) { Serial.println("Gnss start error!!"); error_flag = 1; } else { Serial.println("Gnss setup OK"); } } /* Start 1PSS output to PIN_D02 */ //Gnss.start1PPS(); /* Turn off all LED:Setup done. */ ledOff(PIN_LED0); ledOff(PIN_LED1); ledOff(PIN_LED2); ledOff(PIN_LED3); /* Set error LED. */ if (error_flag == 1) { Led_isError(true); exit(0); } } void recorder_setup() { theAudio = AudioClass::getInstance(); theAudio->begin(audio_attention_cb); puts("initialization Audio Library"); /* Select input device as microphone */ theAudio->setRecorderMode(AS_SETRECDR_STS_INPUTDEVICE_MIC); /* * Initialize filetype to stereo mp3 with 48 Kb/s sampling rate * Search for MP3 codec in "/mnt/sd0/BIN" directory */ theAudio->initRecorder(AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_48000, AS_CHANNEL_STEREO); puts("Init Recorder!"); /* Open file for data write on SD card */ theSD.begin(); if (theSD.exists(RECORD_FILE_NAME)) { printf("Remove existing file [%s].\n", RECORD_FILE_NAME); theSD.remove(RECORD_FILE_NAME); } myFile = theSD.open(RECORD_FILE_NAME, FILE_WRITE); /* Verify file open */ if (!myFile) { printf("File open error\n"); exit(1); } printf("Open! [%s]\n", RECORD_FILE_NAME); theAudio->startRecorder(); puts("Recording Start!"); } void setup() { gnss_setup(); recorder_setup(); } /** * @brief Record given frame number */ void loop() { static int LastPrintMin = 0; /* Blink LED. */ Led_isActive(); /* Check update. */ if (Gnss.waitUpdate(0)) { /* Get NaviData. */ SpNavData NavData; Gnss.getNavData(&NavData); /* Set posfix LED. */ bool LedSet = (NavData.posDataExist && (NavData.posFixMode != FixInvalid)); Led_isPosfix(LedSet); /* Print satellite information every minute. */ if (NavData.time.minute != LastPrintMin) { print_condition(&NavData); LastPrintMin = NavData.time.minute; } /* Print position information. */ print_pos(&NavData); } err_t err; /* recording end condition */ if (theAudio->getRecordingSize() > recoding_size) { theAudio->stopRecorder(); sleep(1); err = theAudio->readFrames(myFile); goto exitRecording; } /* Read frames to record in file */ err = theAudio->readFrames(myFile); if (err != AUDIOLIB_ECODE_OK) { printf("File End! =%d\n",err); theAudio->stopRecorder(); goto exitRecording; } if (ErrEnd) { printf("Error End\n"); theAudio->stopRecorder(); goto exitRecording; } /* This sleep is adjusted by the time to write the audio stream file. Please adjust in according with the processing contents being processed at the same time by Application. */ // usleep(10000); return; exitRecording: theAudio->closeOutputFile(myFile); myFile.close(); theAudio->setReadyMode(); theAudio->end(); Gnss.stop(); Gnss.end(); puts("End Recording"); exit(1); }
Please let me know what was wrong with your application or share the code.
Best Regards,
Kamil Tomaszewski -
Kamil,
Thank you for responding. However, your code did not work for me. I did not get any GNSS or Audio, and all output stopped after about 10 seconds.
I am attaching my code here. As I said, I am successful with doing either Audio or GNSS, but not at the same time. You can see how this choice is selected in the very first lines of my source file. Much of the code was taken from the SPresense examples. I modified so that I can continue to write data samples to a logfile at 10 Hz while waiting for the next GNSS report at 1 Hz. You can imagine other sensor data being written to the log file at the 10 Hz rate. I use an analog mic and .wav file. To save confusion, I put all my source in a single file here, and both setup() and main() are at the very bottom. Hope its clear.
M. Lewis// GNSS and Audio at the same time example, while writing data to a logfile and output to Serial port // M. Lewis bool doAudio = false; // Record Audio bool doGnss = true; // GNSS/GPS bool doLed = true; // Blink LED bool doStream = true; // Stream sampled data lines to Serial output at Sample Rate bool doFile = true; // Stream sampled data lines to logFile at Sample Rate #include <Arduino.h> #include <arch/board/board.h> #include <SDHCI.h> #include <File.h> #include <Storage.h> #include <elapsedMillis.h> #include <GNSS.h> #include <RTC.h> // For setting realtime clock #include <Audio.h> SDClass theSD; // This is the SD card class File logFile; // File object //char* logName = "/mnt/spif/logfile.log"; char* logName = "logfile.log"; String logString; elapsedMillis sinceSample; int sampleMillis = 1000/10; // 10 Hz ////////////// LED Control ////////////// unsigned long blinkStartMS; #define BLINK_MS 500 // number of millisecs for on or off int blinkMillis = 1000/2; // 2 Hz elapsedMillis sinceBlink; void led_setup() { Serial.println("led_setup()"); pinMode(LED0, OUTPUT); // Init the on-board SPresense LEDs pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); blinkStartMS = 0 ; } void led_loop() { static bool state = true; if (sinceBlink < blinkMillis) { return; } sinceBlink = sinceBlink - blinkMillis; state = ! state; digitalWrite(PIN_LED0, state==false ? LOW : HIGH); } void led_setAll(bool state) { digitalWrite(PIN_LED0, state==false ? LOW : HIGH); digitalWrite(PIN_LED1, state==false ? LOW : HIGH); digitalWrite(PIN_LED2, state==false ? LOW : HIGH); digitalWrite(PIN_LED3, state==false ? LOW : HIGH); } static void Led_isPosfix(bool state) { digitalWrite(PIN_LED1, state==false ? LOW : HIGH); } static void Led_isError(bool state) { digitalWrite(PIN_LED3, state==false ? LOW : HIGH); } ////////////// Log File Control ////////////// void file_setup() { Serial.println("file_setup() start"); //logFile = Storage.open(logName, FILE_WRITE); // Open the file. Note: only one file can be open at a time if (! theSD.begin()) { Serial.print("uSD card is not present!!"); while(1){;} } logString = String("MSec"); if (doGnss) { logString += ","; logString += gnss_get_columns(); } logString += "\r\n"; Serial.print(logString.c_str()); logFile = theSD.open(logName, FILE_WRITE); // Open the file. Note: only one file can be open at a time if (!logFile) { Serial.print("Could not open logFile"); return; } if (logFile.size() < 1) { // Empty or non-existant file. Add header line logFile.write(logString.c_str(), strlen(logString.c_str())); logFile.close(); /* Close the file */ //logFile.flush(); } } ////////////// GNSS File Control ////////////// #define STRING_BUFFER_SIZE 128 /**< %Buffer size */ #define RESTART_CYCLE (60 * 5) /**< positioning test term */ static SpGnss Gnss; /**< SpGnss object */ SpNavData NavData; uint32_t recordCount; String gnssLatestString; void gnss_update_latestString(); const uint16_t FAULT_GPS_TIME = 0x2; // NO GPS Time and Date const uint16_t FAULT_GPS_FIX = 0x4; // NO GPS Location uint16_t gps_fault = 0; /** * @enum ParamSat * @brief Satellite system */ enum ParamSat { eSatGps, /**< GPS World wide coverage */ eSatGlonass, /**< GLONASS World wide coverage */ eSatGpsSbas, /**< GPS+SBAS North America */ eSatGpsGlonass, /**< GPS+Glonass World wide coverage */ eSatGpsBeidou, /**< GPS+BeiDou World wide coverage */ eSatGpsGalileo, /**< GPS+Galileo World wide coverage */ eSatGpsQz1c, /**< GPS+QZSS_L1CA East Asia & Oceania */ eSatGpsGlonassQz1c, /**< GPS+Glonass+QZSS_L1CA East Asia & Oceania */ eSatGpsBeidouQz1c, /**< GPS+BeiDou+QZSS_L1CA East Asia & Oceania */ eSatGpsGalileoQz1c, /**< GPS+Galileo+QZSS_L1CA East Asia & Oceania */ eSatGpsQz1cQz1S, /**< GPS+QZSS_L1CA+QZSS_L1S Japan */ }; static enum ParamSat satType = eSatGps; /* Set this parameter depending on your current region. */ void gnss_setSatType() { /* Setup GNSS * It is possible to setup up to two GNSS satellites systems. * Depending on your location you can improve your accuracy by selecting different GNSS system than the GPS system. * See: https://developer.sony.com/develop/spresense/developer-tools/get-started-using-nuttx/nuttx-developer-guide#_gnss * for detailed information. */ switch (satType) { case eSatGps: Gnss.select(GPS); break; case eSatGpsSbas: Gnss.select(GPS); Gnss.select(SBAS); break; case eSatGlonass: Gnss.select(GLONASS); break; case eSatGpsGlonass: Gnss.select(GPS); Gnss.select(GLONASS); break; case eSatGpsBeidou: Gnss.select(GPS); Gnss.select(BEIDOU); break; case eSatGpsGalileo: Gnss.select(GPS); Gnss.select(GALILEO); break; case eSatGpsQz1c: Gnss.select(GPS); Gnss.select(QZ_L1CA); break; case eSatGpsQz1cQz1S: Gnss.select(GPS); Gnss.select(QZ_L1CA); Gnss.select(QZ_L1S); break; case eSatGpsBeidouQz1c: Gnss.select(GPS); Gnss.select(BEIDOU); Gnss.select(QZ_L1CA); break; case eSatGpsGalileoQz1c: Gnss.select(GPS); Gnss.select(GALILEO); Gnss.select(QZ_L1CA); break; case eSatGpsGlonassQz1c: default: Gnss.select(GPS); Gnss.select(GLONASS); Gnss.select(QZ_L1CA); break; } } /** * @brief Activate GNSS device and start positioning. */ void gnss_setup() { int error_flag = 0; recordCount = 0; puts("gnss_setup() Initializing GNSS..."); RTC.begin(); // Initialize RTC at first gps_fault = FAULT_GPS_FIX | FAULT_GPS_TIME; // assume no GPS time or fix, show a fault sleep(3); // Wait HW initialization done led_setAll(true); // Turn on all LEDs Gnss.setDebugMode(PrintInfo); if (Gnss.begin() != 0) { Serial.println("Gnss begin error!!"); error_flag = 1; } else { gnss_setSatType(); // Select International Sat Systems to use if (Gnss.start(COLD_START) != 0) // Start positioning { Serial.println("Gnss COLD_START error!!"); error_flag = 1; } else { Serial.println("Gnss setup OK"); } } //Gnss.start1PPS(); /* Start 1PSS output to PIN_D02 */ led_setAll(false); // Turn off all LEDs if (error_flag == 1) { Led_isError(true); // Set error LED3 exit(0); } puts("gnss_setup() done\n"); } /** * @brief %Print satellite condition. */ static void print_condition(SpNavData *pNavData) { char StringBuffer[STRING_BUFFER_SIZE]; unsigned long cnt; snprintf(StringBuffer, STRING_BUFFER_SIZE, "numSatellites:%2d\n", pNavData->numSatellites); // Print satellite count Serial.print(StringBuffer); for (cnt = 0; cnt < pNavData->numSatellites; cnt++) { const char *pType = "---"; SpSatelliteType sattype = pNavData->getSatelliteType(cnt); switch (sattype) // Get satellite 3 letter string { case GPS: pType = "GPS"; break; case GLONASS: pType = "GLN"; break; case QZ_L1CA: pType = "QCA"; break; case SBAS: pType = "SBA"; break; case QZ_L1S: pType = "Q1S"; break; case BEIDOU: pType = "BDS"; break; case GALILEO: pType = "GAL"; break; default: pType = "UKN"; break; } unsigned long Id = pNavData->getSatelliteId(cnt); unsigned long Elv = pNavData->getSatelliteElevation(cnt); unsigned long Azm = pNavData->getSatelliteAzimuth(cnt); float sigLevel = pNavData->getSatelliteSignalLevel(cnt); snprintf(StringBuffer, STRING_BUFFER_SIZE, "[%2d] Type:%s, Id:%2d, Elv:%2d, Azm:%3d, CN0:", cnt, pType, Id, Elv, Azm ); Serial.print(StringBuffer); Serial.println(sigLevel, 6); } } /** * @brief %Print position information. */ static void print_pos(SpNavData *pNavData) { static int LastPrintMin = 0; char StringBuffer[STRING_BUFFER_SIZE]; /* print time */ snprintf(StringBuffer, STRING_BUFFER_SIZE, "%04d/%02d/%02d ", pNavData->time.year, pNavData->time.month, pNavData->time.day); Serial.print(StringBuffer); snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d:%02d:%02d.%06d, ", pNavData->time.hour, pNavData->time.minute, pNavData->time.sec, pNavData->time.usec); Serial.print(StringBuffer); /* print satellites count */ snprintf(StringBuffer, STRING_BUFFER_SIZE, "numSat:%2d, ", pNavData->numSatellites); Serial.print(StringBuffer); /* print position data */ unsigned char fixMode = pNavData->posFixMode; switch (fixMode) { case 2: Serial.print("2D"); break; case 3: Serial.print("3D"); break; case 0: // FixInvalid: //Serial.print("No-Fix, "); break; // FixInvalid: default: Serial.print("No"); break; } Serial.print("-Fix("); Serial.print(fixMode); Serial.print("), "); if (pNavData->posDataExist == 0) { Serial.print("No Position"); } else { Serial.print("Lat="); Serial.print(pNavData->latitude, 6); Serial.print(", Lon="); Serial.print(pNavData->longitude, 6); } Serial.println(""); if (NavData.time.minute != LastPrintMin) // Print satellite information every minute { print_condition(&NavData); LastPrintMin = NavData.time.minute; } } void gnss_restart() { int error_flag = 0; ledOff(PIN_LED0); // Turn off LED0 Led_isPosfix(false); // Turn off posFix LED1 if (Gnss.stop() != 0) { Serial.println("Gnss stop error!!"); error_flag = 1; } else if (Gnss.end() != 0) { Serial.println("Gnss end error!!"); error_flag = 1; } else { Serial.println("Gnss stop OK."); } if (Gnss.begin() != 0) { Serial.println("Gnss begin error!!"); error_flag = 1; } else if (Gnss.start(HOT_START) != 0) { Serial.println("Gnss hot start error!!"); error_flag = 1; } else { Serial.println("Gnss restart OK."); } if (error_flag == 1) { Led_isError(true); // Set error LED3 exit(0); } } void gnss_update_latestString() { // Following code block was in loop() bool goodFix; int upd=Gnss.waitUpdate(0); //-1); if (upd) // Check update { if (upd) { recordCount++; } // New GNSS data has come in Gnss.getNavData(&NavData); // Get NaviData goodFix = NavData.posDataExist && (NavData.posFixMode != FixInvalid); Led_isPosfix( goodFix ); // Set posFix LED1 if there is a Fix print_pos(&NavData); // Print position information } if (!upd) { return; } //Serial.printf("secondsSinceTime()=%.3f\n", GPS.secondsSinceTime()); gnssLatestString = "GPS,"; if (NavData.time.hour < 10) { gnssLatestString += '0'; } gnssLatestString += NavData.time.hour; gnssLatestString += ':'; if (NavData.time.minute < 10) { gnssLatestString += '0'; } gnssLatestString += NavData.time.minute; gnssLatestString += ':'; if (NavData.time.sec < 10) { gnssLatestString += '0'; } gnssLatestString += NavData.time.sec; // handle millisecs - GPS.milliseconds can fail prior to a fix, then returns a random string uint16_t millisecs = NavData.time.usec / 1000; //Serial.printf("Millisec=%u\n", millisecs); if (millisecs > 1000) {millisecs = 0;} gnssLatestString += '.'; if (millisecs < 10) { gnssLatestString += "00"; } else if (millisecs > 9 && millisecs < 100) { gnssLatestString += "0"; } gnssLatestString += millisecs; gnssLatestString += ","; gnssLatestString += NavData.time.year; gnssLatestString += '/'; gnssLatestString += NavData.time.month; gnssLatestString += '/'; gnssLatestString += NavData.time.day; char fixBuf[300]; char lat, lon; //lat = (!NavData.latitude) ? 'n' : NavData.latitude; // needed when never had fix since GPS.lat initialized to 0 //lon = (!NavData.longitude) ? 'w' : NavData.longitude; lat = 'n'; lon = 'w'; sprintf(fixBuf, ",%.6f,%c,%.6f,%c,%.1f,%.1f,%d,%d,%lu", NavData.latitude, lat, NavData.longitude, lon, NavData.altitude, NavData.velocity, (int)NavData.numSatellites, NavData.posFixMode, recordCount); gnssLatestString += fixBuf; } char* gnss_get_columns() { // return the column headers static char buf[200] = "GPS,Time,Date,Lat_deg,N/S,Lon_deg,E/W,Alt_m,Knots,Track_deg,Sats,Fix,Rcvd"; char* s = buf; return s; } char* gnss_get_latest() // return pointer to CSV IMU data string { gnss_update_latestString(); gps_fault = 0; int status = (NavData.posDataExist && (NavData.posFixMode != FixInvalid)); if (! NavData.posDataExist) { gps_fault |= FAULT_GPS_FIX; } else { //gnss_upd_rtc(); // SPresense version of RTC } return (char*)gnssLatestString.c_str(); } bool gnss_waitUpdate(int milliSecs) { // milliSecs to wait, or -1 to not wait. Assumes setup() was already called bool upd = false; upd=Gnss.waitUpdate(milliSecs); // Check update return upd; } void gnss_loop() {} // Nothing here, GNSS is run at the much slower Sample rate. See gnss_get_latest() above ////////////// AUDIO RECORDING CONTROL ////////////// extern SDClass theSD; // Declared in sp_main.cpp AudioClass *theAudio; File wavFile; int file_count = 0; bool ErrEnd = false; static const uint32_t recording_time = 10; // Recording Time (Seconds) per wav file static const uint32_t recording_sampling_rate = 48000; // Sample Rate (16000 or 48000) static const uint8_t recording_channel_number = 1; // Number of Input Mic Channels (1, 2, or 4) static const uint8_t recording_bit_length = 16; // Audio Sample Bit Length (16 or 24) static const int32_t recording_byte_per_second = recording_sampling_rate * recording_channel_number * recording_bit_length / 8; // Bytes per Second static const int32_t recording_size = recording_byte_per_second * recording_time; // Total WAV File Size static void audio_attention_cb(const ErrorAttentionParam *atprm) // Called when audio internal error occurs { switch (atprm->error_code) { case AS_ATTENTION_CODE_INFORMATION: case AS_ATTENTION_CODE_WARNING: ErrEnd = false; printf("Audio_Attention_CB() info/warn code=0x%x\n", atprm->error_code); break; case AS_ATTENTION_CODE_ERROR: case AS_ATTENTION_CODE_FATAL: default: ErrEnd = true; printf("Audio_Attention_CB() error/fatal code=0x%x\n", atprm->error_code); } } void audio_setup() { puts("audio_setup() Initializing the Audio Library..."); theAudio = AudioClass::getInstance(); theAudio->begin(audio_attention_cb); // Select microphone input device theAudio->setRecorderMode(AS_SETRECDR_STS_INPUTDEVICE_MIC_A, 210); //210 = 21.0 dB Mic Gain theAudio->initRecorder(AS_CODECTYPE_WAV,"/mnt/spif/BIN",recording_sampling_rate,recording_bit_length,recording_channel_number); puts("Setting up the Recorder..."); // Open file for data write on SD card //wavFile = theSD.open("Sound.wav", FILE_WRITE); wavFile = theSD.open(String(file_count)+".wav", FILE_WRITE); /* Verify file open */ if (!wavFile) { printf("Error opening the WAV file..."); exit(1); } puts("Writing the WAV File Header..."); theAudio->writeWavHeader(wavFile); puts("Start Recording"); theAudio->startRecorder(); puts("audio_setup() done\n"); } void audio_loop() { err_t errStatus; // recording end condition if (theAudio->getRecordingSize() > recording_size) { theAudio->stopRecorder(); sleep(0.1); errStatus = theAudio->readFrames(wavFile); theAudio->closeOutputFile(wavFile); wavFile.close(); file_count++; goto restartRecording; } errStatus = theAudio->readFrames(wavFile); /* Read frames to record in file */ if (errStatus != AUDIOLIB_ECODE_OK) { printf("File Ended! =%d\n", errStatus); theAudio->stopRecorder(); goto restartRecording; } if (ErrEnd) { printf("Error End\n"); theAudio->stopRecorder(); goto exitSketch; } if (file_count > 10) { goto exitSketch; } return; restartRecording: wavFile = theSD.open(String(file_count)+".wav", FILE_WRITE); puts("Writing the WAV File Header...\n"); theAudio->writeWavHeader(wavFile); puts("Starting the Recorder...\n"); theAudio->startRecorder(); puts("Next Recording Started...\n"); return; exitSketch: puts("Exiting Sketch!\n"); exit(1); } ////////////// MAIN SETUP() and LOOP() ////////////// void main_setup() { // put your setup code here, to run once: Serial.begin(115200); //while (!Serial) { ; } // wait for serial port to connect. Needed for native USB port only printf("main_setup() initializing logFile %s\n", logName); if (doFile) { file_setup(); } if (doAudio) { audio_setup(); } if (doLed) { led_setup(); } if (doGnss) { gnss_setup(); } Serial.println("\nSetup Complete\n"); } char* time_getstring() // return pointer to date/time string { static String datetime; datetime = String((int)millis(), (unsigned char)DEC); return (char*)datetime.c_str(); } void sampleData() { if (sinceSample < sampleMillis) { // check if the Sample timer has passed its interval return; } sinceSample = sinceSample - sampleMillis; // Sampling time has been reached, Sample the Data char* dataStr; logString = time_getstring(); // get the time string for the beginning of each line in the file if (doGnss) { dataStr = gnss_get_latest(); logString += String(",") + dataStr; } if (doStream) { Serial.println(logString); } if (doFile) { // whether to do the data log file logFile = theSD.open(logName, FILE_WRITE); logFile.write(logString.c_str(), strlen(logString.c_str())); logFile.write("\r\n", 2); logFile.flush(); logFile.close(); } } void main_loop() { if (doAudio) { audio_loop(); } if (doGnss) { gnss_loop(); } if (doLed) { led_loop(); } // Blink SPresense On-board LED sampleData(); } void setup() { main_setup(); } void loop() { main_loop(); }
-
@m-Lewis The code that I sent you records in mp3 format for 10 seconds and then ends. That's why you don't get logs after that.
I noticed that WAV recording and GNSS usage doesn't work on SDK 2.0 together. There is a bug. I'll try to investigate it.
I have two solutions for now:
- You can use MP3 instead of WAV format. It works with SDK2.0
- If you want to use WAV format you can use SDK1.5.1
Below is the code for the second solution:
// GNSS and Audio at the same time example, while writing data to a logfile and output to Serial port // M. Lewis bool doAudio = true; // Record Audio bool doGnss = true; // GNSS/GPS bool doLed = true; // Blink LED bool doStream = true; // Stream sampled data lines to Serial output at Sample Rate bool doFile = true; // Stream sampled data lines to logFile at Sample Rate #include <Arduino.h> #include <arch/board/board.h> #include <SDHCI.h> #include <File.h> #include <Storage.h> #include <elapsedMillis.h> #include <GNSS.h> #include <RTC.h> // For setting realtime clock #include <Audio.h> SDClass theSD; // This is the SD card class File logFile; // File object //char* logName = "/mnt/spif/logfile.log"; char* logName = "logfile.log"; String logString; elapsedMillis sinceSample; int sampleMillis = 1000/10; // 10 Hz ////////////// LED Control ////////////// unsigned long blinkStartMS; #define BLINK_MS 500 // number of millisecs for on or off int blinkMillis = 1000/2; // 2 Hz elapsedMillis sinceBlink; void led_setup() { Serial.println("led_setup()"); pinMode(LED0, OUTPUT); // Init the on-board SPresense LEDs pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); blinkStartMS = 0 ; } void led_loop() { static bool state = true; if (sinceBlink < blinkMillis) { return; } sinceBlink = sinceBlink - blinkMillis; state = ! state; digitalWrite(PIN_LED0, state==false ? LOW : HIGH); } void led_setAll(bool state) { digitalWrite(PIN_LED0, state==false ? LOW : HIGH); digitalWrite(PIN_LED1, state==false ? LOW : HIGH); digitalWrite(PIN_LED2, state==false ? LOW : HIGH); digitalWrite(PIN_LED3, state==false ? LOW : HIGH); } static void Led_isPosfix(bool state) { digitalWrite(PIN_LED1, state==false ? LOW : HIGH); } static void Led_isError(bool state) { digitalWrite(PIN_LED3, state==false ? LOW : HIGH); } ////////////// Log File Control ////////////// void file_setup() { Serial.println("file_setup() start"); //logFile = Storage.open(logName, FILE_WRITE); // Open the file. Note: only one file can be open at a time if (! theSD.begin()) { Serial.print("uSD card is not present!!"); while(1){;} } logString = String("MSec"); if (doGnss) { logString += ","; logString += gnss_get_columns(); } logString += "\r\n"; Serial.print(logString.c_str()); logFile = theSD.open(logName, FILE_WRITE); // Open the file. Note: only one file can be open at a time if (!logFile) { Serial.print("Could not open logFile"); return; } if (logFile.size() < 1) { // Empty or non-existant file. Add header line logFile.write(logString.c_str(), strlen(logString.c_str())); logFile.close(); /* Close the file */ //logFile.flush(); } } ////////////// GNSS File Control ////////////// #define STRING_BUFFER_SIZE 128 /**< %Buffer size */ #define RESTART_CYCLE (60 * 5) /**< positioning test term */ static SpGnss Gnss; /**< SpGnss object */ SpNavData NavData; uint32_t recordCount; String gnssLatestString; void gnss_update_latestString(); const uint16_t FAULT_GPS_TIME = 0x2; // NO GPS Time and Date const uint16_t FAULT_GPS_FIX = 0x4; // NO GPS Location uint16_t gps_fault = 0; /** * @enum ParamSat * @brief Satellite system */ enum ParamSat { eSatGps, /**< GPS World wide coverage */ eSatGlonass, /**< GLONASS World wide coverage */ eSatGpsSbas, /**< GPS+SBAS North America */ eSatGpsGlonass, /**< GPS+Glonass World wide coverage */ eSatGpsQz1c, /**< GPS+QZSS_L1CA East Asia & Oceania */ eSatGpsGlonassQz1c, /**< GPS+Glonass+QZSS_L1CA East Asia & Oceania */ eSatGpsQz1cQz1S, /**< GPS+QZSS_L1CA+QZSS_L1S Japan */ }; static enum ParamSat satType = eSatGps; /* Set this parameter depending on your current region. */ void gnss_setSatType() { /* Setup GNSS * It is possible to setup up to two GNSS satellites systems. * Depending on your location you can improve your accuracy by selecting different GNSS system than the GPS system. * See: https://developer.sony.com/develop/spresense/developer-tools/get-started-using-nuttx/nuttx-developer-guide#_gnss * for detailed information. */ switch (satType) { case eSatGps: Gnss.select(GPS); break; case eSatGpsSbas: Gnss.select(GPS); Gnss.select(SBAS); break; case eSatGlonass: Gnss.select(GLONASS); break; case eSatGpsGlonass: Gnss.select(GPS); Gnss.select(GLONASS); break; case eSatGpsQz1c: Gnss.select(GPS); Gnss.select(QZ_L1CA); break; case eSatGpsQz1cQz1S: Gnss.select(GPS); Gnss.select(QZ_L1CA); Gnss.select(QZ_L1S); break; case eSatGpsGlonassQz1c: default: Gnss.select(GPS); Gnss.select(GLONASS); Gnss.select(QZ_L1CA); break; } } /** * @brief Activate GNSS device and start positioning. */ void gnss_setup() { int error_flag = 0; recordCount = 0; puts("gnss_setup() Initializing GNSS..."); RTC.begin(); // Initialize RTC at first gps_fault = FAULT_GPS_FIX | FAULT_GPS_TIME; // assume no GPS time or fix, show a fault sleep(3); // Wait HW initialization done led_setAll(true); // Turn on all LEDs Gnss.setDebugMode(PrintInfo); if (Gnss.begin() != 0) { Serial.println("Gnss begin error!!"); error_flag = 1; } else { gnss_setSatType(); // Select International Sat Systems to use if (Gnss.start(COLD_START) != 0) // Start positioning { Serial.println("Gnss COLD_START error!!"); error_flag = 1; } else { Serial.println("Gnss setup OK"); } } //Gnss.start1PPS(); /* Start 1PSS output to PIN_D02 */ led_setAll(false); // Turn off all LEDs if (error_flag == 1) { Led_isError(true); // Set error LED3 exit(0); } puts("gnss_setup() done\n"); } /** * @brief %Print satellite condition. */ static void print_condition(SpNavData *pNavData) { char StringBuffer[STRING_BUFFER_SIZE]; unsigned long cnt; snprintf(StringBuffer, STRING_BUFFER_SIZE, "numSatellites:%2d\n", pNavData->numSatellites); // Print satellite count Serial.print(StringBuffer); for (cnt = 0; cnt < pNavData->numSatellites; cnt++) { const char *pType = "---"; SpSatelliteType sattype = pNavData->getSatelliteType(cnt); switch (sattype) // Get satellite 3 letter string { case GPS: pType = "GPS"; break; case GLONASS: pType = "GLN"; break; case QZ_L1CA: pType = "QCA"; break; case SBAS: pType = "SBA"; break; case QZ_L1S: pType = "Q1S"; break; default: pType = "UKN"; break; } unsigned long Id = pNavData->getSatelliteId(cnt); unsigned long Elv = pNavData->getSatelliteElevation(cnt); unsigned long Azm = pNavData->getSatelliteAzimuth(cnt); float sigLevel = pNavData->getSatelliteSignalLevel(cnt); snprintf(StringBuffer, STRING_BUFFER_SIZE, "[%2d] Type:%s, Id:%2d, Elv:%2d, Azm:%3d, CN0:", cnt, pType, Id, Elv, Azm ); Serial.print(StringBuffer); Serial.println(sigLevel, 6); } } /** * @brief %Print position information. */ static void print_pos(SpNavData *pNavData) { static int LastPrintMin = 0; char StringBuffer[STRING_BUFFER_SIZE]; /* print time */ snprintf(StringBuffer, STRING_BUFFER_SIZE, "%04d/%02d/%02d ", pNavData->time.year, pNavData->time.month, pNavData->time.day); Serial.print(StringBuffer); snprintf(StringBuffer, STRING_BUFFER_SIZE, "%02d:%02d:%02d.%06d, ", pNavData->time.hour, pNavData->time.minute, pNavData->time.sec, pNavData->time.usec); Serial.print(StringBuffer); /* print satellites count */ snprintf(StringBuffer, STRING_BUFFER_SIZE, "numSat:%2d, ", pNavData->numSatellites); Serial.print(StringBuffer); /* print position data */ unsigned char fixMode = pNavData->posFixMode; switch (fixMode) { case 2: Serial.print("2D"); break; case 3: Serial.print("3D"); break; case 0: // FixInvalid: //Serial.print("No-Fix, "); break; // FixInvalid: default: Serial.print("No"); break; } Serial.print("-Fix("); Serial.print(fixMode); Serial.print("), "); if (pNavData->posDataExist == 0) { Serial.print("No Position"); } else { Serial.print("Lat="); Serial.print(pNavData->latitude, 6); Serial.print(", Lon="); Serial.print(pNavData->longitude, 6); } Serial.println(""); if (NavData.time.minute != LastPrintMin) // Print satellite information every minute { print_condition(&NavData); LastPrintMin = NavData.time.minute; } } void gnss_restart() { int error_flag = 0; ledOff(PIN_LED0); // Turn off LED0 Led_isPosfix(false); // Turn off posFix LED1 if (Gnss.stop() != 0) { Serial.println("Gnss stop error!!"); error_flag = 1; } else if (Gnss.end() != 0) { Serial.println("Gnss end error!!"); error_flag = 1; } else { Serial.println("Gnss stop OK."); } if (Gnss.begin() != 0) { Serial.println("Gnss begin error!!"); error_flag = 1; } else if (Gnss.start(HOT_START) != 0) { Serial.println("Gnss hot start error!!"); error_flag = 1; } else { Serial.println("Gnss restart OK."); } if (error_flag == 1) { Led_isError(true); // Set error LED3 exit(0); } } void gnss_update_latestString() { // Following code block was in loop() bool goodFix; int upd=Gnss.waitUpdate(0); //-1); if (upd) // Check update { if (upd) { recordCount++; } // New GNSS data has come in Gnss.getNavData(&NavData); // Get NaviData goodFix = NavData.posDataExist && (NavData.posFixMode != FixInvalid); Led_isPosfix( goodFix ); // Set posFix LED1 if there is a Fix print_pos(&NavData); // Print position information } if (!upd) { return; } //Serial.printf("secondsSinceTime()=%.3f\n", GPS.secondsSinceTime()); gnssLatestString = "GPS,"; if (NavData.time.hour < 10) { gnssLatestString += '0'; } gnssLatestString += NavData.time.hour; gnssLatestString += ':'; if (NavData.time.minute < 10) { gnssLatestString += '0'; } gnssLatestString += NavData.time.minute; gnssLatestString += ':'; if (NavData.time.sec < 10) { gnssLatestString += '0'; } gnssLatestString += NavData.time.sec; // handle millisecs - GPS.milliseconds can fail prior to a fix, then returns a random string uint16_t millisecs = NavData.time.usec / 1000; //Serial.printf("Millisec=%u\n", millisecs); if (millisecs > 1000) {millisecs = 0;} gnssLatestString += '.'; if (millisecs < 10) { gnssLatestString += "00"; } else if (millisecs > 9 && millisecs < 100) { gnssLatestString += "0"; } gnssLatestString += millisecs; gnssLatestString += ","; gnssLatestString += NavData.time.year; gnssLatestString += '/'; gnssLatestString += NavData.time.month; gnssLatestString += '/'; gnssLatestString += NavData.time.day; char fixBuf[300]; char lat, lon; //lat = (!NavData.latitude) ? 'n' : NavData.latitude; // needed when never had fix since GPS.lat initialized to 0 //lon = (!NavData.longitude) ? 'w' : NavData.longitude; lat = 'n'; lon = 'w'; sprintf(fixBuf, ",%.6f,%c,%.6f,%c,%.1f,%.1f,%d,%d,%lu", NavData.latitude, lat, NavData.longitude, lon, NavData.altitude, NavData.velocity, (int)NavData.numSatellites, NavData.posFixMode, recordCount); gnssLatestString += fixBuf; } char* gnss_get_columns() { // return the column headers static char buf[200] = "GPS,Time,Date,Lat_deg,N/S,Lon_deg,E/W,Alt_m,Knots,Track_deg,Sats,Fix,Rcvd"; char* s = buf; return s; } char* gnss_get_latest() // return pointer to CSV IMU data string { gnss_update_latestString(); gps_fault = 0; int status = (NavData.posDataExist && (NavData.posFixMode != FixInvalid)); if (! NavData.posDataExist) { gps_fault |= FAULT_GPS_FIX; } else { //gnss_upd_rtc(); // SPresense version of RTC } return (char*)gnssLatestString.c_str(); } bool gnss_waitUpdate(int milliSecs) { // milliSecs to wait, or -1 to not wait. Assumes setup() was already called bool upd = false; upd=Gnss.waitUpdate(milliSecs); // Check update return upd; } void gnss_loop() {} // Nothing here, GNSS is run at the much slower Sample rate. See gnss_get_latest() above ////////////// AUDIO RECORDING CONTROL ////////////// extern SDClass theSD; // Declared in sp_main.cpp AudioClass *theAudio; File wavFile; int file_count = 0; bool ErrEnd = false; static const uint32_t recording_time = 10; // Recording Time (Seconds) per wav file static const uint32_t recording_sampling_rate = 48000; // Sample Rate (16000 or 48000) static const uint8_t recording_channel_number = 1; // Number of Input Mic Channels (1, 2, or 4) static const uint8_t recording_bit_length = 16; // Audio Sample Bit Length (16 or 24) static const int32_t recording_byte_per_second = recording_sampling_rate * recording_channel_number * recording_bit_length / 8; // Bytes per Second static const int32_t recording_size = recording_byte_per_second * recording_time; // Total WAV File Size static void audio_attention_cb(const ErrorAttentionParam *atprm) // Called when audio internal error occurs { switch (atprm->error_code) { case AS_ATTENTION_CODE_INFORMATION: case AS_ATTENTION_CODE_WARNING: ErrEnd = false; printf("Audio_Attention_CB() info/warn code=0x%x\n", atprm->error_code); break; case AS_ATTENTION_CODE_ERROR: case AS_ATTENTION_CODE_FATAL: default: ErrEnd = true; printf("Audio_Attention_CB() error/fatal code=0x%x\n", atprm->error_code); } } void audio_setup() { puts("audio_setup() Initializing the Audio Library..."); theAudio = AudioClass::getInstance(); theAudio->begin(audio_attention_cb); // Select microphone input device theAudio->setRecorderMode(AS_SETRECDR_STS_INPUTDEVICE_MIC_A, 210); //210 = 21.0 dB Mic Gain theAudio->initRecorder(AS_CODECTYPE_WAV,"/mnt/spif/BIN",recording_sampling_rate,recording_bit_length,recording_channel_number); puts("Setting up the Recorder..."); // Open file for data write on SD card //wavFile = theSD.open("Sound.wav", FILE_WRITE); wavFile = theSD.open(String(file_count)+".wav", FILE_WRITE); /* Verify file open */ if (!wavFile) { printf("Error opening the WAV file..."); exit(1); } puts("Writing the WAV File Header..."); theAudio->writeWavHeader(wavFile); puts("audio_setup() done\n"); } void audio_loop() { err_t errStatus; // recording end condition if (theAudio->getRecordingSize() > recording_size) { theAudio->stopRecorder(); sleep(0.1); errStatus = theAudio->readFrames(wavFile); theAudio->closeOutputFile(wavFile); wavFile.close(); file_count++; goto restartRecording; } errStatus = theAudio->readFrames(wavFile); /* Read frames to record in file */ if (errStatus != AUDIOLIB_ECODE_OK) { printf("File Ended! =%d\n", errStatus); theAudio->stopRecorder(); goto restartRecording; } if (ErrEnd) { printf("Error End\n"); theAudio->stopRecorder(); goto exitSketch; } if (file_count > 10) { goto exitSketch; } return; restartRecording: wavFile = theSD.open(String(file_count)+".wav", FILE_WRITE); puts("Writing the WAV File Header...\n"); theAudio->writeWavHeader(wavFile); puts("Starting the Recorder...\n"); theAudio->startRecorder(); puts("Next Recording Started...\n"); return; exitSketch: puts("Exiting Sketch!\n"); exit(1); } ////////////// MAIN SETUP() and LOOP() ////////////// void main_setup() { // put your setup code here, to run once: Serial.begin(115200); //while (!Serial) { ; } // wait for serial port to connect. Needed for native USB port only printf("main_setup() initializing logFile %s\n", logName); if (doFile) { file_setup(); } if (doAudio) { audio_setup(); } if (doLed) { led_setup(); } if (doGnss) { gnss_setup(); } puts("Start Recording"); theAudio->startRecorder(); Serial.println("\nSetup Complete\n"); } char* time_getstring() // return pointer to date/time string { static String datetime; datetime = String((int)millis(), (unsigned char)DEC); return (char*)datetime.c_str(); } void sampleData() { if (sinceSample < sampleMillis) { // check if the Sample timer has passed its interval return; } sinceSample = sinceSample - sampleMillis; // Sampling time has been reached, Sample the Data char* dataStr; logString = time_getstring(); // get the time string for the beginning of each line in the file if (doGnss) { dataStr = gnss_get_latest(); logString += String(",") + dataStr; } if (doStream) { Serial.println(logString); } if (doFile) { // whether to do the data log file logFile = theSD.open(logName, FILE_WRITE); logFile.write(logString.c_str(), strlen(logString.c_str())); logFile.write("\r\n", 2); logFile.flush(); logFile.close(); } } void main_loop() { if (doAudio) { audio_loop(); } if (doGnss) { gnss_loop(); } if (doLed) { led_loop(); } // Blink SPresense On-board LED sampleData(); } void setup() { main_setup(); } void loop() { main_loop(); }
Let me know if it works.
Best Regards,
Kamil Tomaszewski -
Kamil,
I used the difference in your source in SDK 2.0:- Move 'theAudio->startRecorder(); to the end of the main setup(), after everything else is setup.
- Use MP3 instead of WAV.
It works. Thank you!
I still prefer to record .WAV files. Will you continue to look for the bugFix, and could you please let me know when it works.
Thank you again
M.Lewis