From 50db32676c9b133e9ef64e4c681246ac564b51f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?= Date: Fri, 12 Apr 2024 09:11:28 +0200 Subject: [PATCH] persistent config for ESP8266 --- lib/patrix/config.cpp | 109 ++++++++++++++++++++++++++++++++++++++---- lib/patrix/config.h | 2 +- platformio.ini | 6 +-- src/Fermenter.cpp | 60 +++++++++++++---------- src/Test.cpp | 23 +++++++++ 5 files changed, 162 insertions(+), 38 deletions(-) create mode 100644 src/Test.cpp diff --git a/lib/patrix/config.cpp b/lib/patrix/config.cpp index 78990fe..8b12d64 100644 --- a/lib/patrix/config.cpp +++ b/lib/patrix/config.cpp @@ -23,7 +23,7 @@ void configReset() { nvs_flash_init(); config.begin("config", false); config.putString("HOSTNAME", HOSTNAME); - configLoad(); + configLoaded(); } String configGetString(const char *name, const char *fallback, bool allowEmpty) { @@ -48,34 +48,125 @@ double configGetDouble(const char *name, double fallback) { return config.getDouble(name); } -bool configPutDouble(const char *name, double fallback) { - return config.value(name, fallback) == 0; +bool configPutDouble(const char *name, double value) { + return config.value(name, value) == 0; } #else +#include +#include + +JsonDocument json; + +bool configRead(); + +bool configWrite(); + +size_t configWriteBytes(int *address, uint8_t *data, size_t size); + +size_t configReadBytes(int *address, uint8_t *data, size_t size); + void configSetup() { - // ESP8266 FAKE + configRead(); } void configReset() { - // ESP8266 FAKE + json.clear(); + json["HOSTNAME"] = HOSTNAME; + configWrite(); } String configGetString(const char *name, const char *fallback, bool allowEmpty) { - return fallback; + if (!json.containsKey(name)) { + return fallback; + } + String value = json[name]; + if (!allowEmpty && value.isEmpty()) { + return fallback; + } + return value; } bool configPutString(const char *name, const char *value) { - return false; + json[name] = value; + return configWrite(); } double configGetDouble(const char *name, double fallback) { - return fallback; + if (!json.containsKey(name)) { + return fallback; + } + return json[name]; } -bool configPutDouble(const char *name, double fallback) { +bool configPutDouble(const char *name, double value) { + json[name] = value; + return configWrite(); +} + +bool configRead() { + size_t length; + char buffer[512]; + + bool ok = true; + int address = 0; + EEPROM.begin(512); + ok &= configReadBytes(&address, reinterpret_cast(&length), sizeof length); + ok &= configReadBytes(&address, reinterpret_cast(buffer), length); + ok &= EEPROM.end(); + + if (ok) { + JsonDocument tmp; + deserializeJson(tmp, buffer); + if (tmp.is() && !tmp.isNull() && tmp.containsKey("HOSTNAME")) { + info("Config loaded"); + json = tmp; + return true; + } else { + error("Failed to parse config JSON"); + } + } else { + error("Failed to load config from EEPROM"); + } return false; } +bool configWrite() { + char buffer[512]; + size_t length = serializeJson(json, buffer, sizeof buffer); + + bool ok = true; + int address = 0; + EEPROM.begin(512); + ok &= configWriteBytes(&address, reinterpret_cast(&length), sizeof length); + ok &= configWriteBytes(&address, reinterpret_cast(buffer), length); + ok &= EEPROM.end(); + return ok; +} + +size_t configWriteBytes(int *address, uint8_t *data, size_t size) { + uint8_t *b = data; + for (; b < data + size; b++) { + EEPROM.write((*address)++, *b); + if (*address >= EEPROM.length()) { + error("END OF EEPROM!!!"); + break; + } + } + return b - data; +} + +size_t configReadBytes(int *address, uint8_t *data, size_t size) { + uint8_t *b = data; + for (; b < data + size; b++) { + *b = EEPROM.read((*address)++); + if (*address >= EEPROM.length()) { + error("END OF EEPROM!!!"); + break; + } + } + return b - data; +} + #endif diff --git a/lib/patrix/config.h b/lib/patrix/config.h index 9814b1e..c749472 100644 --- a/lib/patrix/config.h +++ b/lib/patrix/config.h @@ -7,7 +7,7 @@ void configSetup(); void configReset(); -void configLoad(); +void configLoaded(); String configGetString(const char *name, const char *fallback, bool allowEmpty); diff --git a/platformio.ini b/platformio.ini index d96b0d2..f0a0806 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,7 +29,7 @@ monitor_port = ${COMMON.monitor_port} monitor_speed = ${COMMON.monitor_speed} monitor_filters = ${COMMON.monitor_filters} lib_deps = ${COMMON.lib_deps} -build_flags = -D HOSTNAME=\"TEST32\" -D WIFI_SSID=\"${COMMON.WIFI_SSID}\" -D WIFI_PKEY=\"${COMMON.WIFI_PKEY}\" -D OTA_PASSWORD=\"OtaAuthPatrixTEST32\" -D BOOT_DELAY=false -D DEBUG_LOG=false +build_flags = -D TEST32 -D HOSTNAME=\"TEST32\" -D WIFI_SSID=\"${COMMON.WIFI_SSID}\" -D WIFI_PKEY=\"${COMMON.WIFI_PKEY}\" -D OTA_PASSWORD=\"OtaAuthPatrixTEST32\" -D BOOT_DELAY=false -D DEBUG_LOG=false [env:TEST8266] upload_port = 10.0.0.162 @@ -44,7 +44,7 @@ monitor_port = ${COMMON.monitor_port} monitor_speed = ${COMMON.monitor_speed} monitor_filters = esp8266_exception_decoder lib_deps = ${COMMON.lib_deps} -build_flags = -D HOSTNAME=\"TEST8266\" -D WIFI_SSID=\"${COMMON.WIFI_SSID}\" -D WIFI_PKEY=\"${COMMON.WIFI_PKEY}\" -D OTA_PASSWORD=\"OtaAuthPatrixTEST8266\" -D BOOT_DELAY=true -D DEBUG_LOG=true +build_flags = -D TEST8266 -D HOSTNAME=\"TEST8266\" -D WIFI_SSID=\"${COMMON.WIFI_SSID}\" -D WIFI_PKEY=\"${COMMON.WIFI_PKEY}\" -D OTA_PASSWORD=\"OtaAuthPatrixTEST8266\" -D BOOT_DELAY=true -D DEBUG_LOG=true [env:Fermenter] upload_port = 10.0.0.164 @@ -59,4 +59,4 @@ monitor_port = ${COMMON.monitor_port} monitor_speed = ${COMMON.monitor_speed} monitor_filters = esp8266_exception_decoder lib_deps = ${COMMON.lib_deps} -build_flags = -D HOSTNAME=\"Fermenter\" -D WIFI_SSID=\"${COMMON.WIFI_SSID}\" -D WIFI_PKEY=\"${COMMON.WIFI_PKEY}\" -D OTA_PASSWORD=\"OtaAuthPatrixFermenter\" -D BOOT_DELAY=true -D DEBUG_LOG=true +build_flags = -D FERMENTER -D HOSTNAME=\"Fermenter\" -D WIFI_SSID=\"${COMMON.WIFI_SSID}\" -D WIFI_PKEY=\"${COMMON.WIFI_PKEY}\" -D OTA_PASSWORD=\"OtaAuthPatrixFermenter\" -D BOOT_DELAY=true -D DEBUG_LOG=true diff --git a/src/Fermenter.cpp b/src/Fermenter.cpp index c5b850a..e13c0b3 100644 --- a/src/Fermenter.cpp +++ b/src/Fermenter.cpp @@ -1,3 +1,5 @@ +#if defined(FERMENTER) + #include #include "sensors/Dallas.h" #include "sensors/DallasSensor.h" @@ -10,31 +12,37 @@ #define CONTROL_PWM_BITS 10 #define CONTROL_PWM_MAX (pow(2, CONTROL_PWM_BITS) - 1) +#define PID_DEFAULT_P 100 +#define PID_DEFAULT_I 10 +#define PID_DEFAULT_D 0 +#define PID_DEFAULT_TARGET 31 +#define PID_DEFAULT_OVER 5 + Dallas dallas(SENSOR_GPIO); DallasSensor sensor(dallas, 0x3D0417C1D740FF28, "sensor", 0.5, 5, 60); ArduPID pid; -double temperatureTarget = 31; +double proportional = PID_DEFAULT_P; + +double integral = PID_DEFAULT_I; + +double derivative = PID_DEFAULT_D; + +double temperatureTarget = PID_DEFAULT_TARGET; + +double temperatureOver = PID_DEFAULT_OVER; double temperatureCurrent = NAN; -double temperatureMaxOvershoot = 5; - double heaterPWM = 0; -double proportional = 1; - -double integral = 0; - -double derivative = 0; - void patrixSetup() { dallas.begin(); analogWriteResolution(CONTROL_PWM_BITS); - configLoad(); + configLoaded(); pid.begin(&temperatureCurrent, &heaterPWM, &temperatureTarget, proportional, integral, derivative); pid.setOutputLimits(0, CONTROL_PWM_MAX); @@ -52,7 +60,7 @@ void patrixLoop() { heaterPWM = 0; } - const bool emergencyCutOff = heaterPWM > 0 && temperatureCurrent > temperatureTarget + temperatureMaxOvershoot; + const bool emergencyCutOff = heaterPWM > 0 && temperatureCurrent > temperatureTarget + temperatureOver; if (emergencyCutOff) { heaterPWM = 0; } @@ -67,7 +75,7 @@ void patrixLoop() { int heaterPercent = (int) round(100.0 * heaterPWM / CONTROL_PWM_MAX); debug("p: %.10f | i: %.10f | d: %.10f | current: %5.2f | target: %5.2f | heater: %3d%%", proportional, integral, derivative, temperatureCurrent, temperatureTarget, heaterPercent); if (emergencyCutOff) { - error("[EMERGENCY CUTOFF] temperatureCurrent (=%5.2f) > temperatureTarget + %5.2f (=%5.2f) [EMERGENCY CUTOFF]", temperatureCurrent, temperatureMaxOvershoot, temperatureTarget); + error("[EMERGENCY CUTOFF] temperatureCurrent (=%5.2f) > temperatureTarget + %5.2f (=%5.2f) [EMERGENCY CUTOFF]", temperatureCurrent, temperatureOver, temperatureTarget); } } } @@ -99,15 +107,15 @@ bool setDouble(const char *name, double *destinationPtr, double min, double max) bool patrix_command(char *first) { bool result = false; - if (strcmp(first, "over") == 0) { - result = setDouble("over", &temperatureMaxOvershoot, 0, 20); - } else if (strcmp(first, "target") == 0) { + if (strcmp(first, "over") == 0 || strcmp(first, "o") == 0) { + result = setDouble("over", &temperatureOver, 0, 20); + } else if (strcmp(first, "target") == 0 || strcmp(first, "t") == 0) { result = setDouble("target", &temperatureTarget, -10, 60); - } else if (strcmp(first, "p") == 0) { + } else if (strcmp(first, "proportional") == 0 || strcmp(first, "p") == 0) { result = setDouble("p", &proportional, NAN, NAN); - } else if (strcmp(first, "i") == 0) { + } else if (strcmp(first, "integral") == 0 || strcmp(first, "i") == 0) { result = setDouble("i", &integral, NAN, NAN); - } else if (strcmp(first, "d") == 0) { + } else if (strcmp(first, "derivative") == 0 || strcmp(first, "d") == 0) { result = setDouble("d", &derivative, NAN, NAN); } if (result) { @@ -116,11 +124,13 @@ bool patrix_command(char *first) { return result; } -void configLoad() { - proportional = configGetDouble("p", 3000); - integral = configGetDouble("i", 10); - derivative = configGetDouble("d", 0); - temperatureTarget = configGetDouble("target", 31); - temperatureMaxOvershoot = configGetDouble("over", 5); +void configLoaded() { + proportional = configGetDouble("p", PID_DEFAULT_P); + integral = configGetDouble("i", PID_DEFAULT_I); + derivative = configGetDouble("d", PID_DEFAULT_D); + temperatureTarget = configGetDouble("target", PID_DEFAULT_TARGET); + temperatureOver = configGetDouble("over", PID_DEFAULT_OVER); pid.setCoefficients(proportional, integral, derivative); -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/Test.cpp b/src/Test.cpp new file mode 100644 index 0000000..f61af92 --- /dev/null +++ b/src/Test.cpp @@ -0,0 +1,23 @@ +#if defined(TEST8266) || defined(TEST32) + +#include +#include "config.h" + +void patrixSetup() { + +} + +void patrixLoop() { + +} + +void configLoaded() { + +} + +bool patrix_command(char *first) { + return false; +} + + +#endif \ No newline at end of file