From 991a63aed2f2d004835bd056cf83ad795432dadb Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 20 Oct 2022 08:53:51 +0100 Subject: [PATCH] Create DataLoggingExample7_OpenLogESP32_SPI_SDIO.ino --- ...aLoggingExample7_OpenLogESP32_SPI_SDIO.ino | 322 ++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 examples/Data_Logging/DataLoggingExample7_OpenLogESP32_SPI_SDIO/DataLoggingExample7_OpenLogESP32_SPI_SDIO.ino diff --git a/examples/Data_Logging/DataLoggingExample7_OpenLogESP32_SPI_SDIO/DataLoggingExample7_OpenLogESP32_SPI_SDIO.ino b/examples/Data_Logging/DataLoggingExample7_OpenLogESP32_SPI_SDIO/DataLoggingExample7_OpenLogESP32_SPI_SDIO.ino new file mode 100644 index 0000000..21ad52f --- /dev/null +++ b/examples/Data_Logging/DataLoggingExample7_OpenLogESP32_SPI_SDIO/DataLoggingExample7_OpenLogESP32_SPI_SDIO.ino @@ -0,0 +1,322 @@ +/* + Configuring the GNSS to automatically send RXM SFRBX and RAWX reports over SPI and log them to file on SD card using full 4-bit SDIO + By: Paul Clark + SparkFun Electronics + Date: October 20th, 2022 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to configure the u-blox GNSS to send RXM SFRBX and RAWX reports automatically + and log the data to SD card in UBX format. + + This code is written for the OpenLog ESP32 (DEV-20594) - coming soon! + + Hardware set-up: + Close the DSEL jumper on the ZED-F9P breakout - to select SPI mode + Connect: + OpenLog ESP32 : ZED-F9P + GND GND + 3V3_SW 3V3 + SCK (18) SCK + PICO (23) PICO (MOSI) + POCI (19) POCI (MISO) + 33 CS + + ** Please note: this example will only work on u-blox ADR or High Precision GNSS or Time Sync products ** + + Data is logged in u-blox UBX format. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + OpenLog ESP32: https://www.sparkfun.com/products/20594 + ZED-F9P RTK2: https://www.sparkfun.com/products/15136 + NEO-M8P RTK: https://www.sparkfun.com/products/15005 +*/ + +#define GNSS_CS 33 // Connect the ZED-F9P CS pin to OpenLog ESP32 pin 33 +#define EN_3V3_SW 32 // The 3.3V_SW regulator Enable pin is connected to D32 +#define STAT_LED 25 // The OpenLog ESP32 STAT LED is connected to pin 25 +#define IMU_CS 5 // The ISM330 IMU CS is connected to pin 5 +#define MAG_CS 27 // The MMC5983 Mag CS is connected to pin 27 + +#include "FS.h" +#include "SD_MMC.h" +File myFile; + +#include +#define spiPort SPI + +#include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +#define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes +#define fileBufferSize 16384 // Allocate 16KBytes of RAM for UBX message storage +uint8_t *myBuffer; // Use myBuffer to hold the data while we write it to SD card + +unsigned long lastPrint; // Record when the last Serial print took place + +// Note: we'll keep a count of how many SFRBX and RAWX messages arrive - but the count will not be completely accurate. +// If two or more SFRBX messages arrive together as a group and are processed by one call to checkUblox, the count will +// only increase by one. + +int numSFRBX = 0; // Keep count of how many SFRBX message groups have been received (see note above) +int numRAWX = 0; // Keep count of how many RAWX message groups have been received (see note above) + +// Callback: newSFRBX will be called when new RXM SFRBX data arrives +// See u-blox_structs.h for the full definition of UBX_RXMSFRBX_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMSFRBXcallback +// / _____ This _must_ be UBX_RXM_SFRBX_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void newSFRBX(UBX_RXM_SFRBX_data_t *ubxDataStruct) +{ + numSFRBX++; // Increment the count +} + +// Callback: newRAWX will be called when new RXM RAWX data arrives +// See u-blox_structs.h for the full definition of UBX_RXMRAWX_data_t +// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMRAWXcallback +// / _____ This _must_ be UBX_RXM_RAWX_data_t +// | / _____ You can use any name you like for the struct +// | | / +// | | | +void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct) +{ + numRAWX++; // Increment the count +} + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println(F("SparkFun OpenLog ESP32 GNSS Logging : SPI and SDIO")); + + pinMode(STAT_LED, OUTPUT); // Flash the STAT LED each time we write to the SD card + digitalWrite(STAT_LED, LOW); + + pinMode(GNSS_CS, OUTPUT); + digitalWrite(GNSS_CS, HIGH); + pinMode(IMU_CS, OUTPUT); + digitalWrite(IMU_CS, HIGH); + pinMode(MAG_CS, OUTPUT); + digitalWrite(MAG_CS, HIGH); + + pinMode(EN_3V3_SW, OUTPUT); // Enable power for the microSD card and GNSS + digitalWrite(EN_3V3_SW, HIGH); + + delay(1000); // Allow time for the SD card to start up + + spiPort.begin(); + + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Initialize the GNSS. Wait for a 3D fix. Get the date and time for the log file + + Serial.println(F("Initializing the GNSS...")); + + //myGNSS.enableDebugging(); // Uncomment this line to see helpful debug messages on Serial + + myGNSS.setFileBufferSize(fileBufferSize); // setFileBufferSize must be called _before_ .begin + + // Connect to the u-blox module using SPI port, csPin and speed setting + // ublox devices generally work up to 5MHz. We'll use 4MHz for this example: + bool begun = false; + do + { + begun = myGNSS.begin(spiPort, GNSS_CS, 4000000); + if (!begun) + { + Serial.println(F("u-blox GNSS not detected on SPI bus. Please check wiring.")); + delay(1000); + } + } + while (!begun); + + //myGNSS.factoryDefault(); delay(5000); // Uncomment this line to reset the module back to its factory defaults + + myGNSS.setSPIOutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the SPI port to output both UBX and NMEA messages + + //myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Optional: save (only) the communications port settings to flash and BBR + + Serial.print(F("Waiting for a 3D fix")); + + uint8_t fix = 0; + + do + { + fix = myGNSS.getFixType(); + delay(1000); + Serial.print(F(".")); + } + while ( fix != 3 ); // Wait for a 3D fix + + Serial.println(); + + uint16_t y = myGNSS.getYear(); + uint8_t M = myGNSS.getMonth(); + uint8_t d = myGNSS.getDay(); + uint8_t h = myGNSS.getHour(); + uint8_t m = myGNSS.getMinute(); + uint8_t s = myGNSS.getSecond(); + + char szBuffer[40] = {'\0'}; + snprintf(szBuffer, sizeof(szBuffer), "/%04d%02d%02d%02d%02d%02d.ubx", y, M, d, h, m, s); + + Serial.println(F("GNSS initialized.")); + + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Initialize the SD card. Open the log file + + Serial.println(F("Initializing SD card...")); + + // Begin the SD card + if(!SD_MMC.begin()) + { + Serial.println(F("Card mount failed. Freezing...")); + while(1); + } + + // Open the log file for writing + Serial.printf("Log file is: %s\r\n", szBuffer); + myFile = SD_MMC.open((const char *)szBuffer, FILE_WRITE); + if(!myFile) + { + Serial.println(F("Failed to open log file for writing. Freezing...")); + while(1); + } + + Serial.println(F("SD card initialized.")); + + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Wait for a key press + + while (Serial.available()) // Make sure the Serial buffer is empty + { + Serial.read(); + } + + Serial.println(F("Press any key to start logging.")); + + while (!Serial.available()) // Wait for the user to press a key + { + ; // Do nothing + } + + delay(100); // Wait, just in case multiple characters were sent + + while (Serial.available()) // Empty the Serial buffer + { + Serial.read(); + } + + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Enable RAWX and SFRBX + + myGNSS.setNavigationFrequency(4); // Set navigation rate to 4Hz + + myGNSS.setAutoRXMSFRBXcallbackPtr(&newSFRBX); // Enable automatic RXM SFRBX messages with callback to newSFRBX + + myGNSS.logRXMSFRBX(); // Enable RXM SFRBX data logging + + myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX + + myGNSS.logRXMRAWX(); // Enable RXM RAWX data logging + + myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_SPI, 1); // Ensure the GxGGA (Global positioning system fix data) message is enabled. Send every measurement. + myGNSS.enableNMEAMessage(UBX_NMEA_GSA, COM_PORT_SPI, 1); // Ensure the GxGSA (GNSS DOP and Active satellites) message is enabled. Send every measurement. + myGNSS.enableNMEAMessage(UBX_NMEA_GSV, COM_PORT_SPI, 1); // Ensure the GxGSV (GNSS satellites in view) message is enabled. Send every measurement. + + myGNSS.setNMEALoggingMask(SFE_UBLOX_FILTER_NMEA_ALL); // Enable logging of all enabled NMEA messages + + myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card + + Serial.println(F("Press any key to stop logging.")); + + lastPrint = millis(); // Initialize lastPrint +} + +void loop() +{ + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + myGNSS.checkUblox(); // Check for the arrival of new data and process it. + myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + while (myGNSS.fileBufferAvailable() >= sdWriteSize) // Check to see if we have at least sdWriteSize waiting in the buffer + { + digitalWrite(STAT_LED, HIGH); // Flash the STAT LED each time we write to the SD card + + myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer + + myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card + + // In case the SD writing is slow or there is a lot of data to write, keep checking for the arrival of new data + myGNSS.checkUblox(); // Check for the arrival of new data and process it. + myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. + + digitalWrite(STAT_LED, LOW); // Turn the STAT LED off again + } + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + if (millis() > (lastPrint + 1000)) // Print the message count once per second + { + Serial.print(F("Number of message groups received: SFRBX: ")); // Print how many message groups have been received (see note above) + Serial.print(numSFRBX); + Serial.print(F(" RAWX: ")); + Serial.println(numRAWX); + + uint16_t maxBufferBytes = myGNSS.getMaxFileBufferAvail(); // Get how full the file buffer has been (not how full it is now) + + //Serial.print(F("The maximum number of bytes which the file buffer has contained is: ")); // It is a fun thing to watch how full the buffer gets + //Serial.println(maxBufferBytes); + + if (maxBufferBytes > ((fileBufferSize / 5) * 4)) // Warn the user if fileBufferSize was more than 80% full + { + Serial.println(F("Warning: the file buffer has been over 80% full. Some data may have been lost.")); + } + + lastPrint = millis(); // Update lastPrint + } + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + if (Serial.available()) // Check if the user wants to stop logging + { + uint16_t remainingBytes = myGNSS.fileBufferAvailable(); // Check if there are any bytes remaining in the file buffer + + while (remainingBytes > 0) // While there is still data in the file buffer + { + digitalWrite(STAT_LED, HIGH); // Flash the STAT LED while we write to the SD card + + uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time + if (bytesToWrite > sdWriteSize) + { + bytesToWrite = sdWriteSize; + } + + myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer + + myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card + + remainingBytes -= bytesToWrite; // Decrement remainingBytes + } + + digitalWrite(STAT_LED, LOW); // Turn the STAT LED off + + myFile.close(); // Close the data file + + myGNSS.setNavigationFrequency(1); // Set navigation rate to 1Hz + + myGNSS.disableMessage(UBX_CLASS_RXM, UBX_RXM_RAWX, COM_PORT_SPI); + myGNSS.disableMessage(UBX_CLASS_RXM, UBX_RXM_SFRBX, COM_PORT_SPI); + + Serial.println(F("Logging stopped. Freezing...")); + while(1); // Do nothing more + } + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +}