From 9405b3d8b8204a42bf58b74f940cda9ff19812e5 Mon Sep 17 00:00:00 2001 From: Maximilian Grau Date: Mon, 1 Nov 2021 16:56:50 +0100 Subject: [PATCH] Save/load state of BME680 to intern EEPROM --- src/bmeSPI.cxx | 89 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 12 deletions(-) diff --git a/src/bmeSPI.cxx b/src/bmeSPI.cxx index 6499172..1f6e422 100644 --- a/src/bmeSPI.cxx +++ b/src/bmeSPI.cxx @@ -3,12 +3,14 @@ #include "main.h" #include "semphr.h" #include "spi.h" +#include "stm32l1xx_hal_flash_ex.h" #include "task.h" #include #include "BME68x-Sensor-API/bme68x.h" #include "BSEC/bsec_interface.h" +#include "SSD1306_SPI.hpp" #include "oled-driver/Renderer.hpp" extern QueueHandle_t spiMutex; @@ -51,8 +53,10 @@ float iaq, rawTemperature, pressure, rawHumidity, gasResistance, stabStatus, run uint8_t iaqAccuracy, staticIaqAccuracy, co2Accuracy, breathVocAccuracy, compGasAccuracy, gasPercentageAcccuracy; -// uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE]; -// uint8_t workBuffer[BSEC_MAX_WORKBUFFER_SIZE]; +uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE]; +uint8_t workBuffer[BSEC_MAX_WORKBUFFER_SIZE]; + +constexpr uintptr_t EepromAddress = FLASH_EEPROM_BASE; void setChipSelect(bool state) { @@ -310,33 +314,94 @@ void printBmeSensorData() { renderer.clearAll(); - snprintf(buffer, MaximumChars, - "%d°C, %luhPa, %d%%\nIAQ: %d, Accuracy: %d\nCO2: %dppm\n%d, %d, %d - %lukOhm", + const auto MaxTextWidth = renderer.getLineWidth("1000hPa"); + + snprintf(buffer, MaximumChars, "%d°C\n%luhPa\n%d%%\nAcc: %d", static_cast(temperature), // bmeData[numberOfData - 1].pressure / 100, // static_cast(humidity), // - static_cast(iaq), // - iaqAccuracy, // - static_cast(co2Equivalent), // - bmeData[numberOfData - 1].status, // - bmeData[numberOfData - 1].gas_index, // - bmeData[numberOfData - 1].gas_wait, // - bmeData[numberOfData - 1].gas_resistance / 1000); + iaqAccuracy); + renderer.print({128, 0}, buffer, Renderer::Alignment::Right); + renderer.drawVerticalLine(OledWidth - MaxTextWidth - 2, 0, OledPages - 1); - renderer.print({0, 0}, buffer); + if (iaqAccuracy == 0) + snprintf(buffer, MaximumChars, "IAQ:---\n---ppm\n"); + else + snprintf(buffer, MaximumChars, "IAQ:%d\n%dppm\n", + static_cast(iaq), // + static_cast(co2Equivalent)); + + renderer.print({0, 0}, buffer, Renderer::Alignment::Left, 2); renderer.render(); } +void readStateFromEeprom() +{ + + uint8_t sizeOfData = *reinterpret_cast(EepromAddress); + + if (sizeOfData != BSEC_MAX_STATE_BLOB_SIZE) + return; + + // Existing state in EEPROM + for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++) + { + bsecState[i] = *reinterpret_cast(EepromAddress + i + 1); + } + + bsec_set_state(bsecState, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, sizeof(workBuffer)); +} + +void writeStateToEeprom() +{ + if (iaqAccuracy != 3) + return; + + uint32_t numberSerializedState = BSEC_MAX_STATE_BLOB_SIZE; + + auto status = bsec_get_state(0, bsecState, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, + BSEC_MAX_STATE_BLOB_SIZE, &numberSerializedState); + + if (status != BSEC_OK) + return; + + HAL_FLASHEx_DATAEEPROM_Unlock(); + + // write size + HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EepromAddress, + BSEC_MAX_STATE_BLOB_SIZE); + + for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++) + { + HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EepromAddress + i + 1, + bsecState[i]); + } + + HAL_FLASHEx_DATAEEPROM_Lock(); +} + //-------------------------------------------------------------------------------------------------- extern "C" void sensorTask(void *) { initDisplay(); bmeSensorInit(); + readStateFromEeprom(); + + uint16_t counter = 0; while (1) { bmeRun(); bsecRun(); printBmeSensorData(); + + if (counter++ >= 100) + { + initDisplay(); + counter = 0; + writeStateToEeprom(); + } + + vTaskDelay(pdMS_TO_TICKS(10)); } } \ No newline at end of file