From daaefc7eba2825103622bc542f5b4610da8cf52f Mon Sep 17 00:00:00 2001 From: Thomas Hooge Date: Wed, 25 Dec 2024 19:23:44 +0100 Subject: [PATCH] Use I2C FRAM module if available to store page voltage state --- lib/obp60task/OBP60Extensions.cpp | 28 ++++++++++++++++++++++++++-- lib/obp60task/OBP60Extensions.h | 22 +++++++++++++++++++++- lib/obp60task/OBP60Hardware.h | 2 ++ lib/obp60task/PageVoltage.cpp | 19 ++++++++++++++++--- lib/obp60task/obp60task.cpp | 2 +- lib/obp60task/platformio.ini | 1 + 6 files changed, 67 insertions(+), 7 deletions(-) diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index 5ef81d8..c288bd8 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -61,6 +61,10 @@ GxEPD2_BW & getdisplay(){r // Horter I2C moduls PCF8574 pcf8574_Out(PCF8574_I2C_ADDR1); // First digital output modul PCF8574 from Horter +// FRAM +Adafruit_FRAM_I2C fram; +bool hasFRAM = false; + // Global vars bool blinkingLED = false; // Enable / disable blinking flash LED bool statusLED = false; // Actual status of flash LED on/off @@ -70,7 +74,7 @@ int uvDuration = 0; // Under voltage duration in n x 100ms LedTaskData *ledTaskData=nullptr; -void hardwareInit() +void hardwareInit(GwApi *api) { Wire.begin(); // Init PCF8574 digital outputs @@ -78,7 +82,27 @@ void hardwareInit() if(pcf8574_Out.begin()){ // Initialize PCF8574 pcf8574_Out.write8(255); // Clear all outputs } - + fram = Adafruit_FRAM_I2C(); + if (esp_reset_reason() == ESP_RST_POWERON) { + // help initialize FRAM + api->getLogger()->logDebug(GwLog::LOG,"Delaying I2C init for 250ms due to cold boot"); + delay(250); + } + // FRAM (e.g. MB85RC256V) + if (fram.begin(FRAM_I2C_ADDR)) { + hasFRAM = true; + uint16_t manufacturerID; + uint16_t productID; + fram.getDeviceID(&manufacturerID, &productID); + // Boot counter + uint8_t framcounter = fram.read(0x0000); + fram.write(0x0000, framcounter+1); + api->getLogger()->logDebug(GwLog::LOG,"FRAM detected: 0x%04x/0x%04x (counter=%d)", manufacturerID, productID, framcounter); + } + else { + hasFRAM = false; + api->getLogger()->logDebug(GwLog::LOG,"NO FRAM detected"); + } } void startLedTask(GwApi *api){ diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h index c07bd54..a0be7cd 100644 --- a/lib/obp60task/OBP60Extensions.h +++ b/lib/obp60task/OBP60Extensions.h @@ -8,6 +8,19 @@ #define FASTLED_ESP32_FLASH_LOCK 1 #include "LedSpiTask.h" #include // E-paper lib V2 +#include // I2C FRAM + +// FRAM address reservations 32kB: 0x0000 - 0x7FFF +// 0x0000 - 0x03ff: single variables +#define FRAM_VOLTAGE_AVG 0x000A +#define FRAM_VOLTAGE_TREND 0x000B +#define FRAM_VOLTAGE_MODE 0x000C +// Barograph history data +#define FRAM_BAROGRAPH_START 0x0400 +#define FRAM_BAROGRAPH_END 0x13FF + +extern Adafruit_FRAM_I2C fram; +extern bool hasFRAM; // Fonts declarations for display (#inclues see OBP60Extensions.cpp) extern const GFXfont Ubuntu_Bold8pt7b; @@ -47,7 +60,7 @@ Point rotatePoint(const Point& origin, const Point& p, double angle); std::vector rotatePoints(const Point& origin, const std::vector& pts, double angle); void fillPoly4(const std::vector& p4, uint16_t color); -void hardwareInit(); +void hardwareInit(GwApi *api); void setPortPin(uint pin, bool value); // Set port pin for extension port @@ -83,4 +96,11 @@ void startLedTask(GwApi *api); void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request); +#define fram_width 16 +#define fram_height 16 +static unsigned char fram_bits[] PROGMEM = { + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f }; + #endif diff --git a/lib/obp60task/OBP60Hardware.h b/lib/obp60task/OBP60Hardware.h index f450790..4782b4c 100644 --- a/lib/obp60task/OBP60Hardware.h +++ b/lib/obp60task/OBP60Hardware.h @@ -30,6 +30,8 @@ #define INA226_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator // Horter modules #define PCF8574_I2C_ADDR1 0x20 // First digital out module + // FRAM (e.g. MB85RC256V) + #define FRAM_I2C_ADDR 0x50 // SPI (E-Ink display, Extern Bus) #define OBP_SPI_CS 39 #define OBP_SPI_DC 40 diff --git a/lib/obp60task/PageVoltage.cpp b/lib/obp60task/PageVoltage.cpp index 8a30006..cdee817 100644 --- a/lib/obp60task/PageVoltage.cpp +++ b/lib/obp60task/PageVoltage.cpp @@ -8,20 +8,26 @@ class PageVoltage : public Page { bool init = false; // Marker for init done bool keylock = false; // Keylock -int average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s +uint8_t average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s bool trend = true; // Trend indicator [0|1], 0=off, 1=on double raw = 0; char mode = 'D'; // display mode (A)nalog | (D)igital public: PageVoltage(CommonData &common){ - common.logger->logDebug(GwLog::LOG,"Show PageVoltage"); + common.logger->logDebug(GwLog::LOG,"Instantiate PageVoltage"); + if (hasFRAM) { + average = fram.read(FRAM_VOLTAGE_AVG); + trend = fram.read(FRAM_VOLTAGE_TREND); + mode = fram.read(FRAM_VOLTAGE_MODE); + } } virtual int handleKey(int key){ // Change average if(key == 1){ average ++; average = average % 4; // Modulo 4 + if (hasFRAM) fram.write(FRAM_VOLTAGE_AVG, average); return 0; // Commit the key } @@ -32,12 +38,14 @@ public: } else { mode = 'A'; } + if (hasFRAM) fram.write(FRAM_VOLTAGE_MODE, mode); return 0; } // Trend indicator if(key == 5){ trend = !trend; + if (hasFRAM) fram.write(FRAM_VOLTAGE_TREND, trend); return 0; // Commit the key } @@ -335,7 +343,7 @@ public: // Symbol printVoltageSymbol(40, 60, commonData.fgcolor); - // Additional informatio at right side + // Additional information at right side getdisplay().setFont(&Ubuntu_Bold8pt7b); getdisplay().setCursor(300, 60); getdisplay().print("Source:"); @@ -351,6 +359,11 @@ public: getdisplay().print("Avg:"); printAvg(average, 300, 180, false); + // FRAM indicator + if (hasFRAM) { + getdisplay().drawXBitmap(300, 240, fram_bits, fram_width, fram_height, commonData.fgcolor); + } + } // Key Layout diff --git a/lib/obp60task/obp60task.cpp b/lib/obp60task/obp60task.cpp index 7f65bbc..40a00c7 100644 --- a/lib/obp60task/obp60task.cpp +++ b/lib/obp60task/obp60task.cpp @@ -43,7 +43,7 @@ void OBP60Init(GwApi *api){ // Init hardware - hardwareInit(); + hardwareInit(api); // Init power rail 5.0V String powermode = api->getConfig()->getConfigItem(api->getConfig()->powerMode,true)->asString(); diff --git a/lib/obp60task/platformio.ini b/lib/obp60task/platformio.ini index 14bd788..63f1085 100644 --- a/lib/obp60task/platformio.ini +++ b/lib/obp60task/platformio.ini @@ -35,6 +35,7 @@ lib_deps = paulstoffregen/OneWire@2.3.8 milesburton/DallasTemperature@3.11.0 signetica/SunRise@2.0.2 + adafruit/Adafruit FRAM I2C@^2.0.3 build_flags= #https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL # -D ARDUINO_USB_MODE=1 #0=OTG (to implement other external devices), 1=CDC (is a serial device)