added external pump control

This commit is contained in:
Yurii
2023-12-07 01:01:19 +03:00
parent 412740c5d2
commit dd293e9802
14 changed files with 299 additions and 112 deletions

View File

@@ -0,0 +1,29 @@
#pragma once
#include <WiFiManager.h>
class CheckboxParameter : public WiFiManagerParameter {
public:
const char* checked = "type=\"checkbox\" checked";
const char* noChecked = "type=\"checkbox\"";
const char* trueVal = "T";
CheckboxParameter(const char* id, const char* label, bool value) : WiFiManagerParameter("") {
init(id, label, String(value ? trueVal : "0").c_str(), 1, "", WFM_LABEL_AFTER);
}
const char* getValue() const override {
return trueVal;
}
void setValue(bool value) {
WiFiManagerParameter::setValue(value ? trueVal : "0", 1);
}
const char* getCustomHTML() const override {
return strcmp(WiFiManagerParameter::getValue(), trueVal) == 0 ? checked : noChecked;
}
bool getCheckboxValue() {
return strcmp(WiFiManagerParameter::getValue(), trueVal) == 0 ? true : false;
}
};

View File

@@ -0,0 +1,21 @@
#pragma once
#include <WiFiManager.h>
class DoubleParameter : public WiFiManagerParameter {
public:
DoubleParameter(const char* id, const char* label, double value, const uint8_t length = 10) : WiFiManagerParameter("") {
init(id, label, String(value, length - 1).c_str(), length, "", WFM_LABEL_DEFAULT);
}
double getValue() {
return atof(WiFiManagerParameter::getValue());
}
void setValue(double value, int length) {
WiFiManagerParameter::setValue(String(value, length - 1).c_str(), length);
}
void setValue(double value) {
setValue(value, getValueLength());
}
};

View File

@@ -0,0 +1,21 @@
#pragma once
#include <WiFiManager.h>
class IntParameter : public WiFiManagerParameter {
public:
IntParameter(const char* id, const char* label, int value, const uint8_t length = 10) : WiFiManagerParameter("") {
init(id, label, String(value).c_str(), length, "", WFM_LABEL_DEFAULT);
}
int getValue() {
return atoi(WiFiManagerParameter::getValue());
}
void setValue(int value, int length) {
WiFiManagerParameter::setValue(String(value).c_str(), length);
}
void setValue(int value) {
setValue(value, getValueLength());
}
};

View File

@@ -0,0 +1,8 @@
#pragma once
#include <WiFiManager.h>
class SeparatorParameter : public WiFiManagerParameter {
public:
SeparatorParameter() : WiFiManagerParameter("<hr>") {}
};

View File

@@ -0,0 +1,21 @@
#pragma once
#include <WiFiManager.h>
class ShortParameter : public WiFiManagerParameter {
public:
ShortParameter(const char* id, const char* label, short value, const uint8_t length = 10) : WiFiManagerParameter("") {
init(id, label, String(value).c_str(), length, "", WFM_LABEL_DEFAULT);
}
short getValue() {
return atoi(WiFiManagerParameter::getValue());
}
void setValue(short value, int length) {
WiFiManagerParameter::setValue(String(value).c_str(), length);
}
void setValue(short value) {
setValue(value, getValueLength());
}
};

View File

@@ -0,0 +1,21 @@
#pragma once
#include <WiFiManager.h>
class UnsignedIntParameter : public WiFiManagerParameter {
public:
UnsignedIntParameter(const char* id, const char* label, unsigned int value, const uint8_t length = 10) : WiFiManagerParameter("") {
init(id, label, String(value).c_str(), length, "", WFM_LABEL_DEFAULT);
}
unsigned int getValue() {
return (unsigned int) atoi(WiFiManagerParameter::getValue());
}
void setValue(unsigned int value, int length) {
WiFiManagerParameter::setValue(String(value).c_str(), length);
}
void setValue(unsigned int value) {
setValue(value, getValueLength());
}
};

View File

@@ -0,0 +1,21 @@
#pragma once
#include <WiFiManager.h>
class UnsignedShortParameter : public WiFiManagerParameter {
public:
UnsignedShortParameter(const char* id, const char* label, unsigned short value, const uint8_t length = 10) : WiFiManagerParameter("") {
init(id, label, String(value).c_str(), length, "", WFM_LABEL_DEFAULT);
}
unsigned short getValue() {
return (unsigned short) atoi(WiFiManagerParameter::getValue());
}
void setValue(unsigned short value, int length) {
WiFiManagerParameter::setValue(String(value).c_str(), length);
}
void setValue(unsigned short value) {
setValue(value, getValueLength());
}
};

View File

@@ -1,88 +0,0 @@
class IntParameter : public WiFiManagerParameter {
public:
IntParameter(const char* id, const char* label, int value, const uint8_t length = 10) : WiFiManagerParameter("") {
init(id, label, String(value).c_str(), length, "", WFM_LABEL_DEFAULT);
}
int getValue() {
return atoi(WiFiManagerParameter::getValue());
}
void setValue(int value, int length) {
WiFiManagerParameter::setValue(String(value).c_str(), length);
}
void setValue(int value) {
setValue(value, getValueLength());
}
};
class UnsignedIntParameter : public WiFiManagerParameter {
public:
UnsignedIntParameter(const char* id, const char* label, unsigned int value, const uint8_t length = 10) : WiFiManagerParameter("") {
init(id, label, String(value).c_str(), length, "", WFM_LABEL_DEFAULT);
}
unsigned int getValue() {
return (unsigned int) atoi(WiFiManagerParameter::getValue());
}
void setValue(unsigned int value, int length) {
WiFiManagerParameter::setValue(String(value).c_str(), length);
}
void setValue(unsigned int value) {
setValue(value, getValueLength());
}
};
class DoubleParameter : public WiFiManagerParameter {
public:
DoubleParameter(const char* id, const char* label, double value, const uint8_t length = 10) : WiFiManagerParameter("") {
init(id, label, String(value, length - 1).c_str(), length, "", WFM_LABEL_DEFAULT);
}
double getValue() {
return atof(WiFiManagerParameter::getValue());
}
void setValue(double value, int length) {
WiFiManagerParameter::setValue(String(value, length - 1).c_str(), length);
}
void setValue(double value) {
setValue(value, getValueLength());
}
};
class CheckboxParameter : public WiFiManagerParameter {
public:
const char* checked = "type=\"checkbox\" checked";
const char* noChecked = "type=\"checkbox\"";
const char* trueVal = "T";
CheckboxParameter(const char* id, const char* label, bool value) : WiFiManagerParameter("") {
init(id, label, String(value ? trueVal : "0").c_str(), 1, "", WFM_LABEL_AFTER);
}
const char* getValue() const override {
return trueVal;
}
void setValue(bool value) {
WiFiManagerParameter::setValue(value ? trueVal : "0", 1);
}
const char* getCustomHTML() const override {
return strcmp(WiFiManagerParameter::getValue(), trueVal) == 0 ? checked : noChecked;
}
bool getCheckboxValue() {
return strcmp(WiFiManagerParameter::getValue(), trueVal) == 0 ? true : false;
}
};
class SeparatorParameter : public WiFiManagerParameter {
public:
SeparatorParameter() : WiFiManagerParameter("<hr>") {}
};

View File

@@ -13,7 +13,8 @@ framework = arduino
lib_deps =
;arduino-libraries/NTPClient@^3.2.1
bblanchon/ArduinoJson@^6.20.0
ihormelnyk/OpenTherm Library@^1.1.4
;ihormelnyk/OpenTherm Library@^1.1.4
https://github.com/Laxilef/opentherm_library/archive/refs/heads/master.zip
knolleary/PubSubClient@^2.8
bblanchon/StreamUtils@^1.7.3
lennarthennigs/ESP Telnet@^2.1.2
@@ -31,7 +32,7 @@ build_flags =
-D USE_TELNET=1
upload_speed = 921600
monitor_speed = 115200
version = 1.3.4
version = 1.4.0
; Defaults
[esp8266_defaults]
@@ -167,7 +168,7 @@ build_flags =
;-D DEBUG_BY_DEFAULT=1
;-D WM_DEBUG_MODE=3
[env:wemos_d1_mini32]
[env:d1_mini32]
platform = ${esp32_defaults.platform}
board = wemos_d1_mini32
lib_deps = ${esp32_defaults.lib_deps}

View File

@@ -14,12 +14,19 @@ public:
MainTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {}
protected:
const static byte REASON_PUMP_START_HEATING = 1;
const static byte REASON_PUMP_START_ANTISTUCK = 2;
Blinker* blinker = nullptr;
unsigned long lastHeapInfo = 0;
unsigned long firstFailConnect = 0;
unsigned int heapSize = 0;
unsigned int minFreeHeapSize = 0;
unsigned long restartSignalTime = 0;
bool heatingEnabled = false;
unsigned long heatingDisabledTime = 0;
byte externalPumpStartReason;
unsigned long externalPumpStartTime = 0;
const char* getTaskName() {
return "Main";
@@ -38,6 +45,7 @@ protected:
pinMode(LED_STATUS_PIN, OUTPUT);
digitalWrite(LED_STATUS_PIN, false);
#endif
pinMode(settings.externalPump.pin, OUTPUT);
#if defined(ESP32)
heapSize = ESP.getHeapSize();
@@ -107,9 +115,9 @@ protected:
#ifdef LED_STATUS_PIN
ledStatus(LED_STATUS_PIN);
yield();
#endif
heap();
externalPump();
// anti memory leak
if (Log.lock()) {
@@ -207,4 +215,67 @@ protected:
this->blinker->tick();
}
void externalPump() {
if (!vars.states.heating && this->heatingEnabled) {
this->heatingEnabled = false;
this->heatingDisabledTime = millis();
} else if (vars.states.heating && !this->heatingEnabled) {
this->heatingEnabled = true;
}
if (!settings.externalPump.use) {
if (vars.externalPump.enable) {
digitalWrite(settings.externalPump.pin, false);
vars.externalPump.enable = false;
vars.externalPump.lastEnableTime = millis();
Log.sinfoln("EXTPUMP", F("Disabled: use = off"));
}
return;
}
if (vars.externalPump.enable && !this->heatingEnabled) {
if (this->externalPumpStartReason == MainTask::REASON_PUMP_START_HEATING && millis() - this->heatingDisabledTime > settings.externalPump.postCirculationTime) {
digitalWrite(settings.externalPump.pin, false);
vars.externalPump.enable = false;
vars.externalPump.lastEnableTime = millis();
Log.sinfoln("EXTPUMP", F("Disabled: expired post circulation time"));
} else if (this->externalPumpStartReason == MainTask::REASON_PUMP_START_ANTISTUCK && millis() - this->externalPumpStartTime >= settings.externalPump.antiStuckTime) {
digitalWrite(settings.externalPump.pin, false);
vars.externalPump.enable = false;
vars.externalPump.lastEnableTime = millis();
Log.sinfoln("EXTPUMP", F("Disabled: expired anti stuck time"));
}
} else if (vars.externalPump.enable && this->heatingEnabled && this->externalPumpStartReason == MainTask::REASON_PUMP_START_ANTISTUCK) {
this->externalPumpStartReason = MainTask::REASON_PUMP_START_HEATING;
} else if (!vars.externalPump.enable && this->heatingEnabled) {
vars.externalPump.enable = true;
this->externalPumpStartTime = millis();
this->externalPumpStartReason = MainTask::REASON_PUMP_START_HEATING;
digitalWrite(settings.externalPump.pin, true);
Log.sinfoln("EXTPUMP", F("Enabled: heating on"));
} else if (!vars.externalPump.enable && millis() - vars.externalPump.lastEnableTime >= settings.externalPump.antiStuckInterval) {
vars.externalPump.enable = true;
this->externalPumpStartTime = millis();
this->externalPumpStartReason = MainTask::REASON_PUMP_START_ANTISTUCK;
digitalWrite(settings.externalPump.pin, true);
Log.sinfoln("EXTPUMP", F("Enabled: anti stuck"));
}
}
};

View File

@@ -55,11 +55,6 @@ protected:
pinMode(LED_OT_RX_PIN, OUTPUT);
digitalWrite(LED_OT_RX_PIN, false);
#endif
#ifdef HEATING_STATUS_PIN
pinMode(HEATING_STATUS_PIN, OUTPUT);
digitalWrite(HEATING_STATUS_PIN, false);
#endif
}
void loop() {
@@ -127,10 +122,6 @@ protected:
prevUpdateNonEssentialVars = 0;
vars.parameters.heatingEnabled = heatingEnabled;
Log.sinfoln(FPSTR(S_OT_HEATING), "%s", heatingEnabled ? F("Enabled") : F("Disabled"));
#ifdef HEATING_STATUS_PIN
digitalWrite(HEATING_STATUS_PIN, heatingEnabled);
#endif
}
vars.states.heating = ot->isCentralHeatingActive(localResponse);

View File

@@ -79,6 +79,14 @@ struct Settings {
} indoor;
} sensors;
struct {
bool use = false;
byte pin = EXT_PUMP_PIN_DEFAULT;
unsigned short postCirculationTime = 600;
unsigned int antiStuckInterval = 2592000;
unsigned short antiStuckTime = 300;
} externalPump;
char validationValue[8] = SETTINGS_VALID_VALUE;
} settings;
@@ -113,6 +121,11 @@ struct Variables {
float dhw = 0.0f;
} temperatures;
struct {
bool enable = false;
unsigned long lastEnableTime = 0;
} externalPump;
struct {
bool heatingEnabled = false;
byte heatingMinTemp = DEFAULT_HEATING_MIN_TEMP;

View File

@@ -1,6 +1,9 @@
#define WM_MDNS
#include <WiFiManager.h>
#include <WiFiManagerParameters.h>
#include <UnsignedIntParameter.h>
#include <UnsignedShortParameter.h>
#include <CheckboxParameter.h>
#include <SeparatorParameter.h>
#include <netif/etharp.h>
WiFiManager wm;
@@ -11,6 +14,7 @@ WiFiManagerParameter* wmMqttUser;
WiFiManagerParameter* wmMqttPassword;
WiFiManagerParameter* wmMqttPrefix;
UnsignedIntParameter* wmMqttPublishInterval;
UnsignedIntParameter* wmOtInPin;
UnsignedIntParameter* wmOtOutPin;
UnsignedIntParameter* wmOtMemberIdCode;
@@ -21,11 +25,17 @@ CheckboxParameter* wmOtHeatingCh1ToCh2;
CheckboxParameter* wmOtDhwToCh2;
CheckboxParameter* wmOtDhwBlocking;
CheckboxParameter* wmOtModSyncWithHeating;
UnsignedIntParameter* wmOutdoorSensorPin;
UnsignedIntParameter* wmIndoorSensorPin;
SeparatorParameter* wmSep1;
SeparatorParameter* wmSep2;
CheckboxParameter* wmExtPumpUse;
UnsignedIntParameter* wmExtPumpPin;
UnsignedShortParameter* wmExtPumpPostCirculationTime;
UnsignedIntParameter* wmExtPumpAntiStuckInterval;
UnsignedShortParameter* wmExtPumpAntiStuckTime;
SeparatorParameter* wmSep;
extern EEManager eeSettings;
#if USE_TELNET
@@ -37,7 +47,7 @@ class WifiManagerTask : public Task {
public:
WifiManagerTask(bool _enabled = false, unsigned long _interval = 0) : Task(_enabled, _interval) {}
WifiManagerTask* addTaskForDisable(Task* task) {
WifiManagerTask* addTaskForDisable(AbstractTask* task) {
this->tasksForDisable.push_back(task);
return this;
}
@@ -45,7 +55,7 @@ public:
protected:
bool connected = false;
unsigned long lastArpGratuitous = 0;
std::vector<Task*> tasksForDisable;
std::vector<AbstractTask*> tasksForDisable;
const char* getTaskName() {
return "WifiManager";
@@ -77,6 +87,8 @@ protected:
std::vector<const char *> menu = {"custom", "wifi", "param", "sep", "info", "update", "restart"};
wm.setMenu(menu);
wmSep = new SeparatorParameter();
wmHostname = new WiFiManagerParameter("hostname", "Hostname", settings.hostname, 80);
wm.addParameter(wmHostname);
@@ -98,8 +110,7 @@ protected:
wmMqttPublishInterval = new UnsignedIntParameter("mqtt_publish_interval", "MQTT publish interval", settings.mqtt.interval, 5);
wm.addParameter(wmMqttPublishInterval);
wmSep1 = new SeparatorParameter();
wm.addParameter(wmSep1);
wm.addParameter(wmSep);
wmOtInPin = new UnsignedIntParameter("ot_in_pin", "Opentherm GPIO IN", settings.opentherm.inPin, 2);
wm.addParameter(wmOtInPin);
@@ -131,8 +142,7 @@ protected:
wmOtModSyncWithHeating = new CheckboxParameter("ot_mod_sync_with_heating", "Modulation sync with heating", settings.opentherm.modulationSyncWithHeating);
wm.addParameter(wmOtModSyncWithHeating);
wmSep2 = new SeparatorParameter();
wm.addParameter(wmSep2);
wm.addParameter(wmSep);
wmOutdoorSensorPin = new UnsignedIntParameter("outdoor_sensor_pin", "Outdoor sensor GPIO", settings.sensors.outdoor.pin, 2);
wm.addParameter(wmOutdoorSensorPin);
@@ -140,6 +150,23 @@ protected:
wmIndoorSensorPin = new UnsignedIntParameter("indoor_sensor_pin", "Indoor sensor GPIO", settings.sensors.indoor.pin, 2);
wm.addParameter(wmIndoorSensorPin);
wm.addParameter(wmSep);
wmExtPumpUse = new CheckboxParameter("ext_pump_use", "Use external pump", settings.externalPump.use);
wm.addParameter(wmExtPumpUse);
wmExtPumpPin = new UnsignedIntParameter("ext_pump_pin", "External pump GPIO", settings.externalPump.pin, 2);
wm.addParameter(wmExtPumpPin);
wmExtPumpPostCirculationTime = new UnsignedShortParameter("ext_pump_ps_time", "External pump post circulation time", settings.externalPump.postCirculationTime, 5);
wm.addParameter(wmExtPumpPostCirculationTime);
wmExtPumpAntiStuckInterval = new UnsignedIntParameter("ext_pump_as_interval", "External pump anti stuck interval", settings.externalPump.antiStuckInterval, 7);
wm.addParameter(wmExtPumpAntiStuckInterval);
wmExtPumpAntiStuckTime = new UnsignedShortParameter("ext_pump_as_time", "External pump anti stuck time", settings.externalPump.antiStuckTime, 5);
wm.addParameter(wmExtPumpAntiStuckTime);
//wm.setCleanConnect(true);
wm.setRestorePersistent(false);
@@ -149,7 +176,7 @@ protected:
wm.setConfigPortalBlocking(false);
wm.setSaveParamsCallback(saveParamsCallback);
wm.setPreOtaUpdateCallback([this] {
for (Task* task : this->tasksForDisable) {
for (AbstractTask* task : this->tasksForDisable) {
if (task->isEnabled()) {
task->disable();
}
@@ -347,6 +374,32 @@ protected:
settings.sensors.indoor.pin = wmIndoorSensorPin->getValue();
}
if (wmExtPumpUse->getCheckboxValue() != settings.externalPump.use) {
changed = true;
settings.externalPump.use = wmExtPumpUse->getCheckboxValue();
}
if (wmExtPumpPin->getValue() != settings.externalPump.pin) {
changed = true;
needRestart = true;
settings.externalPump.pin = wmExtPumpPin->getValue();
}
if (wmExtPumpPostCirculationTime->getValue() != settings.externalPump.postCirculationTime) {
changed = true;
settings.externalPump.postCirculationTime = wmExtPumpPostCirculationTime->getValue();
}
if (wmExtPumpAntiStuckInterval->getValue() != settings.externalPump.antiStuckInterval) {
changed = true;
settings.externalPump.antiStuckInterval = wmExtPumpAntiStuckInterval->getValue();
}
if (wmExtPumpAntiStuckTime->getValue() != settings.externalPump.antiStuckTime) {
changed = true;
settings.externalPump.antiStuckTime = wmExtPumpAntiStuckTime->getValue();
}
if (!changed) {
return;
}

View File

@@ -1,5 +1,5 @@
#define PROJECT_NAME "OpenTherm Gateway"
#define PROJECT_VERSION "1.3.4"
#define PROJECT_VERSION "1.4.0"
#define PROJECT_REPO "https://github.com/Laxilef/OTGateway"
#define AP_SSID "OpenTherm Gateway"
#define AP_PASSWORD "otgateway123456"
@@ -54,6 +54,10 @@
#define SENSOR_INDOOR_PIN_DEFAULT 0
#endif
#ifndef EXT_PUMP_PIN_DEFAULT
#define EXT_PUMP_PIN_DEFAULT 0
#endif
#ifndef PROGMEM
#define PROGMEM
#endif