Group Details Private

DeveloperWorld

  • RE: GNSS - When is Time Valid? - Enhance NavData.posFixMode?

    @m-Lewis The easiest way to check that the date and time are valid is:

    /* Check update. */
    if (Gnss.waitUpdate(-1))
    {
      /* Get NaviData. */
      SpNavData NavData;
      Gnss.getNavData(&NavData);
    
      /* Check date and time. */
      if (NavData.time.year > 1980)
      {
        /* Date and time are valid */
    }
    

    Best Regards,
    Kamil Tomaszewski

    posted in Spresense
  • RE: GNSS and Record Audio at the same time?

    @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:

    1. You can use MP3 instead of WAV format. It works with SDK2.0
    2. 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

    posted in Spresense
  • RE: Auduino Compiling error : stdio.h

    @pnj Please comment line 25:

    // #include <stdio.h>
    

    in file: *\AppData\Local\Arduino15\packages\SPRESENSE\hardware\spresense<version>\cores\spresense\Print.h
    and add:

    #include <stdio.h>
    

    to file: *\AppData\Local\Arduino15\packages\SPRESENSE\hardware\spresense<version>\cores\spresense\main.cpp

    Let me know if it helped.

    posted in Spresense
  • RE: Unique ID for device detection.

    @m-Lewis

    Below is the code that shows how to get board unique ID using Arduino:

    #include <sys/boardctl.h>
    
    void setup() {
      uint8_t raw_id[CONFIG_BOARDCTL_UNIQUEID_SIZE];
      Serial.begin(115200);
    
      boardctl(BOARDIOC_UNIQUEID, (uintptr_t) raw_id);
      for (int i = 0; i < CONFIG_BOARDCTL_UNIQUEID_SIZE; i++) {
        Serial.print(raw_id[i], HEX);
      }
    }
    
    void loop() {
    }
    
    posted in Spresense
  • RE: GNSS and Record Audio at the same time?

    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

    posted in Spresense
  • RE: Control of FM Radio via API?

    To my knowledge there is no such method to set the radio directly. The only way to set it directly, that I know of, is via the presetBroadcastStation and then use setPlayContent to go to that preset as you have described.

    In the documentation I can't see any other valid "uri" than contnetId=X for radio, so it don't looks like you have something like "uri":radio:fm?frequency?XXXX unfortunatly.

    posted in Audio Control API
  • RE: Auduino Compiling error : stdio.h

    Hi @pnj

    It would help a lot if you could provide the code/sketch you are trying to build.
    Also, what sensor are you using? What libraries?

    BR
    Karl

    I tried the following code just to see if using the rewind macro would generate any error and it didn't:
    Using SDK 2.0.2

    void setup() {
      // put your setup code here, to run once:
    /* This code is just to test the build for errors. */
      FILE *fp = NULL;
      rewind(fp);
      
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    
    ####################################
    ## Used memory size:  768 [KByte] ##
    ####################################
    Sketch uses 159444 bytes (20%) of program storage space. Maximum is 786432 bytes.
    Global variables use 159444 bytes (20%) of dynamic memory, leaving 626988 bytes for local variables. Maximum is 786432 bytes.
    

    @pnj said in Auduino Compiling error : stdio.h:

    some example

    posted in Spresense
  • RE: Maximum volume = 55?

    Yes, it is the same hard upper limit (55) for al devices, but some devices like HT-ZF9 the hardware limitation can be lower (50 in this case) but you can never get above 55 for any device.

    posted in Audio Control API
  • RE: Maximum volume = 55?

    Hi @grolschie, just got a reply from the engineers and the max volume in the API is a safety feature, so you don't destroy your speakers by accident. The reason you don't have this limitation on the IR remote is that you do it incrementally and there for probably notice then it gets to loud. But since you can set the volume directly via the API a max cap is required.
    One case what was mentioned is if you are using google assistant and say "Hey google, set STR volume ten" this will set max volume.

    posted in Audio Control API
  • RE: Maximum volume = 55?

    @grolschie I currently don't have access to any of the STR-XXX devices so I can't test, the intended usage is to query the device for the current volume and get the max and min volume, (I would scale the value so it is always between 0-100 from my device handler) in theory min and max volume this can be different for every device (don't think it is), but for example the device I have HT-Z9F and SRS-ZR5 have min 0 and max 50, and the same is then using the IR remote.

    What happens then you set the volume to 55 with setAudioVolume, will it be 74 of 55 on the device?

    posted in Audio Control API