Added core frost functionality
This commit is contained in:
parent
f2af9c3fda
commit
7081391f63
|
@ -124,8 +124,8 @@
|
|||
#define RX_DATA_TIMOUT 50
|
||||
|
||||
const int FirmwareRevision = 31;
|
||||
const int FirmwareSubRevision = 6;
|
||||
const char* FirmwareDate = "27 Oct 2019";
|
||||
const int FirmwareSubRevision = 7;
|
||||
const char* FirmwareDate = "30 Oct 2019";
|
||||
|
||||
|
||||
#ifdef ESP32
|
||||
|
@ -149,6 +149,7 @@ bool validateFrame(const CProtocol& frame, const char* name);
|
|||
void checkDisplayUpdate();
|
||||
void checkDebugCommands();
|
||||
void manageCyclicMode();
|
||||
void manageFrostMode();
|
||||
bool preemptCyclicMode();
|
||||
void doStreaming();
|
||||
void heaterOn();
|
||||
|
@ -851,6 +852,7 @@ void loop()
|
|||
FilteredSamples.AmbientTemp.update(fTemperature);
|
||||
|
||||
manageCyclicMode();
|
||||
manageFrostMode();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -941,6 +943,31 @@ void manageCyclicMode()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void manageFrostMode()
|
||||
{
|
||||
uint8_t engage = NVstore.getUserSettings().FrostOn;
|
||||
if(engage) {
|
||||
float deltaT = getTemperatureSensor() - engage;
|
||||
int heaterState = getHeaterInfo().getRunState();
|
||||
if(deltaT < 0) {
|
||||
if(heaterState == 0) {
|
||||
RTC_Store.setFrostOn(true);
|
||||
DebugPort.printf("FROST MODE: Starting heater, < %d`C\r\n", engage);
|
||||
heaterOn();
|
||||
}
|
||||
}
|
||||
uint8_t rise = NVstore.getUserSettings().FrostRise;
|
||||
if(deltaT > rise) {
|
||||
if(RTC_Store.getFrostOn()) {
|
||||
DebugPort.printf("FROST MODE: Stopping heater, > %d`C\r\n", engage+rise);
|
||||
heaterOff();
|
||||
RTC_Store.setFrostOn(false); // cancel active frost mode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool preemptCyclicMode()
|
||||
{
|
||||
const sCyclicThermostat& cyclic = NVstore.getUserSettings().cyclic;
|
||||
|
@ -993,6 +1020,7 @@ void requestOn()
|
|||
{
|
||||
if(bHasHtrData && (0 == SmartError.checkVolts(FilteredSamples.FastipVolts.getValue(), FilteredSamples.FastGlowAmps.getValue()))) {
|
||||
RTC_Store.setCyclicEngaged(true); // for cyclic mode
|
||||
RTC_Store.setFrostOn(false); // cancel frost mode
|
||||
if(!preemptCyclicMode()) { // only start if below cyclic threshold when enabled
|
||||
heaterOn();
|
||||
}
|
||||
|
@ -1003,6 +1031,7 @@ void requestOff()
|
|||
{
|
||||
heaterOff();
|
||||
RTC_Store.setCyclicEngaged(false); // for cyclic mode
|
||||
RTC_Store.setFrostOn(false); // cancel active frost mode
|
||||
}
|
||||
|
||||
void heaterOn()
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "../Utility/NVStorage.h"
|
||||
#include "../Protocol/Protocol.h"
|
||||
#include "../Utility/TempSense.h"
|
||||
#include "../RTC/RTCStore.h"
|
||||
|
||||
#define MAXIFONT tahoma_24ptFontInfo
|
||||
|
||||
|
@ -270,7 +271,7 @@ CBasicScreen::keyHandler(uint8_t event)
|
|||
if(event & key_Centre) {
|
||||
if(NVstore.getUserSettings().menuMode < 2) {
|
||||
int runstate = getHeaterInfo().getRunStateEx();
|
||||
if(runstate) { // running, including cyclic mode idle
|
||||
if(runstate && !RTC_Store.getFrostOn()) { // running, including cyclic mode idle
|
||||
if(repeatCount > 5) {
|
||||
repeatCount = -1;
|
||||
requestOff();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "../RTC/Clock.h"
|
||||
#include "../Protocol/Protocol.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../RTC/RTCStore.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -135,7 +136,7 @@ CClockScreen::keyHandler(uint8_t event)
|
|||
if(event & key_Centre) {
|
||||
if(NVstore.getUserSettings().menuMode < 2) {
|
||||
int runstate = getHeaterInfo().getRunStateEx();
|
||||
if(runstate) { // running, including cyclic mode idle
|
||||
if(runstate && !RTC_Store.getFrostOn()) { // running, including cyclic mode idle
|
||||
if(_keyRepeatCount > 5) {
|
||||
_keyRepeatCount = -1;
|
||||
requestOff();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "../Protocol/Protocol.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../Utility/FuelGauge.h"
|
||||
#include "../RTC/RTCStore.h"
|
||||
|
||||
|
||||
#define MINIFONT miniFontInfo
|
||||
|
@ -217,7 +218,7 @@ CDetailedScreen::keyHandler(uint8_t event)
|
|||
|
||||
if(event & key_Centre) {
|
||||
int runstate = getHeaterInfo().getRunStateEx();
|
||||
if(runstate) { // running, including cyclic mode idle
|
||||
if(runstate && !RTC_Store.getFrostOn()) { // running, including cyclic mode idle
|
||||
if(_keyRepeatCount > 5) {
|
||||
_keyRepeatCount = -1; // prevent double handling
|
||||
requestOff();
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "../RTC/TimerManager.h"
|
||||
#include "../Protocol/SmartError.h"
|
||||
#include "../Utility/DataFilter.h"
|
||||
#include "../RTC/RTCStore.h"
|
||||
|
||||
|
||||
#define MINIFONT miniFontInfo
|
||||
|
@ -329,6 +330,11 @@ CScreenHeader::showBatteryIcon(float voltage)
|
|||
int
|
||||
CScreenHeader::showTimers()
|
||||
{
|
||||
if(RTC_Store.getFrostOn()) {
|
||||
int xPos = X_TIMER_ICON;
|
||||
_drawBitmap(xPos, Y_TIMER_ICON, frostIconInfo);
|
||||
return 0;
|
||||
}
|
||||
int nextTimer = CTimerManager::getNextTimer(); // timer ID and repeat flag info of next scheduled timer
|
||||
if(nextTimer) {
|
||||
int xPos = X_TIMER_ICON;
|
||||
|
@ -358,12 +364,21 @@ CScreenHeader::showTimers()
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
_display.fillRect(X_TIMER_ICON-3, Y_TIMER_ICON, TimerIconInfo.width+3, TimerIconInfo.height, BLACK); // erase icon
|
||||
_display.fillRect(X_TIMER_ICON-3, Y_TIMER_ICON, TimerIconInfo.width+3, 13, BLACK); // erase icon
|
||||
_display.fillRect(X_TIMER_ICON-5, Y_TIMER_ICON+12, 21, 5, BLACK); // erase annotation
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CScreenHeader::showFrost()
|
||||
{
|
||||
if(RTC_Store.getFrostOn()) {
|
||||
int xPos = X_TIMER_ICON;
|
||||
_drawBitmap(xPos, Y_TIMER_ICON, frostIconInfo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CScreenHeader::showTime()
|
||||
|
|
|
@ -54,6 +54,7 @@ protected:
|
|||
void showBatteryIcon(float voltage);
|
||||
int showTimers();
|
||||
virtual void showTime(); // x location depends upon how many timers are active
|
||||
bool showFrost();
|
||||
void showHeaderDetail(bool state) { _hdrDetail = state; };
|
||||
public:
|
||||
CScreenHeader(C128x64_OLED& disp, CScreenManager& mgr);
|
||||
|
|
|
@ -1392,3 +1392,26 @@ const uint8_t PROGMEM threshIcon[] =
|
|||
|
||||
const BITMAP_INFO threshIconInfo(9, 9, threshIcon);
|
||||
|
||||
//
|
||||
// Image data for frost
|
||||
//
|
||||
|
||||
const uint8_t PROGMEM frostIcon[] =
|
||||
{
|
||||
0x15, 0x00, // # # #
|
||||
0x0A, 0x00, // # #
|
||||
0xA4, 0xA0, // # # # # #
|
||||
0x44, 0x40, // # # #
|
||||
0xA4, 0xA0, // # # # # #
|
||||
0x15, 0x00, // # # #
|
||||
0x0E, 0x00, // ###
|
||||
0x15, 0x00, // # # #
|
||||
0xA4, 0xA0, // # # # # #
|
||||
0x44, 0x40, // # # #
|
||||
0xA4, 0xA0, // # # # # #
|
||||
0x0A, 0x00, // # #
|
||||
0x15, 0x00, // # # #
|
||||
};
|
||||
|
||||
const BITMAP_INFO frostIconInfo(11, 13, frostIcon);
|
||||
|
||||
|
|
|
@ -159,3 +159,5 @@ extern const BITMAP_INFO algIconInfo;
|
|||
|
||||
extern const BITMAP_INFO passwordIconInfo;
|
||||
extern const BITMAP_INFO threshIconInfo;
|
||||
extern const BITMAP_INFO frostIconInfo;
|
||||
|
||||
|
|
|
@ -154,6 +154,20 @@ CRTC_Store::getDesiredPump()
|
|||
return _demandPump;
|
||||
}
|
||||
|
||||
void
|
||||
CRTC_Store::setFrostOn(bool state)
|
||||
{
|
||||
_frostOn = state;
|
||||
_PackAndSaveByte5();
|
||||
}
|
||||
|
||||
bool
|
||||
CRTC_Store::getFrostOn()
|
||||
{
|
||||
_ReadAndUnpackByte5();
|
||||
return _frostOn;
|
||||
}
|
||||
|
||||
void
|
||||
CRTC_Store::resetRunTime()
|
||||
{
|
||||
|
@ -230,6 +244,7 @@ CRTC_Store::_ReadAndUnpackByte5()
|
|||
uint8_t NVval = 0;
|
||||
Clock.readData((uint8_t*)&NVval, 1, 5);
|
||||
_demandPump = NVval & 0x3f;
|
||||
_frostOn = (NVval & 0x40) != 0;
|
||||
_accessed[2] = true;
|
||||
DebugPort.printf("RTC_Store - read byte5: pump=%d\r\n", _demandPump);
|
||||
}
|
||||
|
@ -239,6 +254,8 @@ void
|
|||
CRTC_Store::_PackAndSaveByte5()
|
||||
{
|
||||
uint8_t NVval = (_demandPump & 0x3f);
|
||||
NVval |= _frostOn ? 0x40 : 0;
|
||||
|
||||
Clock.saveData((uint8_t*)&NVval, 1, 5);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ class CRTC_Store {
|
|||
bool _BootInit; // Byte4[6]
|
||||
bool _CyclicEngaged; // Byte4[7]
|
||||
uint8_t _demandPump; // Byte5[0..5]
|
||||
bool _frostOn; // Byte5[6]
|
||||
uint8_t _RunTime; // Byte6[0..4]
|
||||
uint8_t _GlowTime; // Byte6[5..7]
|
||||
void _ReadAndUnpackByte4();
|
||||
|
@ -61,6 +62,8 @@ public:
|
|||
int getGlowTime();
|
||||
int getMaxGlowTime() const { return 8; };
|
||||
int getMaxRunTime() const { return 32; };
|
||||
void setFrostOn(bool state);
|
||||
bool getFrostOn();
|
||||
};
|
||||
|
||||
extern CRTC_Store RTC_Store;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "Clock.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../Utility/helpers.h"
|
||||
#include "../RTC/RTCStore.h"
|
||||
|
||||
// main array to hold information of which timer is active at any particular minute of the week
|
||||
// LSBs are used for the timerID + 1
|
||||
|
@ -271,7 +272,9 @@ CTimerManager::manageTime(int _hour, int _minute, int _dow)
|
|||
}
|
||||
else {
|
||||
DebugPort.println("End of timer interval, stopping heater");
|
||||
requestOff();
|
||||
// if(!RTC_Store.getFrostOn() && !RTC_Store.getCyclicEngaged())
|
||||
if(!RTC_Store.getFrostOn())
|
||||
requestOff();
|
||||
retval = 2;
|
||||
}
|
||||
_activeTimer = newID;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "DebugPort.h"
|
||||
#include "../Protocol/Protocol.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../RTC/RTCStore.h"
|
||||
|
||||
const int BREATHINTERVAL = 45;
|
||||
const int FADEAMOUNT = 3;
|
||||
|
@ -122,7 +123,7 @@ void
|
|||
CGPIOin1::_doStartStop(bool active)
|
||||
{
|
||||
if(active) {
|
||||
if(getHeaterInfo().getRunStateEx())
|
||||
if(getHeaterInfo().getRunStateEx() && !RTC_Store.getFrostOn())
|
||||
requestOff();
|
||||
else
|
||||
requestOn();
|
||||
|
|
|
@ -216,6 +216,8 @@ bool makeJSONStringEx(CModerator& moderator, char* opStr, int len)
|
|||
bSend |= moderator.addJson("CyclicTemp", getDemandDegC(), root); // actual pivot point for cyclic mode
|
||||
bSend |= moderator.addJson("CyclicOff", stop, root); // threshold of over temp for cyclic mode
|
||||
bSend |= moderator.addJson("CyclicOn", NVstore.getUserSettings().cyclic.Start, root); // threshold of under temp for cyclic mode
|
||||
bSend |= moderator.addJson("FrostOn", NVstore.getUserSettings().FrostOn, root); // temp drops below this, auto start - 0 = disable
|
||||
bSend |= moderator.addJson("FrostRise", NVstore.getUserSettings().FrostRise, root); // temp rise in frost mode till auto off
|
||||
bSend |= moderator.addJson("PumpCount", RTC_Store.getFuelGauge(), root); // running count of pump strokes
|
||||
bSend |= moderator.addJson("PumpCal", NVstore.getHeaterTuning().pumpCal, root); // mL/stroke
|
||||
bSend |= moderator.addJson("LowVoltCutout", NVstore.getHeaterTuning().getLVC(), root); // low voltage cutout
|
||||
|
@ -283,6 +285,8 @@ bool makeJSONStringGPIO(CModerator& moderator, char* opStr, int len)
|
|||
bSend |= moderator.addJson("GPmodeIn2", GPIOin2Names[info.in2Mode], root);
|
||||
bSend |= moderator.addJson("GPmodeOut1", GPIOout1Names[info.out1Mode], root);
|
||||
bSend |= moderator.addJson("GPmodeOut2", GPIOout2Names[info.out2Mode], root);
|
||||
bSend |= moderator.addJson("GPOutThr1", NVstore.getUserSettings().GPIO.thresh[0], root);
|
||||
bSend |= moderator.addJson("GPOutThr2", NVstore.getUserSettings().GPIO.thresh[1], root);
|
||||
bSend |= moderator.addJson("GPmodeAnlg", GPIOalgNames[info.algMode], root);
|
||||
bSend |= moderator.addJson("ExtThermoTmout", (uint32_t)NVstore.getUserSettings().ExtThermoTimeout, root);
|
||||
const char* stop = getExternalThermostatHoldTime();
|
||||
|
|
|
@ -379,6 +379,8 @@ sUserSettings::load()
|
|||
}
|
||||
validatedLoad("thermoWindow", ThermostatWindow, 1.0f, 0.2f, 10.f);
|
||||
DebugPort.printf("2) Window = %f\r\n", ThermostatWindow);
|
||||
validatedLoad("frostOn", FrostOn, 0, u8inBounds, 0, 10);
|
||||
validatedLoad("frostRise", FrostRise, 5, u8inBounds, 0, 20);
|
||||
validatedLoad("enableWifi", enableWifi, 1, u8inBounds, 0, 1);
|
||||
validatedLoad("enableOTA", enableOTA, 0, u8inBounds, 0, 1);
|
||||
validatedLoad("cyclicStop", cyclic.Stop, 0, s8inBounds, 0, 10);
|
||||
|
@ -444,6 +446,8 @@ sUserSettings::save()
|
|||
preferences.putUChar("degF", degF);
|
||||
preferences.putUChar("thermoMethod", ThermostatMethod);
|
||||
preferences.putFloat("thermoWindow", ThermostatWindow);
|
||||
preferences.putUChar("frostOn", FrostOn);
|
||||
preferences.putUChar("frostRise", FrostRise);
|
||||
preferences.putUChar("enableWifi", enableWifi);
|
||||
preferences.putUChar("enableOTA", enableOTA);
|
||||
preferences.putChar("cyclicStop", cyclic.Stop);
|
||||
|
|
|
@ -284,6 +284,8 @@ struct sUserSettings : public CESP32_NVStorage {
|
|||
uint8_t degF;
|
||||
uint8_t ThermostatMethod; // 0: standard heater, 1: Narrow Hysterisis, 2:Managed Hz mode
|
||||
float ThermostatWindow;
|
||||
uint8_t FrostOn;
|
||||
uint8_t FrostRise;
|
||||
uint8_t useThermostat;
|
||||
uint8_t enableWifi;
|
||||
uint8_t enableOTA;
|
||||
|
@ -324,6 +326,8 @@ struct sUserSettings : public CESP32_NVStorage {
|
|||
degF = 0;
|
||||
ThermostatMethod = 0;
|
||||
ThermostatWindow = 1.0;
|
||||
FrostOn = 0;
|
||||
FrostRise = 5;
|
||||
useThermostat = 1;
|
||||
enableWifi = 1;
|
||||
enableOTA = 0;
|
||||
|
@ -351,6 +355,8 @@ struct sUserSettings : public CESP32_NVStorage {
|
|||
degF = rhs.degF;
|
||||
ThermostatMethod = rhs.ThermostatMethod;
|
||||
ThermostatWindow = rhs.ThermostatWindow;
|
||||
FrostOn = rhs.FrostOn;
|
||||
FrostRise = rhs.FrostRise;
|
||||
useThermostat = rhs.useThermostat;
|
||||
enableWifi = rhs.enableWifi;
|
||||
enableOTA = rhs.enableOTA;
|
||||
|
|
|
@ -309,6 +309,22 @@ void DecodeCmd(const char* cmd, String& payload)
|
|||
else if(strcmp("GPin2", cmd) == 0) {
|
||||
simulateGPIOin(payload.toInt() ? 0x02 : 0x00); // simulate key 2 press
|
||||
}
|
||||
else if(strcmp("GPOutThr1", cmd) == 0) {
|
||||
sUserSettings us = NVstore.getUserSettings();
|
||||
us.GPIO.thresh[0] = payload.toInt(); // 0 = disable; < 0, active if less than abs(val); > 0, active if over val
|
||||
if(INBOUNDS(us.GPIO.thresh[0], -50, 50)) {
|
||||
NVstore.setUserSettings(us);
|
||||
NVstore.save();
|
||||
}
|
||||
}
|
||||
else if(strcmp("GPOutThr2", cmd) == 0) {
|
||||
sUserSettings us = NVstore.getUserSettings();
|
||||
us.GPIO.thresh[1] = payload.toInt(); // 0 = disable; < 0, active if less than abs(val); > 0, active if over val
|
||||
if(INBOUNDS(us.GPIO.thresh[1], -50, 50)) {
|
||||
NVstore.setUserSettings(us);
|
||||
NVstore.save();
|
||||
}
|
||||
}
|
||||
else if(strcmp("JSONpack", cmd) == 0) {
|
||||
sUserSettings us = NVstore.getUserSettings();
|
||||
uint8_t packed = payload.toInt() ? 0x00 : 0x01;
|
||||
|
@ -395,5 +411,21 @@ void DecodeCmd(const char* cmd, String& payload)
|
|||
else if(strcmp("SysHourMeters", cmd) == 0) {
|
||||
pHourMeter->resetHard();
|
||||
}
|
||||
else if(strcmp("FrostOn", cmd) == 0) {
|
||||
sUserSettings us = NVstore.getUserSettings();
|
||||
us.FrostOn = payload.toInt();
|
||||
if(INBOUNDS(us.FrostOn, 0, 30)) {
|
||||
NVstore.setUserSettings(us);
|
||||
NVstore.save();
|
||||
}
|
||||
}
|
||||
else if(strcmp("FrostRise", cmd) == 0) {
|
||||
sUserSettings us = NVstore.getUserSettings();
|
||||
us.FrostRise = payload.toInt();
|
||||
if(INBOUNDS(us.FrostRise, 1, 30)) {
|
||||
NVstore.setUserSettings(us);
|
||||
NVstore.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue