Implemented functionality to start & stop heater according to external thermostat input

This commit is contained in:
Ray Jones 2019-08-26 06:37:41 +10:00
parent f5a8c3c11e
commit e7bac339b5
10 changed files with 100 additions and 13 deletions

Binary file not shown.

View file

@ -1,5 +1,5 @@
REM Firmware
esptool.exe --chip esp32 --port COM16 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 boot_app0.bin 0x1000 bootloader_qio_80m.bin 0x10000 AfterburnerV3.0.3.bin 0x8000 Afterburner.partitions.bin
esptool.exe --chip esp32 --port COM16 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 boot_app0.bin 0x1000 bootloader_qio_80m.bin 0x10000 AfterburnerV3.0.4.bin 0x8000 Afterburner.partitions.bin
REM SPIFFS
esptool.exe --chip esp32 --port COM16 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_size detect 0x3d0000 spiffs.bin

View file

@ -15,10 +15,10 @@ board = esp32dev
framework = arduino
board_build.partitions = min_spiffs.csv
upload_speed = 921600
upload_port = 192.168.20.40
upload_protocol = espota
;upload_port = COM16
;upload_protocol = esptool
;upload_port = 192.168.20.40
;upload_protocol = espota
upload_port = COM16
upload_protocol = esptool
upload_flags =
--port=3232
monitor_speed = 115200

View file

@ -218,6 +218,9 @@ CScreenHeader::showBTicon()
if(getBluetoothClient().isConnected()) {
_drawBitmap(X_BT_ICON, Y_BT_ICON, BluetoothIconInfo, WHITE);
}
else {
_display.fillRect(X_BT_ICON, Y_BT_ICON, BluetoothIconInfo.width, BluetoothIconInfo.height, BLACK);
}
}
void

View file

@ -56,6 +56,7 @@ CThermostatModeScreen::onSelect()
_window = NVstore.getUserSettings().ThermostatWindow;
_thermoMode = NVstore.getUserSettings().ThermostatMethod;
_cyclicMode = NVstore.getUserSettings().cyclic;
_ExtHold = NVstore.getUserSettings().ExtThermoTimeout;
}
void
@ -98,6 +99,21 @@ CThermostatModeScreen::show()
}
if(modeStr)
_printMenuText(Column, Line3, modeStr, _rowSel == 4);
modeStr = "??";
if(_thermoMode == 3) {
switch(_ExtHold) {
case 0: modeStr = "Psv"; break;
case 60000: modeStr = "1 min"; break;
case 120000: modeStr = "2 min"; break;
case 300000: modeStr = "5 min"; break;
case 600000: modeStr = "10 min"; break;
case 900000: modeStr = "15 min"; break;
case 1200000: modeStr = "20 min"; break;
case 1800000: modeStr = "30 min"; break;
case 3600000: modeStr = "1 hour"; break;
}
_printMenuText(_display.width()-border, Line2, modeStr, _rowSel == 5, eRightJustify);
}
if(_cyclicMode.isEnabled()) {
float fTemp = _cyclicMode.Stop+1;
if(NVstore.getUserSettings().degF) {
@ -178,6 +194,10 @@ CThermostatModeScreen::animate()
if(pMsg)
_scrollMessage(56, pMsg, _scrollChar);
break;
case 5:
_display.drawFastHLine(0, 52, 128, WHITE);
pMsg = " External thermostat handling - start upon initial closure, stop the heater after the nominated period. ";
break;
}
return true;
}
@ -202,6 +222,7 @@ CThermostatModeScreen::keyHandler(uint8_t event)
case 1:
case 2:
case 3:
case 5:
_adjust(-1);
break;
case 10:
@ -220,6 +241,7 @@ CThermostatModeScreen::keyHandler(uint8_t event)
case 1:
case 2:
case 3:
case 5:
_adjust(+1);
break;
case 10:
@ -252,12 +274,17 @@ CThermostatModeScreen::keyHandler(uint8_t event)
_rowSel++;
UPPERLIMIT(_rowSel, 4);
break;
case 4:
if(_thermoMode == 3)
_rowSel++;
break;
case 10: // confirmed save
_enableStoringMessage();
settings = NVstore.getUserSettings();
settings.ThermostatMethod = _thermoMode;
settings.ThermostatWindow = _window;
settings.cyclic = _cyclicMode;
settings.ExtThermoTimeout = _ExtHold;
NVstore.setUserSettings(settings);
saveNV();
_rowSel = 0;
@ -275,6 +302,7 @@ CThermostatModeScreen::keyHandler(uint8_t event)
case 2:
case 3:
case 4:
case 5:
_rowSel = 10;
break;
}
@ -329,5 +357,19 @@ CThermostatModeScreen::_adjust(int dir)
wrap = getExternalThermostatModeActive() ? 3 : 2;
WRAPLIMITS(_thermoMode, 0, wrap);
break;
case 5:
switch(_ExtHold) {
case 0: _ExtHold = (dir > 0) ? 60000 : 0; break;
case 60000: _ExtHold = (dir > 0) ? 120000 : 0; break;
case 120000: _ExtHold = (dir > 0) ? 300000 : 60000; break;
case 300000: _ExtHold = (dir > 0) ? 600000 : 120000; break;
case 600000: _ExtHold = (dir > 0) ? 900000 : 300000; break;
case 900000: _ExtHold = (dir > 0) ? 1200000 : 600000; break;
case 1200000: _ExtHold = (dir > 0) ? 1800000 : 900000; break;
case 1800000: _ExtHold = (dir > 0) ? 3600000 : 1200000; break;
case 3600000: _ExtHold = (dir > 0) ? 3600000 : 1800000; break;
default: _ExtHold = 0; break;
}
break;
}
}

View file

@ -36,6 +36,7 @@ class CThermostatModeScreen : public CPasswordScreen
void _adjust(int dir);
float _window;
int _thermoMode;
unsigned long _ExtHold;
sCyclicThermostat _cyclicMode;
int _animateCount;
int _scrollChar;

View file

@ -24,6 +24,7 @@
#include <driver/adc.h>
#include "DebugPort.h"
#include "../Protocol/Protocol.h"
#include "../Utility/NVStorage.h"
const int BREATHINTERVAL = 45;
const int FADEAMOUNT = 3;
@ -61,6 +62,7 @@ const char* GPIOalgNames[] = {
CGPIOin1::CGPIOin1()
{
_Mode = Disabled;
_prevActive = false;
}
void
@ -77,11 +79,14 @@ CGPIOin1::Modes CGPIOin1::getMode() const
void
CGPIOin1::manage(bool active)
{
switch (_Mode) {
case Disabled: break;
case Start: _doStart(active); break;
case Run: _doRun(active); break;
case StartStop: _doStartStop(active); break;
if(_prevActive ^ active) {
switch (_Mode) {
case Disabled: break;
case Start: _doStart(active); break;
case Run: _doRun(active); break;
case StartStop: _doStartStop(active); break;
}
_prevActive = active;
}
}
@ -122,6 +127,8 @@ CGPIOin1::_doStartStop(bool active)
CGPIOin2::CGPIOin2()
{
_Mode = Disabled;
_prevActive = false;
_OffHoldoff = 0;
}
void
@ -148,8 +155,11 @@ CGPIOin2::manage(bool active)
void
CGPIOin2::_doStop(bool active)
{
if(active) {
requestOff();
if(_prevActive ^ active) {
if(active) {
requestOff();
}
_prevActive = active;
}
}
@ -158,6 +168,28 @@ CGPIOin2::_doStop(bool active)
void
CGPIOin2::_doThermostat(bool active)
{
// only if actually using thermostat input, and a timeout is defined do we perform heater start / stop functions
if((NVstore.getUserSettings().ThermostatMethod == 3) && NVstore.getUserSettings().ExtThermoTimeout) {
if(active && !_prevActive) { // initial switch on of thermostat input
DebugPort.println("starting heater due to thermostat contact closure");
requestOn(); // request heater to start upon closure of thermostat input
}
if(!active && _prevActive) { // initial switch off of thermostat input
_OffHoldoff = (millis() + NVstore.getUserSettings().ExtThermoTimeout) | 1;
DebugPort.printf("thermostat contact opened - will stop in %ldms\r\n", NVstore.getUserSettings().ExtThermoTimeout);
}
if(!active) {
if(_OffHoldoff) {
long tDelta = millis() - _OffHoldoff;
if(tDelta >= 0) {
DebugPort.println("stopping heater due to thermostat contact being open for required dwell");
requestOff(); // request heater to stop after thermostat input has stayed open for interval
_OffHoldoff = 0;
}
}
}
_prevActive = active;
}
// handling actually performed at Tx Manage for setting the fuel rate
}
@ -222,7 +254,6 @@ CGPIOin::manage()
_lastKey = newKey;
if(keyChange) {
simulateKey(newKey);
// record possible sub sample transients - JSON usage especially
if(keyChange & 0x01)
@ -230,6 +261,7 @@ CGPIOin::manage()
if(keyChange & 0x02)
_eventList[1].push_back(newKey & 0x02); // mask the channel bit
}
simulateKey(newKey);
}
void

View file

@ -50,6 +50,7 @@ public:
Modes getMode() const;
private:
Modes _Mode;
bool _prevActive;
void _doStart(bool active);
void _doRun(bool active);
void _doStartStop(bool active);
@ -69,6 +70,8 @@ public:
Modes getMode() const;
private:
Modes _Mode;
bool _prevActive;
unsigned long _OffHoldoff;
void _doStop(bool active);
void _doThermostat(bool active);
};

View file

@ -329,6 +329,7 @@ sUserSettings::load()
preferences.begin("user", false);
validatedLoad("dimTime", dimTime, 60000, -600000, 600000);
validatedLoad("menuTimeout", menuTimeout, 60000, 0, 300000);
validatedLoad("thermoTimeout", ExtThermoTimeout, 0, 0, 3600000);
validatedLoad("degF", degF, 0, u8inBounds, 0, 1);
validatedLoad("thermostat", useThermostat, 1, u8inBounds, 0, 1);
validatedLoad("thermoMethod", ThermostatMethod, 0, u8inBounds, 0, 255);
@ -395,6 +396,7 @@ sUserSettings::save()
preferences.begin("user", false);
preferences.putLong("dimTime", dimTime);
preferences.putLong("menuTimeout", menuTimeout);
preferences.putLong("thermoTimeout", ExtThermoTimeout);
preferences.putUChar("thermostat", useThermostat);
preferences.putUChar("degF", degF);
preferences.putUChar("thermoMethod", ThermostatMethod);

View file

@ -245,6 +245,7 @@ struct sMQTTparams : public CESP32_NVStorage {
struct sUserSettings : public CESP32_NVStorage {
long dimTime;
long menuTimeout;
long ExtThermoTimeout;
uint8_t degF;
uint8_t ThermostatMethod; // 0: standard heater, 1: Narrow Hysterisis, 2:Managed Hz mode
float ThermostatWindow;
@ -261,6 +262,7 @@ struct sUserSettings : public CESP32_NVStorage {
bool retval = true;
retval &= INBOUNDS(dimTime, -600000, 600000); // +/- 10 mins
retval &= INBOUNDS(menuTimeout, 0, 300000); // 5 mins
retval &= INBOUNDS(ExtThermoTimeout, 0, 3600000); // 1 hour
retval &= (degF == 0) || (degF == 1);
retval &= ThermostatMethod <= 3; // only modes 0, 1 or 2, 3
retval &= INBOUNDS(ThermostatWindow, 0.2f, 10.f);
@ -280,6 +282,7 @@ struct sUserSettings : public CESP32_NVStorage {
void init() {
dimTime = 60000;
menuTimeout = 60000;
ExtThermoTimeout = 0;
degF = 0;
ThermostatMethod = 0;
ThermostatWindow = 1.0;
@ -301,6 +304,7 @@ struct sUserSettings : public CESP32_NVStorage {
sUserSettings& operator=(const sUserSettings& rhs) {
dimTime = rhs.dimTime;
menuTimeout = rhs.menuTimeout;
ExtThermoTimeout = rhs.ExtThermoTimeout;
degF = rhs.degF;
ThermostatMethod = rhs.ThermostatMethod;
ThermostatWindow = rhs.ThermostatWindow;