From 2fc020ae6c016c375f3aeefab1822ccf6146b12a Mon Sep 17 00:00:00 2001 From: rljonesau Date: Thu, 14 Mar 2019 21:52:59 +1100 Subject: [PATCH] Implemented mechanism for thermostat hysteresis. Need to build UI. --- Arduino/BTCDieselHeater/BTCDieselHeater.ino | 24 +++++-- .../BTCDieselHeater/src/OLED/BasicScreen.cpp | 8 +-- .../src/OLED/DetailedScreen.cpp | 6 +- .../BTCDieselHeater/src/Protocol/Protocol.cpp | 4 +- .../BTCDieselHeater/src/Protocol/Protocol.h | 2 +- .../BTCDieselHeater/src/Protocol/TxManage.cpp | 72 ++++++++++++++++++- .../BTCDieselHeater/src/Protocol/helpers.h | 4 +- Arduino/BTCDieselHeater/src/RTC/Timers.cpp | 6 +- Arduino/BTCDieselHeater/src/RTC/Timers.h | 6 +- .../BTCDieselHeater/src/Utility/BTC_JSON.cpp | 26 +++---- .../BTCDieselHeater/src/Utility/BTC_JSON.h | 4 +- .../BTCDieselHeater/src/Utility/NVStorage.cpp | 38 +++++++++- .../BTCDieselHeater/src/Utility/NVStorage.h | 7 +- 13 files changed, 165 insertions(+), 42 deletions(-) diff --git a/Arduino/BTCDieselHeater/BTCDieselHeater.ino b/Arduino/BTCDieselHeater/BTCDieselHeater.ino index 4d2b6cb..d257fe6 100644 --- a/Arduino/BTCDieselHeater/BTCDieselHeater.ino +++ b/Arduino/BTCDieselHeater/BTCDieselHeater.ino @@ -770,7 +770,6 @@ void loop() DS18B20holdoff = 2; fFilteredTemperature = -100; } - DefaultBTCParams.setTemperature_Actual((unsigned char)(fFilteredTemperature + 0.5)); // update [BTC] frame to send // Added DISABLE INTERRUPTS to test for parasitic fix. // portDISABLE_INTERRUPTS(); TempSensor.requestTemperatures(); // prep sensor for future reading @@ -891,7 +890,7 @@ int getSetTemp() bool reqThermoToggle() { - return setThermostatMode(getThermostatMode() ? 0 : 1); + return setThermostatMode(getThermostatModeActive() ? 0 : 1); } bool setThermostatMode(unsigned char val) @@ -904,9 +903,14 @@ bool setThermostatMode(unsigned char val) } -bool getThermostatMode() +bool getThermostatModeActive() { - return NVstore.getThermostatMode() != 0; + if(bHasOEMController) { + return getHeaterInfo().isThermostat(); + } + else { + return NVstore.getThermostatMode() != 0; + } } void checkDisplayUpdate() @@ -932,7 +936,17 @@ void reqPumpPrime(bool on) DefaultBTCParams.setPump_Prime(on); } -float getActualTemperature() +float getTemperatureDesired() +{ + if(bHasOEMController) { + return getHeaterInfo().getTemperature_Desired(); + } + else { + return NVstore.getDesiredTemperature(); + } +} + +float getTemperatureSensor() { return fFilteredTemperature; } diff --git a/Arduino/BTCDieselHeater/src/OLED/BasicScreen.cpp b/Arduino/BTCDieselHeater/src/OLED/BasicScreen.cpp index 7553994..2847764 100644 --- a/Arduino/BTCDieselHeater/src/OLED/BasicScreen.cpp +++ b/Arduino/BTCDieselHeater/src/OLED/BasicScreen.cpp @@ -54,7 +54,7 @@ CBasicScreen::show() char msg[20]; int xPos, yPos; - float fTemp = getActualTemperature(); + float fTemp = getTemperatureSensor(); if(fTemp > -80) { if(NVstore.getDegFMode()) { fTemp = fTemp * 9 / 5 + 32; @@ -110,8 +110,8 @@ CBasicScreen::show() long tDelta = millis() - _showSetMode; if(tDelta < 0) { // Show current heat demand setting - if(getHeaterInfo().isThermostat()) { - float fTemp = getHeaterInfo().getTemperature_Desired(); + if(getThermostatModeActive()) { + float fTemp = getTemperatureDesired(); if(NVstore.getDegFMode()) { fTemp = fTemp * 9 / 5 + 32; sprintf(msg, "Setpoint = %.0f`F", fTemp); @@ -191,7 +191,7 @@ CBasicScreen::keyHandler(uint8_t event) if(repeatCount > 2) { repeatCount = -1; // prevent double handling _showMode = millis() + 5000; - _nModeSel = getHeaterInfo().isThermostat() ? 0 : 1; + _nModeSel = getThermostatModeActive() ? 0 : 1; } } // hold UP to toggle degC/degF mode selection diff --git a/Arduino/BTCDieselHeater/src/OLED/DetailedScreen.cpp b/Arduino/BTCDieselHeater/src/OLED/DetailedScreen.cpp index 1b58719..e42c638 100644 --- a/Arduino/BTCDieselHeater/src/OLED/DetailedScreen.cpp +++ b/Arduino/BTCDieselHeater/src/OLED/DetailedScreen.cpp @@ -79,7 +79,7 @@ CDetailedScreen::show() { CScreenHeader::show(); - const char* c = String(getActualTemperature()).c_str(); + const char* c = String(getTemperatureSensor()).c_str(); int runstate = getHeaterInfo().getRunState();//HtrFrame.getRunState(); int errstate = getHeaterInfo().getErrState(); //HtrFrame.getErrState(); @@ -92,13 +92,13 @@ CDetailedScreen::show() float desiredT = 0; if((runstate && (runstate <= 5)) || _showTarget) { - if(getHeaterInfo().isThermostat()) + if(getThermostatModeActive()) desiredT = getHeaterInfo().getTemperature_Desired(); else desiredT = -getHeaterInfo().getPump_Fixed(); } - float fTemp = getActualTemperature(); + float fTemp = getTemperatureSensor(); showThermometer(desiredT, // read values from most recently sent [BTC] frame fTemp); diff --git a/Arduino/BTCDieselHeater/src/Protocol/Protocol.cpp b/Arduino/BTCDieselHeater/src/Protocol/Protocol.cpp index a4de339..c9cfaab 100644 --- a/Arduino/BTCDieselHeater/src/Protocol/Protocol.cpp +++ b/Arduino/BTCDieselHeater/src/Protocol/Protocol.cpp @@ -310,11 +310,9 @@ CProtocol::DebugReport(const char* hdr, const char* ftr) } void -CProtocol::setThermostatMode(unsigned on) +CProtocol::setThermostatModeProtocol(unsigned on) { Controller.OperatingMode = on ? 0x32 : 0xCD; - if(!on) - setTemperature_Actual(0); // if using fixed mode, actual must be reported as 0 }; void diff --git a/Arduino/BTCDieselHeater/src/Protocol/Protocol.h b/Arduino/BTCDieselHeater/src/Protocol/Protocol.h index 8d49e28..bcc1e98 100644 --- a/Arduino/BTCDieselHeater/src/Protocol/Protocol.h +++ b/Arduino/BTCDieselHeater/src/Protocol/Protocol.h @@ -183,7 +183,7 @@ public: unsigned char getTemperature_Min() const { return Controller.MinTemperature; }; unsigned char getTemperature_Max() const { return Controller.MaxTemperature; }; unsigned char getTemperature_Actual() const { return Controller.ActualTemperature; }; - void setThermostatMode(unsigned on); + void setThermostatModeProtocol(unsigned on); bool isThermostat() const { return Controller.OperatingMode == 0x32; }; // glow plug float getGlowPlug_Current() const; // glow plug current diff --git a/Arduino/BTCDieselHeater/src/Protocol/TxManage.cpp b/Arduino/BTCDieselHeater/src/Protocol/TxManage.cpp index 43191c0..7829bb4 100644 --- a/Arduino/BTCDieselHeater/src/Protocol/TxManage.cpp +++ b/Arduino/BTCDieselHeater/src/Protocol/TxManage.cpp @@ -21,6 +21,7 @@ #include "TxManage.h" #include "../Utility/NVStorage.h" +#include "../Protocol/helpers.h" extern void DebugReportFrame(const char* hdr, const CProtocol&, const char* ftr); @@ -117,8 +118,77 @@ CTxManage::PrepareFrame(const CProtocol& basisFrame, bool isBTCmaster) m_TxFrame.setFan_Max(NVstore.getFmax()); m_TxFrame.setPump_Min(NVstore.getPmin()); m_TxFrame.setPump_Max(NVstore.getPmax()); - m_TxFrame.setThermostatMode(NVstore.getThermostatMode()); + + float tActual = getTemperatureSensor(); + uint8_t u8Temp = (uint8_t)(tActual); + m_TxFrame.setTemperature_Actual(u8Temp); // use current temp, for now m_TxFrame.setTemperature_Desired(NVstore.getDesiredTemperature()); + + if(NVstore.getThermostatMode()) { + uint8_t ThermoMode = NVstore.getThermostatMethodMode(); // get the METHOD of thermostat control + float Hysteresis = NVstore.getThermostatMethodHysteresis(); + float tCurrent = getTemperatureSensor(); + float tDesired = float(NVstore.getDesiredTemperature()); + float tDelta = tCurrent - tDesired; +#ifdef DEBUG_THERMOSTAT + DebugPort.print("Hysteresis = "); DebugPort.print(Hysteresis); DebugPort.print(" tCurrent = "); DebugPort.print(tCurrent); DebugPort.print(" tDesired = "); DebugPort.print(tDesired); DebugPort.print(" tDelta = "); DebugPort.println(tDelta); +#endif + switch(ThermoMode) { + case 0: // conventional heater controlled thermostat mode + m_TxFrame.setThermostatModeProtocol(1); // using heater thermostat control + u8Temp = (uint8_t)(tActual + 0.5); + m_TxFrame.setTemperature_Actual(u8Temp); +#ifdef DEBUG_THERMOSTAT + DebugPort.print("Conventional thermostat mode: tActual = "); DebugPort.println(u8Temp); +#endif + break; + case 1: // heater controlled thermostat mode - BUT actual temp is tweaked via a changed hysteresis + m_TxFrame.setThermostatModeProtocol(1); // using heater thermostat control + u8Temp = (uint8_t)(tActual + 0.5); // use rounded actual unless within hysteresis window + if(fabs(tDelta) < Hysteresis) { + // hold at desired if inside hysteresis + u8Temp = NVstore.getDesiredTemperature(); + } + else if(fabs(tDelta) <= 1.0) { + // force outside if delta is <= 1 but greater than hysteresis + u8Temp = NVstore.getDesiredTemperature() + ((tDelta > 0) ? 1 : -1); + } + m_TxFrame.setTemperature_Actual(u8Temp); +#ifdef DEBUG_THERMOSTAT + DebugPort.print("Heater hysteresis thermostat mode: tActual = "); DebugPort.println(u8Temp); +#endif + break; + case 2: // BTC controlled thermostat mode + // map Hysteresis to a Hz value, + // Hz mode however uses the desired temperature field, somewhere between 8 - 35 for min/max + // so create a desired "temp" according the the current hystersis + tDelta /= Hysteresis; // convert tDelta to fraction of hysteresis (CAUTION - may be > +-1 !) +#ifdef DEBUG_THERMOSTAT + DebugPort.print("Controller hysteresis thermostat mode: Fraction = "); DebugPort.print(tDelta); +#endif + Hysteresis = (m_TxFrame.getTemperature_Max() + m_TxFrame.getTemperature_Min()) * 0.5; // midpoint - tDelta = 0 hinges here + tDelta *= (m_TxFrame.getTemperature_Max() - Hysteresis); // linear offset from setpoint + Hysteresis -= tDelta; // lower Hz when over temp, higher Hz when under! + // bounds limit - recall original tDelta was NOT managed prior! + LOWERLIMIT(Hysteresis, m_TxFrame.getTemperature_Min()); + UPPERLIMIT(Hysteresis, m_TxFrame.getTemperature_Max()); + // apply modifed desired temperature (works in conjunction with thermostatmode = 0!) + u8Temp = (uint8_t)(Hysteresis + 0.5); + m_TxFrame.setTemperature_Desired(u8Temp); + m_TxFrame.setThermostatModeProtocol(0); // direct heater to use Hz Mode + m_TxFrame.setTemperature_Actual(0); // must force actual to 0 for Hz mode +#ifdef DEBUG_THERMOSTAT + DebugPort.print(" tDesired (pseudo Hz demand) = "); DebugPort.println(u8Temp); +#endif + break; + } + } + else { + m_TxFrame.setThermostatModeProtocol(0); // not using any form of thermostat control + m_TxFrame.setTemperature_Actual(0); // must force actual to 0 for Hz mode + } +// m_TxFrame.setThermostatMode(NVstore.getThermostatMode()); + m_TxFrame.Controller.OperatingVoltage = NVstore.getSysVoltage(); m_TxFrame.Controller.FanSensor = NVstore.getFanSensor(); m_TxFrame.Controller.GlowDrive = NVstore.getGlowDrive(); diff --git a/Arduino/BTCDieselHeater/src/Protocol/helpers.h b/Arduino/BTCDieselHeater/src/Protocol/helpers.h index bfedb63..761ec0c 100644 --- a/Arduino/BTCDieselHeater/src/Protocol/helpers.h +++ b/Arduino/BTCDieselHeater/src/Protocol/helpers.h @@ -30,8 +30,10 @@ extern bool reqTempDelta(int delta); extern bool reqTemp(unsigned char newTemp); extern bool reqThermoToggle(); extern bool setThermostatMode(unsigned char); +extern bool getThermostatModeActive(); // OEM: actual mode from blue wire, BTC: or our NV extern void reqPumpPrime(bool on); -extern float getActualTemperature(); +float getTemperatureDesired(); // OEM: the advertised value, BTC our setpoint +extern float getTemperatureSensor(); extern int getSetTemp(); extern void setPumpMin(float); extern void setPumpMax(float); diff --git a/Arduino/BTCDieselHeater/src/RTC/Timers.cpp b/Arduino/BTCDieselHeater/src/RTC/Timers.cpp index 27ae184..651ca67 100644 --- a/Arduino/BTCDieselHeater/src/RTC/Timers.cpp +++ b/Arduino/BTCDieselHeater/src/RTC/Timers.cpp @@ -25,7 +25,7 @@ #include "BTCDateTime.h" -void decodeTimerDays(const char* ipStr) +void decodeJSONTimerDays(const char* ipStr) { char dayInfo[32]; int timerIdx; @@ -53,7 +53,7 @@ void decodeTimerDays(const char* ipStr) } -void decodeTimerTime(int stop, const char* ipStr) +void decodeJSONTimerTime(int stop, const char* ipStr) { int hour, min; int timerIdx; @@ -75,7 +75,7 @@ void decodeTimerTime(int stop, const char* ipStr) } } -void decodeTimerNumeric(int valID, const char* ipStr) +void decodeJSONTimerNumeric(int valID, const char* ipStr) { int value; int timerIdx; diff --git a/Arduino/BTCDieselHeater/src/RTC/Timers.h b/Arduino/BTCDieselHeater/src/RTC/Timers.h index 013dd95..ff47469 100644 --- a/Arduino/BTCDieselHeater/src/RTC/Timers.h +++ b/Arduino/BTCDieselHeater/src/RTC/Timers.h @@ -81,8 +81,8 @@ struct sTimer { }; const char* getTimerJSONStr(int timer, int param); -void decodeTimerDays(const char* str); -void decodeTimerTime(int stop, const char*); -void decodeTimerNumeric(int repeat, const char*); +void decodeJSONTimerDays(const char* str); +void decodeJSONTimerTime(int stop, const char*); +void decodeJSONTimerNumeric(int repeat, const char*); #endif diff --git a/Arduino/BTCDieselHeater/src/Utility/BTC_JSON.cpp b/Arduino/BTCDieselHeater/src/Utility/BTC_JSON.cpp index 5eb98ea..23ecd91 100644 --- a/Arduino/BTCDieselHeater/src/Utility/BTC_JSON.cpp +++ b/Arduino/BTCDieselHeater/src/Utility/BTC_JSON.cpp @@ -115,22 +115,22 @@ void interpretJsonCommand(char* pLine) } else if(strcmp("TimerDays", it->key) == 0) { // value encoded as "ID Days,Days" - decodeTimerDays(it->value.as()); + decodeJSONTimerDays(it->value.as()); } else if(strcmp("TimerStart", it->key) == 0) { // value encoded as "ID HH:MM" - decodeTimerTime(0, it->value.as()); + decodeJSONTimerTime(0, it->value.as()); } else if(strcmp("TimerStop", it->key) == 0) { // value encoded as "ID HH:MM" - decodeTimerTime(1, it->value.as()); + decodeJSONTimerTime(1, it->value.as()); } else if(strcmp("TimerRepeat", it->key) == 0) { // value encoded as "ID val" - decodeTimerNumeric(0, it->value.as()); + decodeJSONTimerNumeric(0, it->value.as()); } else if(strcmp("TimerTemp", it->key) == 0) { - decodeTimerNumeric(1, it->value.as()); + decodeJSONTimerNumeric(1, it->value.as()); } else if(strcmp("TimerConflict", it->key) == 0) { validateTimer(it->value.as()); @@ -152,22 +152,22 @@ void validateTimer(int ID) timerConflict = CTimerManager::conflictTest(ID); // check targeted timer against other timers - TimerModerator.reset(ID); // ensure we fully update client with our understanding of selected timer + TimerModerator.reset(ID); // ensure we update client with our (real) version of the selected timer } -bool makeJsonString(CModerator& moderator, char* opStr, int len) +bool makeJSONString(CModerator& moderator, char* opStr, int len) { StaticJsonBuffer<800> jsonBuffer; // create a JSON buffer on the stack JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to bool bSend = false; // reset should send flag - float tidyTemp = getActualTemperature(); + float tidyTemp = getTemperatureSensor(); tidyTemp = int(tidyTemp * 10) * 0.1f; // round to 0.1 resolution if(tidyTemp > -80) { bSend |= moderator.addJson("TempCurrent", tidyTemp, root); } - bSend |= moderator.addJson("TempDesired", getHeaterInfo().getTemperature_Desired(), root); + bSend |= moderator.addJson("TempDesired", getTemperatureDesired(), root); bSend |= moderator.addJson("TempMin", getHeaterInfo().getTemperature_Min(), root); bSend |= moderator.addJson("TempMax", getHeaterInfo().getTemperature_Max(), root); bSend |= moderator.addJson("TempBody", getHeaterInfo().getTemperature_HeatExchg(), root); @@ -175,7 +175,7 @@ bool makeJsonString(CModerator& moderator, char* opStr, int len) bSend |= moderator.addJson("RunString", getHeaterInfo().getRunStateStr(), root); // verbose it up! bSend |= moderator.addJson("ErrorState", getHeaterInfo().getErrState(), root ); bSend |= moderator.addJson("ErrorString", getHeaterInfo().getErrStateStrEx(), root); // verbose it up! - bSend |= moderator.addJson("Thermostat", getHeaterInfo().isThermostat(), root ); + bSend |= moderator.addJson("Thermostat", getThermostatModeActive(), root ); bSend |= moderator.addJson("PumpFixed", getHeaterInfo().getPump_Fixed(), root ); bSend |= moderator.addJson("PumpMin", getHeaterInfo().getPump_Min(), root ); bSend |= moderator.addJson("PumpMax", getHeaterInfo().getPump_Max(), root ); @@ -204,7 +204,7 @@ bool makeJsonString(CModerator& moderator, char* opStr, int len) // timer // Only timer parameters that have changed will be sent, after reset the typical string will be // {"TimerStart":XX:XX,"TimerStop":XX:XX,"TimerDays":XX,"TimerRepeat":X} -bool makeJsonTimerString(int channel, char* opStr, int len) +bool makeJSONTimerString(int channel, char* opStr, int len) { StaticJsonBuffer<800> jsonBuffer; // create a JSON buffer on the stack JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to @@ -229,7 +229,7 @@ void updateJSONclients(bool report) // update general parameters char jsonStr[800]; { - if(makeJsonString(JSONmoderator, jsonStr, sizeof(jsonStr))) { + if(makeJSONString(JSONmoderator, jsonStr, sizeof(jsonStr))) { if (report) { DebugPort.print("JSON send: "); DebugPort.println(jsonStr); } @@ -241,7 +241,7 @@ void updateJSONclients(bool report) bool bNewTimerInfo = false; for(int tmr=0; tmr<14; tmr++) { - if(makeJsonTimerString(tmr, jsonStr, sizeof(jsonStr))) { + if(makeJSONTimerString(tmr, jsonStr, sizeof(jsonStr))) { if (report) { DebugPort.print("JSON send: "); DebugPort.println(jsonStr); } diff --git a/Arduino/BTCDieselHeater/src/Utility/BTC_JSON.h b/Arduino/BTCDieselHeater/src/Utility/BTC_JSON.h index e68bd07..c76a0a4 100644 --- a/Arduino/BTCDieselHeater/src/Utility/BTC_JSON.h +++ b/Arduino/BTCDieselHeater/src/Utility/BTC_JSON.h @@ -27,8 +27,8 @@ extern char defaultJSONstr[64]; -bool makeJsonString(CModerator& moderator, char* opStr, int len); -bool makeJsonTimerString(int channel, char* opStr, int len); +bool makeJSONString(CModerator& moderator, char* opStr, int len); +bool makeJSONTimerString(int channel, char* opStr, int len); void updateJSONclients(bool report); template diff --git a/Arduino/BTCDieselHeater/src/Utility/NVStorage.cpp b/Arduino/BTCDieselHeater/src/Utility/NVStorage.cpp index 689b4a5..1138b7b 100644 --- a/Arduino/BTCDieselHeater/src/Utility/NVStorage.cpp +++ b/Arduino/BTCDieselHeater/src/Utility/NVStorage.cpp @@ -28,12 +28,14 @@ bool s8inBounds(int8_t test, int8_t minLim, int8_t maxLim); bool u8Match2(uint8_t test, uint8_t test1, uint8_t test2); bool u16inBounds(uint16_t test, uint16_t minLim, uint16_t maxLim); bool s32inBounds(long test, long minLim, long maxLim); +bool thermoMethodinBounds(uint8_t test, uint8_t minLim, uint8_t maxLim); bool sNVStore::valid() { bool retval = true; retval &= (DimTime >= 0) && (DimTime < 300000); // 5 mins + retval &= (ThermostatMethod & 0x03) < 3; // only modes 0, 1 or 2 for(int i=0; i<2; i++) { retval &= timer[i].valid(); } @@ -48,6 +50,7 @@ sNVStore::init() timer[i].init(); } DimTime = 60000; // 1 minute + ThermostatMethod = 10 << 2; // 1 degree hysteresis, normal thermostat Heater.init(); } @@ -92,6 +95,18 @@ CHeaterStorage::getThermostatMode() return _calValues.Heater.ThermostatMode; } +unsigned char +CHeaterStorage::getThermostatMethodMode() +{ + return _calValues.ThermostatMethod & 0x03; +} + +float +CHeaterStorage::getThermostatMethodHysteresis() +{ + return float((_calValues.ThermostatMethod >> 2) & 0x3f) * 0.05f; // top 5 bits / 10, then / 2 +} + void CHeaterStorage::setPmin(float val) { @@ -130,6 +145,22 @@ CHeaterStorage::setThermostatMode(unsigned char val) _calValues.Heater.ThermostatMode = val; } +void +CHeaterStorage::setThermostatMethodMode(unsigned char val) +{ + _calValues.ThermostatMethod &= 0xF3; + _calValues.ThermostatMethod |= (val & 0x03); +} + +void +CHeaterStorage::setThermostatMethodHysteresis(float val) +{ + _calValues.ThermostatMethod &= 0x03; + int nVal = int(val * 10 + 0.5); + _calValues.ThermostatMethod |= ((nVal & 0x3F) << 2); +} + + void CHeaterStorage::setSystemVoltage(float fVal) { @@ -331,6 +362,8 @@ CESP32HeaterStorage::loadUI() preferences.begin("user", false); validatedLoad("dimTime", _calValues.DimTime, 60000, s32inBounds, 0, 600000); validatedLoad("degF", _calValues.degF, 0, u8inBounds, 0, 1); + validatedLoad("thermoMethod", _calValues.ThermostatMethod, (10 << 2), u8inBounds, 0, 2, 0x03); +// validatedLoad("thermoMethod", _calValues.ThermostatMethod, (10 << 2) + 0, u8inBounds, 0, 2); // TESTO!!!! preferences.end(); } @@ -340,14 +373,15 @@ CESP32HeaterStorage::saveUI() preferences.begin("user", false); preferences.putULong("dimTime", _calValues.DimTime); preferences.putUChar("degF", _calValues.degF); + preferences.putUChar("thermoMethod", _calValues.ThermostatMethod); preferences.end(); } bool -CESP32HeaterStorage::validatedLoad(const char* key, uint8_t& val, int defVal, std::function validator, int min, int max) +CESP32HeaterStorage::validatedLoad(const char* key, uint8_t& val, int defVal, std::function validator, int min, int max, uint8_t mask) { val = preferences.getUChar(key, defVal); - if(!validator(val, min, max)) { + if(!validator(val & mask, min, max)) { DebugPort.print("CESP32HeaterStorage::validatedLoad invalid read "); DebugPort.print(key); DebugPort.print("="); DebugPort.print(val); diff --git a/Arduino/BTCDieselHeater/src/Utility/NVStorage.h b/Arduino/BTCDieselHeater/src/Utility/NVStorage.h index 34d5215..78cc628 100644 --- a/Arduino/BTCDieselHeater/src/Utility/NVStorage.h +++ b/Arduino/BTCDieselHeater/src/Utility/NVStorage.h @@ -67,6 +67,7 @@ struct sNVStore { sHeater Heater; long DimTime; uint8_t degF; + uint8_t ThermostatMethod; // 0: standard heater, 1: Narrow Hysterisis, 2:Managed Hz mode sTimer timer[14]; bool valid(); void init(); @@ -103,6 +104,8 @@ public: unsigned short getFmax(); unsigned char getDesiredTemperature(); unsigned char getThermostatMode(); + unsigned char getThermostatMethodMode(); + float getThermostatMethodHysteresis(); unsigned char getSysVoltage(); unsigned char getFanSensor(); unsigned char getGlowDrive(); @@ -115,6 +118,8 @@ public: void setFmax(unsigned short val); void setDesiredTemperature(unsigned char val); void setThermostatMode(unsigned char val); + void setThermostatMethodMode(unsigned char val); + void setThermostatMethodHysteresis(float val); void setSystemVoltage(float fVal); void setFanSensor(unsigned char val); void setGlowDrive(unsigned char val); @@ -146,7 +151,7 @@ public: void loadUI(); void saveUI(); bool validatedLoad(const char* key, int8_t& val, int defVal, std::function validator, int min, int max); - bool validatedLoad(const char* key, uint8_t& val, int defVal, std::function validator, int min, int max); + bool validatedLoad(const char* key, uint8_t& val, int defVal, std::function validator, int min, int max, uint8_t mask=0xff); bool validatedLoad(const char* key, uint16_t& val, int defVal, std::function validator, int min, int max); bool validatedLoad(const char* key, long& val, long defVal, std::function validator, long min, long max); };