diff --git a/Binaries/OpenLog_Artemis-V10-v21.bin b/Binaries/OpenLog_Artemis-V10-v21.bin new file mode 100644 index 0000000..b36aafe Binary files /dev/null and b/Binaries/OpenLog_Artemis-V10-v21.bin differ diff --git a/Binaries/OpenLog_Artemis-X04-v21.bin b/Binaries/OpenLog_Artemis-X04-v21.bin new file mode 100644 index 0000000..140a669 Binary files /dev/null and b/Binaries/OpenLog_Artemis-X04-v21.bin differ diff --git a/CHANGELOG.md b/CHANGELOG.md index 3efad0b..2cc65e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ Change Log ====================== +v2.1 +--------- + +v2.1 is a 'mini' release: + +* The compiled binaries for v2.1 are based on v2.2.0 of the Apollo3 core +* Corrects issue [109](https://github.com/sparkfun/OpenLog_Artemis/issues/109) +* Corrects issue [104](https://github.com/sparkfun/OpenLog_Artemis/issues/104) + v2.0 --------- diff --git a/Firmware/OpenLog_Artemis/OpenLog_Artemis.ino b/Firmware/OpenLog_Artemis/OpenLog_Artemis.ino index 0b3a566..58c22b7 100644 --- a/Firmware/OpenLog_Artemis/OpenLog_Artemis.ino +++ b/Firmware/OpenLog_Artemis/OpenLog_Artemis.ino @@ -107,10 +107,15 @@ The work-around is to use Serial1 in place of serialLog and then to manually force UART1 to use pins 12 and 13 We need a work-around anyway because if pins 12 or 13 have been used as analog inputs, Serial1.begin does not re-configure them for UART TX and RX (in progress) Reduce sleep current as much as possible. v1.2.1 achieved ~110uA. With v2.1.0 the draw is more like 260uA... + + (in progress) Update to Apollo3 v2.2.0 - FIRMWARE_VERSION_MAJOR = 2; FIRMWARE_VERSION_MINOR = 1. + (done) Add a fix for issue #109 - check if a BME280 is connected before calling multiplexerBegin: https://github.com/sparkfun/OpenLog_Artemis/issues/109 + (done) Correct issue #104. enableSD was redundant. The microSD power always needs to be on if there is a card inserted, otherwise the card pulls + the SPI lines low, preventing communication with the IMU: https://github.com/sparkfun/OpenLog_Artemis/issues/104 */ const int FIRMWARE_VERSION_MAJOR = 2; -const int FIRMWARE_VERSION_MINOR = 0; +const int FIRMWARE_VERSION_MINOR = 1; //Define the OLA board identifier: // This is an int which is unique to this variant of the OLA and which allows us @@ -120,7 +125,7 @@ const int FIRMWARE_VERSION_MINOR = 0; // the variant * 0x100 (OLA = 1; GNSS_LOGGER = 2; GEOPHONE_LOGGER = 3) // the major firmware version * 0x10 // the minor firmware version -#define OLA_IDENTIFIER 0x120 // Stored as 288 decimal in OLA_settings.txt +#define OLA_IDENTIFIER 0x121 // Stored as 289 decimal in OLA_settings.txt #include "settings.h" @@ -642,58 +647,55 @@ void loop() { Serial1.print(outputData); //Print to TX pin //Record to SD - if (settings.logData == true) + if ((settings.logData == true) && (online.microSD)) { - if (settings.enableSD && online.microSD) + digitalWrite(PIN_STAT_LED, HIGH); + uint32_t recordLength = sensorDataFile.write(outputData, strlen(outputData)); + if (recordLength != strlen(outputData)) //Record the buffer to the card { - digitalWrite(PIN_STAT_LED, HIGH); - uint32_t recordLength = sensorDataFile.write(outputData, strlen(outputData)); - if (recordLength != strlen(outputData)) //Record the buffer to the card + if (settings.printDebugMessages == true) { - if (settings.printDebugMessages == true) - { - SerialPrintf3("*** sensorDataFile.write data length mismatch! *** recordLength: %d, outputDataLength: %d\r\n", recordLength, strlen(outputData)); - } + SerialPrintf3("*** sensorDataFile.write data length mismatch! *** recordLength: %d, outputDataLength: %d\r\n", recordLength, strlen(outputData)); } + } + + //Force sync every 500ms + if (bestMillis() - lastDataLogSyncTime > 500) + { + lastDataLogSyncTime = bestMillis(); + sensorDataFile.sync(); + if (settings.frequentFileAccessTimestamps == true) + updateDataFileAccess(&sensorDataFile); // Update the file access time & date + } - //Force sync every 500ms - if (bestMillis() - lastDataLogSyncTime > 500) + //Check if it is time to open a new log file + uint64_t secsSinceLastFileNameChange = rtcMillis() - lastSDFileNameChangeTime; // Calculate how long we have been logging for + secsSinceLastFileNameChange /= 1000ULL; // Convert to secs + if ((settings.openNewLogFilesAfter > 0) && (((unsigned long)secsSinceLastFileNameChange) >= settings.openNewLogFilesAfter)) + { + //Close existings files + if (online.dataLogging == true) { - lastDataLogSyncTime = bestMillis(); sensorDataFile.sync(); - if (settings.frequentFileAccessTimestamps == true) - updateDataFileAccess(&sensorDataFile); // Update the file access time & date + updateDataFileAccess(&sensorDataFile); // Update the file access time & date + sensorDataFile.close(); + strcpy(sensorDataFileName, findNextAvailableLog(settings.nextDataLogNumber, "dataLog")); + beginDataLogging(); //180ms + if (settings.showHelperText == true) printHelperText(false); //printHelperText to terminal and sensor file } - - //Check if it is time to open a new log file - uint64_t secsSinceLastFileNameChange = rtcMillis() - lastSDFileNameChangeTime; // Calculate how long we have been logging for - secsSinceLastFileNameChange /= 1000ULL; // Convert to secs - if ((settings.openNewLogFilesAfter > 0) && (((unsigned long)secsSinceLastFileNameChange) >= settings.openNewLogFilesAfter)) + if (online.serialLogging == true) { - //Close existings files - if (online.dataLogging == true) - { - sensorDataFile.sync(); - updateDataFileAccess(&sensorDataFile); // Update the file access time & date - sensorDataFile.close(); - strcpy(sensorDataFileName, findNextAvailableLog(settings.nextDataLogNumber, "dataLog")); - beginDataLogging(); //180ms - if (settings.showHelperText == true) printHelperText(false); //printHelperText to terminal and sensor file - } - if (online.serialLogging == true) - { - serialDataFile.sync(); - updateDataFileAccess(&serialDataFile); // Update the file access time & date - serialDataFile.close(); - strcpy(serialDataFileName, findNextAvailableLog(settings.nextSerialLogNumber, "serialLog")); - beginSerialLogging(); - } - - lastSDFileNameChangeTime = rtcMillis(); // Record the time of the file name change + serialDataFile.sync(); + updateDataFileAccess(&serialDataFile); // Update the file access time & date + serialDataFile.close(); + strcpy(serialDataFileName, findNextAvailableLog(settings.nextSerialLogNumber, "serialLog")); + beginSerialLogging(); } - digitalWrite(PIN_STAT_LED, LOW); + lastSDFileNameChangeTime = rtcMillis(); // Record the time of the file name change } + + digitalWrite(PIN_STAT_LED, LOW); } if ((settings.useGPIO32ForStopLogging == true) && (stopLoggingSeen == true)) // Has the user pressed the stop logging button? @@ -889,56 +891,51 @@ void beginSD() pin_config(PinName(PIN_MICROSD_CHIP_SELECT), g_AM_HAL_GPIO_OUTPUT); // Make sure the pin does actually get re-configured digitalWrite(PIN_MICROSD_CHIP_SELECT, HIGH); //Be sure SD is deselected - if (settings.enableSD == true) - { - // For reasons I don't understand, we seem to have to wait for at least 1ms after SPI.begin before we call microSDPowerOn. - // If you comment the next line, the Artemis resets at microSDPowerOn when beginSD is called from wakeFromSleep... - // But only on one of my V10 red boards. The second one I have doesn't seem to need the delay!? - delay(5); + // If the microSD card is present, it needs to be powered on otherwise the IMU will fail to start + // (The microSD card will pull the SPI pins low, preventing communication with the IMU) + + // For reasons I don't understand, we seem to have to wait for at least 1ms after SPI.begin before we call microSDPowerOn. + // If you comment the next line, the Artemis resets at microSDPowerOn when beginSD is called from wakeFromSleep... + // But only on one of my V10 red boards. The second one I have doesn't seem to need the delay!? + delay(5); - microSDPowerOn(); + microSDPowerOn(); - //Max power up time is 250ms: https://www.kingston.com/datasheets/SDCIT-specsheet-64gb_en.pdf - //Max current is 200mA average across 1s, peak 300mA - for (int i = 0; i < 10; i++) //Wait + //Max power up time is 250ms: https://www.kingston.com/datasheets/SDCIT-specsheet-64gb_en.pdf + //Max current is 200mA average across 1s, peak 300mA + for (int i = 0; i < 10; i++) //Wait + { + checkBattery(); + delay(1); + } + + if (sd.begin(SD_CONFIG) == false) // Try to begin the SD card using the correct chip select + { + printDebug(F("SD init failed (first attempt). Trying again...\r\n")); + for (int i = 0; i < 250; i++) //Give SD more time to power up, then try again { checkBattery(); delay(1); } - if (sd.begin(SD_CONFIG) == false) // Try to begin the SD card using the correct chip select { - printDebug(F("SD init failed (first attempt). Trying again...\r\n")); - for (int i = 0; i < 250; i++) //Give SD more time to power up, then try again - { - checkBattery(); - delay(1); - } - if (sd.begin(SD_CONFIG) == false) // Try to begin the SD card using the correct chip select - { - SerialPrintln(F("SD init failed (second attempt). Is card present? Formatted?")); - SerialPrintln(F("Please ensure the SD card is formatted correctly using https://www.sdcard.org/downloads/formatter/")); - digitalWrite(PIN_MICROSD_CHIP_SELECT, HIGH); //Be sure SD is deselected - online.microSD = false; - return; - } - } - - //Change to root directory. All new file creation will be in root. - if (sd.chdir() == false) - { - SerialPrintln(F("SD change directory failed")); + SerialPrintln(F("SD init failed (second attempt). Is card present? Formatted?")); + SerialPrintln(F("Please ensure the SD card is formatted correctly using https://www.sdcard.org/downloads/formatter/")); + digitalWrite(PIN_MICROSD_CHIP_SELECT, HIGH); //Be sure SD is deselected online.microSD = false; return; } - - online.microSD = true; } - else + + //Change to root directory. All new file creation will be in root. + if (sd.chdir() == false) { - microSDPowerOff(); + SerialPrintln(F("SD change directory failed")); online.microSD = false; + return; } + + online.microSD = true; } void enableCIPOpullUp() // updated for v2.1.0 of the Apollo3 core diff --git a/Firmware/OpenLog_Artemis/Sensors.ino b/Firmware/OpenLog_Artemis/Sensors.ino index c5eb695..20f8831 100644 --- a/Firmware/OpenLog_Artemis/Sensors.ino +++ b/Firmware/OpenLog_Artemis/Sensors.ino @@ -1541,7 +1541,7 @@ void printHelperText(bool terminalOnly) strcat(helperText, "\r\n"); SerialPrint(helperText); - if ((terminalOnly == false) && (settings.logData == true) && (online.microSD) && (settings.enableSD && online.microSD)) + if ((terminalOnly == false) && (settings.logData == true) && (online.microSD)) sensorDataFile.print(helperText); } diff --git a/Firmware/OpenLog_Artemis/autoDetect.ino b/Firmware/OpenLog_Artemis/autoDetect.ino index 47b7b06..88fe21a 100644 --- a/Firmware/OpenLog_Artemis/autoDetect.ino +++ b/Firmware/OpenLog_Artemis/autoDetect.ino @@ -1502,11 +1502,27 @@ deviceType_e testDevice(uint8_t i2cAddress, uint8_t muxAddress, uint8_t portNumb //Given an address, returns the device type if it responds as we would expect //This version is dedicated to testing muxes and uses a custom .begin to avoid the slippery mux problem //However, we also need to check if an MS8607 is attached (address 0x76) as it can cause the I2C bus to lock up if not detected correctly +//Also check for a BME280 - to prevent multiplexerBegin from confusing it deviceType_e testMuxDevice(uint8_t i2cAddress, uint8_t muxAddress, uint8_t portNumber) { switch (i2cAddress) { case 0x70: + { + //Ignore devices we've already recorded. This was causing the mux to get tested, a begin() would happen, and the mux would be reset. + if (deviceExists(DEVICE_MULTIPLEXER, i2cAddress, muxAddress, portNumber) == true) return (DEVICE_MULTIPLEXER); + + //I don't think multiplexerBegin will cause any badness for the SHTC3 as its commands are all 16-bit + //But, just in case, let's see if one is connected + SHTC3 sensor; + if (sensor.begin(qwiic) == 0) //Wire port. Device returns 0 upon success. + return (DEVICE_HUMIDITY_SHTC3); + + //Confidence: Medium - Write/Read/Clear to 0x00 + if (multiplexerBegin(i2cAddress, qwiic) == true) //Address, Wire port + return (DEVICE_MULTIPLEXER); + } + break; case 0x71: case 0x72: case 0x73: @@ -1532,9 +1548,7 @@ deviceType_e testMuxDevice(uint8_t i2cAddress, uint8_t muxAddress, uint8_t portN // So, we can't use .begin as the test for a MS5637 / MS5837 / MS8607. We need to be more creative! // If we write 0xA0 to i2cAddress and then read two bytes: // A mux will return 0xA0A0 - // An MS5637 / MS5837 / MS8607 will return the value stored in its eeprom which _hopefully_ is not 0xA0A0! - - // Let's hope this doesn't cause problems for the BME280...! We should be OK as the default address for the BME280 is 0x77. + // An MS5637 / MS5837 / MS8607 / BME280 will return an eeprom or register value which _hopefully_ is not 0xA0A0! qwiic.beginTransmission((uint8_t)i2cAddress); qwiic.write((uint8_t)0xA0); @@ -1543,12 +1557,12 @@ deviceType_e testMuxDevice(uint8_t i2cAddress, uint8_t muxAddress, uint8_t portN if (i2c_status == 0) // If the I2C write was successful { qwiic.requestFrom((uint8_t)i2cAddress, 2U); // Read two bytes - uint8_t buffer[2]; + uint8_t buffer[2] = { 0, 0 }; for (uint8_t i = 0; i < 2; i++) { buffer[i] = qwiic.read(); } - if ((buffer[0] != 0xA0) || (buffer[1] != 0xA0)) // If we read back something other than 0xA0A0 then we are probably talking to an MS5637 / MS5837 / MS8607, not a mux + if ((buffer[0] != 0xA0) || (buffer[1] != 0xA0)) // If we read back something other than 0xA0A0 then we are probably talking to an MS5637 / MS5837 / MS8607 / BME280, not a mux { return (DEVICE_PRESSURE_MS5637); } @@ -1564,6 +1578,29 @@ deviceType_e testMuxDevice(uint8_t i2cAddress, uint8_t muxAddress, uint8_t portN //Ignore devices we've already recorded. This was causing the mux to get tested, a begin() would happen, and the mux would be reset. if (deviceExists(DEVICE_MULTIPLEXER, i2cAddress, muxAddress, portNumber) == true) return (DEVICE_MULTIPLEXER); + //multiplexerBegin confuses the BME280, so let's check if one is connected first + // If we write 0xA0 to i2cAddress and then read two bytes: + // A mux will return 0xA0A0 + // A BME280 will return a register value which _hopefully_ is not 0xA0A0! + + qwiic.beginTransmission((uint8_t)i2cAddress); + qwiic.write((uint8_t)0xA0); + uint8_t i2c_status = qwiic.endTransmission(); + + if (i2c_status == 0) // If the I2C write was successful + { + qwiic.requestFrom((uint8_t)i2cAddress, 2U); // Read two bytes + uint8_t buffer[2] = { 0, 0 }; + for (uint8_t i = 0; i < 2; i++) + { + buffer[i] = qwiic.read(); + } + if ((buffer[0] != 0xA0) || (buffer[1] != 0xA0)) // If we read back something other than 0xA0A0 then we are probably talking to a BME280, not a mux + { + return (DEVICE_PHT_BME280); + } + } + //Confidence: Medium - Write/Read/Clear to 0x00 if (multiplexerBegin(i2cAddress, qwiic) == true) //Address, Wire port return (DEVICE_MULTIPLEXER); diff --git a/Firmware/OpenLog_Artemis/menuAttachedDevices.ino b/Firmware/OpenLog_Artemis/menuAttachedDevices.ino index 99b9625..7380535 100644 --- a/Firmware/OpenLog_Artemis/menuAttachedDevices.ino +++ b/Firmware/OpenLog_Artemis/menuAttachedDevices.ino @@ -82,7 +82,21 @@ bool detectQwiicDevices() { if (settings.printDebugMessages == true) { - SerialPrintf2("detectQwiicDevices: MS8607/MS5637/MS5837 found at address 0x%02X. Ignoring it for now...\r\n", address); + SerialPrintf2("detectQwiicDevices: MS8607/MS5637/MS5837/BME280 found at address 0x%02X. Ignoring it for now...\r\n", address); + } + } + else if (foundType == DEVICE_PHT_BME280) + { + if (settings.printDebugMessages == true) + { + SerialPrintf2("detectQwiicDevices: BME280 found at address 0x%02X. Ignoring it for now...\r\n", address); + } + } + else if (foundType == DEVICE_HUMIDITY_SHTC3) + { + if (settings.printDebugMessages == true) + { + SerialPrintf2("detectQwiicDevices: SHTC3 found at address 0x%02X. Ignoring it for now...\r\n", address); } } } diff --git a/Firmware/OpenLog_Artemis/menuMain.ino b/Firmware/OpenLog_Artemis/menuMain.ino index c65d62d..8542898 100644 --- a/Firmware/OpenLog_Artemis/menuMain.ino +++ b/Firmware/OpenLog_Artemis/menuMain.ino @@ -25,7 +25,7 @@ void menuMain() SerialPrintln(F("h) Print Sensor Helper Text (and return to logging)")); - if (settings.enableSD && online.microSD) + if (online.microSD) SerialPrintln(F("s) SD Card File Transfer")); SerialPrintln(F("r) Reset all settings to default")); @@ -61,7 +61,7 @@ void menuMain() menuDebug(); else if (incoming == 's') { - if (settings.enableSD && online.microSD) + if (online.microSD) { //Close log files before showing sdCardMenu if (online.dataLogging == true) diff --git a/Firmware/OpenLog_Artemis/nvm.ino b/Firmware/OpenLog_Artemis/nvm.ino index a46d0ab..1a58034 100644 --- a/Firmware/OpenLog_Artemis/nvm.ino +++ b/Firmware/OpenLog_Artemis/nvm.ino @@ -113,7 +113,6 @@ void recordSystemSettingsToFile() settingsFile.println("logMaxRate=" + (String)settings.logMaxRate); settingsFile.println("enableRTC=" + (String)settings.enableRTC); settingsFile.println("enableIMU=" + (String)settings.enableIMU); - settingsFile.println("enableSD=" + (String)settings.enableSD); settingsFile.println("enableTerminalOutput=" + (String)settings.enableTerminalOutput); settingsFile.println("logDate=" + (String)settings.logDate); settingsFile.println("logTime=" + (String)settings.logTime); @@ -325,8 +324,6 @@ bool parseLine(char* str) { settings.enableRTC = d; else if (strcmp(settingName, "enableIMU") == 0) settings.enableIMU = d; - else if (strcmp(settingName, "enableSD") == 0) - settings.enableSD = d; else if (strcmp(settingName, "enableTerminalOutput") == 0) settings.enableTerminalOutput = d; else if (strcmp(settingName, "logDate") == 0) diff --git a/Firmware/OpenLog_Artemis/settings.h b/Firmware/OpenLog_Artemis/settings.h index 936cae1..a24b77b 100644 --- a/Firmware/OpenLog_Artemis/settings.h +++ b/Firmware/OpenLog_Artemis/settings.h @@ -352,7 +352,6 @@ struct struct_settings { bool logMaxRate = false; bool enableRTC = true; bool enableIMU = true; - bool enableSD = true; bool enableTerminalOutput = true; bool logDate = true; bool logTime = true; diff --git a/UPGRADE.md b/UPGRADE.md index 168b0cd..53036a4 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -7,8 +7,8 @@ Which is handy if you want to quickly update the firmware in the field, or are n The firmware is customized for the different versions of the OLA hardware. You will find versions for the **X04 SparkX (Black) OLA** and **V10 SparkFun (Red) OLA** plus any subsequent revisions. The filename tells you which hardware the firmware is for and what version it is: -* **OpenLog_Artemis-V10-v20.bin** - is the _stable_ version for the **V10 SparkFun (Red) OLA** -* **OpenLog_Artemis-X04-v20.bin** - is the _stable_ version for the **X04 SparkX (Black) OLA** +* **OpenLog_Artemis-V10-v21.bin** - is the _stable_ version for the **V10 SparkFun (Red) OLA** +* **OpenLog_Artemis-X04-v21.bin** - is the _stable_ version for the **X04 SparkX (Black) OLA**