mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
replaced Ticker library
This commit is contained in:
50
README.md
50
README.md
@@ -125,9 +125,9 @@ My circuit will work with both 3.3V and 5V. It's easiest though to power directl
|
|||||||
|
|
||||||
Powering the ESP89266 can be either via the USB from a PC or external 5V power supply or from the EMS line itself using a buck step-down converter. The EMS provides about 15V AC current. The advantage of using the EMS is obviously less power cables and it's neater to place inline with the thermostat. I use a [Pololu D24C22F5](https://www.pololu.com/product/2858) which is 5V/2A buck step-down module and probably slightly overkill for what we need. The additional part of the circuit is shown below along with an earlier breadboard prototype using a NodeMCU2 (with the additional LEDs):
|
Powering the ESP89266 can be either via the USB from a PC or external 5V power supply or from the EMS line itself using a buck step-down converter. The EMS provides about 15V AC current. The advantage of using the EMS is obviously less power cables and it's neater to place inline with the thermostat. I use a [Pololu D24C22F5](https://www.pololu.com/product/2858) which is 5V/2A buck step-down module and probably slightly overkill for what we need. The additional part of the circuit is shown below along with an earlier breadboard prototype using a NodeMCU2 (with the additional LEDs):
|
||||||
|
|
||||||
Power circuit | Example |
|
| Power circuit | Example |
|
||||||
--- | ---
|
| ------------------------------------------ | ---------------------------------------------------- |
|
||||||
 |  |
|
|  |  |
|
||||||
|
|
||||||
## Known Issues and ToDo's
|
## Known Issues and ToDo's
|
||||||
|
|
||||||
@@ -176,19 +176,19 @@ When a device is broadcasting to everyone there is no specific destination neede
|
|||||||
|
|
||||||
The Boiler (ID 0x08) will send out these broadcast telegrams regularly:
|
The Boiler (ID 0x08) will send out these broadcast telegrams regularly:
|
||||||
|
|
||||||
Type | Description (see [here](https://emswiki.thefischer.net/doku.php?id=wiki:ems:telegramme)) | Data length (excluding header) | Frequency
|
| Type | Description (see [here](https://emswiki.thefischer.net/doku.php?id=wiki:ems:telegramme)) | Data length (excluding header) | Frequency |
|
||||||
--- | --- | --- | --- |
|
| ---- | ---------------------------------------------------------------------------------------- | ------------------------------ | ------------ |
|
||||||
0x34 | UBAMonitorWWMessage | 19 bytes | 10 seconds
|
| 0x34 | UBAMonitorWWMessage | 19 bytes | 10 seconds |
|
||||||
0x18 | UBAMonitorFast | 25 bytes | 10 seconds
|
| 0x18 | UBAMonitorFast | 25 bytes | 10 seconds |
|
||||||
0x19 | UBAMonitorSlow | 22 bytes | every minute
|
| 0x19 | UBAMonitorSlow | 22 bytes | every minute |
|
||||||
0x1C | UBAWartungsmelding | 27 bytes | every minute
|
| 0x1C | UBAWartungsmelding | 27 bytes | every minute |
|
||||||
0x2A | status, specific to boiler type | - | 10 seconds
|
| 0x2A | status, specific to boiler type | - | 10 seconds |
|
||||||
|
|
||||||
And a thermostat (ID 0x17 for a RC20) would broadcast these messages regularly:
|
And a thermostat (ID 0x17 for a RC20) would broadcast these messages regularly:
|
||||||
|
|
||||||
Type | Description
|
| Type | Description |
|
||||||
--- | --- |
|
| ---- | ----------- | undefined |undefined |undefined |undefined |undefined |
|
||||||
0x06 | time on thermostat Y,M,H,D,M,S,wd
|
| 0x06 | time on thermostat Y,M,H,D,M,S,wd |
|
||||||
|
|
||||||
Refer to the code in `ems.cpp` for further explanation on how to parse these message types and also reference the EMS Wiki.
|
Refer to the code in `ems.cpp` for further explanation on how to parse these message types and also reference the EMS Wiki.
|
||||||
|
|
||||||
@@ -211,7 +211,6 @@ Every telegram sent is echo'd back to Rx.
|
|||||||
* Time http://playground.arduino.cc/code/time
|
* Time http://playground.arduino.cc/code/time
|
||||||
* PubSubClient http://pubsubclient.knolleary.net
|
* PubSubClient http://pubsubclient.knolleary.net
|
||||||
* ArduinoJson https://github.com/bblanchon/ArduinoJson
|
* ArduinoJson https://github.com/bblanchon/ArduinoJson
|
||||||
* Ticker https://github.com/sstaub/Ticker
|
|
||||||
|
|
||||||
`src\emsuart.cpp` handles the low level UART read and write logic. You shouldn't need to touch this. All receive commands from the EMS bus are handled asynchronously using a circular buffer via an interrupt. A separate function processes the buffer and extracts the telegrams. Since we don't send too many write commands this is done sequentially. I couldn't use the standard Arduino Serial implementation because of the 11-bit break signal causes a frame-error which gets ignored.
|
`src\emsuart.cpp` handles the low level UART read and write logic. You shouldn't need to touch this. All receive commands from the EMS bus are handled asynchronously using a circular buffer via an interrupt. A separate function processes the buffer and extracts the telegrams. Since we don't send too many write commands this is done sequentially. I couldn't use the standard Arduino Serial implementation because of the 11-bit break signal causes a frame-error which gets ignored.
|
||||||
|
|
||||||
@@ -225,15 +224,15 @@ Every telegram sent is echo'd back to Rx.
|
|||||||
|
|
||||||
`ems.cpp` defines callback functions that handle all the broadcast types listed above (e.g. 0x34, 0x18, 0x19 etc) plus these extra types:
|
`ems.cpp` defines callback functions that handle all the broadcast types listed above (e.g. 0x34, 0x18, 0x19 etc) plus these extra types:
|
||||||
|
|
||||||
Device | Type | Description | What
|
| Device | Type | Description | What |
|
||||||
--- | --- | --- | --- |
|
| ----------------- | ---- | ----------------------------- | ---------------------------------------- |
|
||||||
Boiler (0x08) | 0x33 | UBAParameterWW | reads selected & desired warm water temp
|
| Boiler (0x08) | 0x33 | UBAParameterWW | reads selected & desired warm water temp |
|
||||||
Boiler (0x08) | 0x14 | UBATotalUptimeMessage |
|
| Boiler (0x08) | 0x14 | UBATotalUptimeMessage | |
|
||||||
Boiler (0x08) | 0x15 | UBAMaintenanceSettingsMessage |
|
| Boiler (0x08) | 0x15 | UBAMaintenanceSettingsMessage | |
|
||||||
Boiler (0x08) | 0x16 | UBAParametersMessage |
|
| Boiler (0x08) | 0x16 | UBAParametersMessage | |
|
||||||
Thermostat (0x17) | 0xA8 | RC20Temperature | sets temperature and operating modes
|
| Thermostat (0x17) | 0xA8 | RC20Temperature | sets temperature and operating modes |
|
||||||
Thermostat (0x17) | 0xA3 | RCOutdoorTempMessage |
|
| Thermostat (0x17) | 0xA3 | RCOutdoorTempMessage | |
|
||||||
Thermostat (0x17) | 0x91 | RC20StatusMessage | reads set & current room temperatures
|
| Thermostat (0x17) | 0x91 | RC20StatusMessage | reads set & current room temperatures |
|
||||||
|
|
||||||
Note the thermostat types are based on a RC20 model thermostat. If using an RC30/RC35 use types 0x3E and 0x48 to read the values.
|
Note the thermostat types are based on a RC20 model thermostat. If using an RC30/RC35 use types 0x3E and 0x48 to read the values.
|
||||||
|
|
||||||
@@ -427,10 +426,10 @@ Next copy the files custom.h, index.html, boiler.ino and the esp*.cpp/h files fr
|
|||||||
|
|
||||||
I will eventually put pre-built version based on ESPurna in the directory `/firmware` which you can upload using esptool (https://github.com/espressif/esptool) bootloader. On Windows, follow these instructions:
|
I will eventually put pre-built version based on ESPurna in the directory `/firmware` which you can upload using esptool (https://github.com/espressif/esptool) bootloader. On Windows, follow these instructions:
|
||||||
|
|
||||||
1. Check if you have python 2.7 installed. If not [download it](https://www.python.org/downloads/) and make sure you add Python to the windows PATH so it'll recognize .py files.
|
1. Check if you have python 2.7 installed. If not [download it](https://www.python.org/downloads/) and make sure you select the option to add Python to the windows PATH.
|
||||||
2. Install the ESPTool by running `pip install esptool` from a command prompt.
|
2. Install the ESPTool by running `pip install esptool` from a command prompt.
|
||||||
3. Connect the ESP via USB, figure out the COM port.
|
3. Connect the ESP via USB, figure out the COM port.
|
||||||
4. run `esptool.py -p <com> write_flash 0x00000 <firmware>` where firmware is the .bin file and \<com\> is the com port, e.g. COM3
|
4. run `esptool.py -p <com> write_flash 0x00000 <firmware>` where firmware is the `.bin` file and \<com\> is the COM port, e.g. `COM3`
|
||||||
|
|
||||||
|
|
||||||
## Using Arduino IDE (*unsupported!*)
|
## Using Arduino IDE (*unsupported!*)
|
||||||
@@ -449,7 +448,6 @@ Porting to the Arduino is tricky and messy (which is one of the reasons I don't
|
|||||||
#define MQTT_PASS "<broker_password>"
|
#define MQTT_PASS "<broker_password>"
|
||||||
```
|
```
|
||||||
* Put all the files in a single sketch folder (`ESPHelper.*, boiler.ino, ems.*, emsuart.*`)
|
* Put all the files in a single sketch folder (`ESPHelper.*, boiler.ino, ems.*, emsuart.*`)
|
||||||
* Download the new and improved Ticker library from https://github.com/sstaub/Ticker copying the .cpp and .h files to the same folder you just created
|
|
||||||
* Possibly change some the #includes to use the local files, replacing `<lib>` with `"lib"`
|
* Possibly change some the #includes to use the local files, replacing `<lib>` with `"lib"`
|
||||||
* cross your fingers and CTRL-R to compile...
|
* cross your fingers and CTRL-R to compile...
|
||||||
|
|
||||||
|
|||||||
@@ -119,13 +119,9 @@ bool ESPHelper::begin(const char * hostname) {
|
|||||||
if (_mqttSet) {
|
if (_mqttSet) {
|
||||||
//make mqtt client use either the secure or non-secure wifi client depending on the setting
|
//make mqtt client use either the secure or non-secure wifi client depending on the setting
|
||||||
if (_useSecureClient) {
|
if (_useSecureClient) {
|
||||||
client = PubSubClient(_currentNet.mqttHost,
|
client = PubSubClient(_currentNet.mqttHost, _currentNet.mqttPort, wifiClientSecure);
|
||||||
_currentNet.mqttPort,
|
|
||||||
wifiClientSecure);
|
|
||||||
} else {
|
} else {
|
||||||
client = PubSubClient(_currentNet.mqttHost,
|
client = PubSubClient(_currentNet.mqttHost, _currentNet.mqttPort, wifiClient);
|
||||||
_currentNet.mqttPort,
|
|
||||||
wifiClient);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//set the mqtt message callback if needed
|
//set the mqtt message callback if needed
|
||||||
@@ -139,13 +135,9 @@ bool ESPHelper::begin(const char * hostname) {
|
|||||||
//make mqtt client use either the secure or non-secure wifi client depending on the setting
|
//make mqtt client use either the secure or non-secure wifi client depending on the setting
|
||||||
//(this shouldnt be needed if making a dummy connection since the idea would be that there wont be mqtt in this case)
|
//(this shouldnt be needed if making a dummy connection since the idea would be that there wont be mqtt in this case)
|
||||||
if (_useSecureClient) {
|
if (_useSecureClient) {
|
||||||
client = PubSubClient("192.168.1.255",
|
client = PubSubClient("192.168.1.255", _currentNet.mqttPort, wifiClientSecure);
|
||||||
_currentNet.mqttPort,
|
|
||||||
wifiClientSecure);
|
|
||||||
} else {
|
} else {
|
||||||
client = PubSubClient("192.168.1.255",
|
client = PubSubClient("192.168.1.255", _currentNet.mqttPort, wifiClient);
|
||||||
_currentNet.mqttPort,
|
|
||||||
wifiClient);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,8 +153,7 @@ bool ESPHelper::begin(const char * hostname) {
|
|||||||
timeout++;
|
timeout++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ArduinoOTA.onProgress([](unsigned int progress,
|
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { /* ota progress code */ });
|
||||||
unsigned int total) { /* ota progress code */ });
|
|
||||||
ArduinoOTA.onError([](ota_error_t error) { /* ota error code */ });
|
ArduinoOTA.onError([](ota_error_t error) { /* ota error code */ });
|
||||||
|
|
||||||
//initially attempt to connect to wifi when we begin (but only block for 2 seconds before timing out)
|
//initially attempt to connect to wifi when we begin (but only block for 2 seconds before timing out)
|
||||||
@@ -229,8 +220,7 @@ void ESPHelper::end() {
|
|||||||
int ESPHelper::loop() {
|
int ESPHelper::loop() {
|
||||||
if (_ssidSet) {
|
if (_ssidSet) {
|
||||||
//check for good connections and attempt a reconnect if needed
|
//check for good connections and attempt a reconnect if needed
|
||||||
if (((_mqttSet && !client.connected()) || setConnectionStatus() < WIFI_ONLY)
|
if (((_mqttSet && !client.connected()) || setConnectionStatus() < WIFI_ONLY) && _connectionStatus != BROADCAST) {
|
||||||
&& _connectionStatus != BROADCAST) {
|
|
||||||
reconnect();
|
reconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,8 +345,7 @@ void ESPHelper::setWifiCallback(void (*callback)()) {
|
|||||||
void ESPHelper::reconnect() {
|
void ESPHelper::reconnect() {
|
||||||
static uint8_t tryCount = 0;
|
static uint8_t tryCount = 0;
|
||||||
|
|
||||||
if (_connectionStatus != BROADCAST
|
if (_connectionStatus != BROADCAST && setConnectionStatus() != FULL_CONNECTION) {
|
||||||
&& setConnectionStatus() != FULL_CONNECTION) {
|
|
||||||
logger(LOG_CONSOLE, "Attempting WiFi Connection...");
|
logger(LOG_CONSOLE, "Attempting WiFi Connection...");
|
||||||
//attempt to connect to the wifi if connection is lost
|
//attempt to connect to the wifi if connection is lost
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
@@ -385,8 +374,7 @@ void ESPHelper::reconnect() {
|
|||||||
|
|
||||||
//attempt to connect to mqtt when we finally get connected to WiFi
|
//attempt to connect to mqtt when we finally get connected to WiFi
|
||||||
if (_mqttSet) {
|
if (_mqttSet) {
|
||||||
static uint8_t timeout =
|
static uint8_t timeout = 0; //allow a max of 5 mqtt connection attempts before timing out
|
||||||
0; //allow a max of 5 mqtt connection attempts before timing out
|
|
||||||
if (!client.connected() && timeout < 5) {
|
if (!client.connected() && timeout < 5) {
|
||||||
logger(LOG_CONSOLE, "Attempting MQTT connection...");
|
logger(LOG_CONSOLE, "Attempting MQTT connection...");
|
||||||
|
|
||||||
@@ -394,9 +382,7 @@ void ESPHelper::reconnect() {
|
|||||||
|
|
||||||
//connect to mqtt with user/pass
|
//connect to mqtt with user/pass
|
||||||
if (_mqttUserSet) {
|
if (_mqttUserSet) {
|
||||||
connected = client.connect(_clientName,
|
connected = client.connect(_clientName, _currentNet.mqttUser, _currentNet.mqttPass);
|
||||||
_currentNet.mqttUser,
|
|
||||||
_currentNet.mqttPass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//connect to mqtt without credentials
|
//connect to mqtt without credentials
|
||||||
@@ -836,8 +822,7 @@ void ESPHelper::consoleProcessCommand() {
|
|||||||
uint8_t cmd = _command[0];
|
uint8_t cmd = _command[0];
|
||||||
|
|
||||||
if (!_verboseMessages) {
|
if (!_verboseMessages) {
|
||||||
telnetClient.println(
|
telnetClient.println("Warning, verbose messaging is off. Use v to toggle.");
|
||||||
"Warning, verbose messaging is off. Use v to toggle.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the command
|
// Process the command
|
||||||
@@ -853,8 +838,7 @@ void ESPHelper::consoleProcessCommand() {
|
|||||||
resetESP();
|
resetESP();
|
||||||
} else if (cmd == '&') {
|
} else if (cmd == '&') {
|
||||||
_verboseMessages = !_verboseMessages; // toggle
|
_verboseMessages = !_verboseMessages; // toggle
|
||||||
telnetClient.printf("Verbose messaging is %s\n",
|
telnetClient.printf("Verbose messaging is %s\n", _verboseMessages ? "on" : "off");
|
||||||
_verboseMessages ? "on" : "off");
|
|
||||||
} else {
|
} else {
|
||||||
// custom Project commands
|
// custom Project commands
|
||||||
if (_consoleCallbackProjectCmds) {
|
if (_consoleCallbackProjectCmds) {
|
||||||
@@ -874,9 +858,7 @@ void ESPHelper::logger(log_level_t level, const char * message) {
|
|||||||
telnetClient.flush();
|
telnetClient.flush();
|
||||||
} else if (level == LOG_HA) {
|
} else if (level == LOG_HA) {
|
||||||
char s[100];
|
char s[100];
|
||||||
sprintf(s,
|
sprintf(s, "%s: %s\n", _hostname,
|
||||||
"%s: %s\n",
|
|
||||||
_hostname,
|
|
||||||
message); // add new line, for the debug telnet printer
|
message); // add new line, for the debug telnet printer
|
||||||
publish(MQTT_NOTIFICATION, s, false);
|
publish(MQTT_NOTIFICATION, s, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ lib_deps =
|
|||||||
Time
|
Time
|
||||||
PubSubClient
|
PubSubClient
|
||||||
ArduinoJson
|
ArduinoJson
|
||||||
Ticker
|
|
||||||
|
|
||||||
[env:nodemcuv2]
|
[env:nodemcuv2]
|
||||||
board = nodemcuv2
|
board = nodemcuv2
|
||||||
|
|||||||
@@ -14,14 +14,7 @@
|
|||||||
|
|
||||||
// public libraries
|
// public libraries
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <Ticker.h> // https://github.com/sstaub/Ticker
|
#include <Ticker.h> // https://github.com/esp8266/Arduino/tree/master/libraries/Ticker
|
||||||
|
|
||||||
// private function prototypes
|
|
||||||
void heartbeat();
|
|
||||||
void systemCheck();
|
|
||||||
void publishValues();
|
|
||||||
void _showerColdShotStart();
|
|
||||||
void _showerColdShotStop();
|
|
||||||
|
|
||||||
// these are set as -D build flags. If you're not using PlatformIO hard code them
|
// these are set as -D build flags. If you're not using PlatformIO hard code them
|
||||||
//#define WIFI_SSID "<my_ssid>"
|
//#define WIFI_SSID "<my_ssid>"
|
||||||
@@ -30,6 +23,23 @@ void _showerColdShotStop();
|
|||||||
//#define MQTT_USER "<broker_username>"
|
//#define MQTT_USER "<broker_username>"
|
||||||
//#define MQTT_PASS "<broker_password>"
|
//#define MQTT_PASS "<broker_password>"
|
||||||
|
|
||||||
|
// private function prototypes
|
||||||
|
void heartbeat();
|
||||||
|
void systemCheck();
|
||||||
|
void publishValues();
|
||||||
|
void _showerColdShotStart();
|
||||||
|
void _showerColdShotStop();
|
||||||
|
void _toggleHeartbeat();
|
||||||
|
|
||||||
|
// timers
|
||||||
|
Ticker publishValuesTimer;
|
||||||
|
Ticker systemCheckTimer;
|
||||||
|
Ticker heartbeatTimer;
|
||||||
|
Ticker showerResetTimer;
|
||||||
|
#define publishValuesTime 300 // every 5 mins post HA values
|
||||||
|
#define systemCheckTime 10 // every 10 seconds check if Boiler is online
|
||||||
|
#define heartbeatTime 1 // every second blink heartbeat LED
|
||||||
|
|
||||||
// hostname is also used as the MQTT topic identifier (home/<hostname>)
|
// hostname is also used as the MQTT topic identifier (home/<hostname>)
|
||||||
#define HOSTNAME "boiler"
|
#define HOSTNAME "boiler"
|
||||||
|
|
||||||
@@ -96,7 +106,7 @@ typedef struct {
|
|||||||
netInfo homeNet = {.mqttHost = MQTT_IP,
|
netInfo homeNet = {.mqttHost = MQTT_IP,
|
||||||
.mqttUser = MQTT_USER,
|
.mqttUser = MQTT_USER,
|
||||||
.mqttPass = MQTT_PASS,
|
.mqttPass = MQTT_PASS,
|
||||||
.mqttPort = 1883,
|
.mqttPort = 1883, // this is the default, change if using another port
|
||||||
.ssid = WIFI_SSID,
|
.ssid = WIFI_SSID,
|
||||||
.pass = WIFI_PASSWORD};
|
.pass = WIFI_PASSWORD};
|
||||||
|
|
||||||
@@ -110,12 +120,8 @@ _Boiler_Shower Boiler_Shower;
|
|||||||
#define myDebug(x, ...) myESP.printf(x, ##__VA_ARGS__);
|
#define myDebug(x, ...) myESP.printf(x, ##__VA_ARGS__);
|
||||||
|
|
||||||
// Timers
|
// Timers
|
||||||
Ticker updateHATimer(publishValues, 300000); // every 5 mins (300000) post HA values
|
|
||||||
Ticker hearbeatTimer(heartbeat, 500); // changing onboard heartbeat led every 500ms
|
|
||||||
Ticker systemCheckTimer(systemCheck, 10000); // every 10 seconds check if Boiler is online
|
|
||||||
Ticker showerResetTimer(_showerColdShotStop, SHOWER_OFF_DURATION, 1); // timer for how long we turn off the hot water
|
|
||||||
const unsigned long POLL_TIMEOUT_ERR = 10000; // if no signal from boiler for last 10 seconds, assume its offline
|
const unsigned long POLL_TIMEOUT_ERR = 10000; // if no signal from boiler for last 10 seconds, assume its offline
|
||||||
bool heartbeat_state = false;
|
bool heartbeatEnabled = false;
|
||||||
|
|
||||||
const unsigned long TX_HOLD_LED_TIME = 2000; // how long to hold the Tx LED because its so quick
|
const unsigned long TX_HOLD_LED_TIME = 2000; // how long to hold the Tx LED because its so quick
|
||||||
|
|
||||||
@@ -312,16 +318,13 @@ void myDebugCallback() {
|
|||||||
ems_setWarmWaterTemp((uint8_t)strtol(&cmd[2], 0, 10));
|
ems_setWarmWaterTemp((uint8_t)strtol(&cmd[2], 0, 10));
|
||||||
break;
|
break;
|
||||||
case 'q': // quiet
|
case 'q': // quiet
|
||||||
b = !ems_getLogVerbose();
|
_toggleHeartbeat();
|
||||||
ems_setLogVerbose(b);
|
|
||||||
enableHeartbeat(b);
|
|
||||||
break;
|
break;
|
||||||
case 'a': // set ww activate on or off
|
case 'a': // set ww activate on or off
|
||||||
if ((cmd[2] - '0') == 1) {
|
if ((cmd[2] - '0') == 1)
|
||||||
ems_setWarmWaterActivated(true);
|
ems_setWarmWaterActivated(true);
|
||||||
} else if ((cmd[2] - '0') == 0) {
|
else if ((cmd[2] - '0') == 0)
|
||||||
ems_setWarmWaterActivated(false);
|
ems_setWarmWaterActivated(false);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'T': // toggle Thermostat
|
case 'T': // toggle Thermostat
|
||||||
b = !ems_getThermostatEnabled();
|
b = !ems_getThermostatEnabled();
|
||||||
@@ -337,6 +340,14 @@ void myDebugCallback() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toggle heartbeat LED
|
||||||
|
void _toggleHeartbeat() {
|
||||||
|
bool b = !ems_getLogVerbose();
|
||||||
|
ems_setLogVerbose(b);
|
||||||
|
heartbeatEnabled = b;
|
||||||
|
digitalWrite(LED_BUILTIN, (b) ? LOW : HIGH); // set the LED
|
||||||
|
}
|
||||||
|
|
||||||
// MQTT Callback to handle incoming/outgoing changes
|
// MQTT Callback to handle incoming/outgoing changes
|
||||||
void MQTTcallback(char * topic, byte * payload, uint8_t length) {
|
void MQTTcallback(char * topic, byte * payload, uint8_t length) {
|
||||||
// check if start is received, if so return boottime - defined in ESPHelper.h
|
// check if start is received, if so return boottime - defined in ESPHelper.h
|
||||||
@@ -403,8 +414,9 @@ void setup() {
|
|||||||
digitalWrite(LED_ERR, HIGH);
|
digitalWrite(LED_ERR, HIGH);
|
||||||
|
|
||||||
// Timers
|
// Timers
|
||||||
updateHATimer.start();
|
publishValuesTimer.attach(publishValuesTime, publishValues); // every 5 mins (300000) post HA values
|
||||||
systemCheckTimer.start();
|
systemCheckTimer.attach(systemCheckTime, systemCheck); // every 10 seconds check if Boiler is online
|
||||||
|
heartbeatTimer.attach(heartbeatTime, heartbeat); // every second blink heartbeat LED
|
||||||
|
|
||||||
// set up Wifi, MQTT, Telnet
|
// set up Wifi, MQTT, Telnet
|
||||||
myESP.setWifiCallback(WIFIcallback);
|
myESP.setWifiCallback(WIFIcallback);
|
||||||
@@ -424,21 +436,12 @@ void setup() {
|
|||||||
_initBoiler();
|
_initBoiler();
|
||||||
|
|
||||||
// heartbeat, only if setting is enabled
|
// heartbeat, only if setting is enabled
|
||||||
enableHeartbeat(ems_getLogVerbose());
|
heartbeatEnabled = ems_getLogVerbose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// flash LEDs
|
// flash LEDs
|
||||||
// Using a faster way to write to pins as digitalWrite does a lot of overhead like pin checking & disabling interrupts
|
// Using a faster way to write to pins as digitalWrite does a lot of overhead like pin checking & disabling interrupts
|
||||||
void showLEDs() {
|
void showLEDs() {
|
||||||
// update Ticker
|
|
||||||
hearbeatTimer.update();
|
|
||||||
|
|
||||||
// hearbeat timer, using internal LED on board
|
|
||||||
if (hearbeatTimer.counter() == 20)
|
|
||||||
hearbeatTimer.interval(200);
|
|
||||||
if (hearbeatTimer.counter() == 80)
|
|
||||||
hearbeatTimer.interval(1000);
|
|
||||||
|
|
||||||
if (ems_getLogVerbose()) {
|
if (ems_getLogVerbose()) {
|
||||||
// ERR LED
|
// ERR LED
|
||||||
if (!Boiler_Status.boiler_online) {
|
if (!Boiler_Status.boiler_online) {
|
||||||
@@ -461,19 +464,10 @@ void showLEDs() {
|
|||||||
|
|
||||||
// heartbeat callback to light up the LED, called via Ticker
|
// heartbeat callback to light up the LED, called via Ticker
|
||||||
void heartbeat() {
|
void heartbeat() {
|
||||||
digitalWrite(LED_BUILTIN, heartbeat_state);
|
if (heartbeatEnabled) {
|
||||||
heartbeat_state = !heartbeat_state;
|
int state = digitalRead(LED_BUILTIN);
|
||||||
}
|
digitalWrite(LED_BUILTIN, !state);
|
||||||
|
}
|
||||||
// enables or disables the heartbeat LED
|
|
||||||
// using the Ticker library
|
|
||||||
void enableHeartbeat(bool on) {
|
|
||||||
heartbeat_state = (on) ? LOW : HIGH;
|
|
||||||
heartbeat();
|
|
||||||
if (on)
|
|
||||||
hearbeatTimer.resume();
|
|
||||||
else
|
|
||||||
hearbeatTimer.pause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// do a healthcheck every now and then to see if we connections
|
// do a healthcheck every now and then to see if we connections
|
||||||
@@ -497,6 +491,7 @@ void _showerColdShotStop() {
|
|||||||
myDebug("Shower: turning back hot shower water.\n");
|
myDebug("Shower: turning back hot shower water.\n");
|
||||||
ems_setWarmWaterActivated(true);
|
ems_setWarmWaterActivated(true);
|
||||||
Boiler_Shower.isColdShot = false;
|
Boiler_Shower.isColdShot = false;
|
||||||
|
showerResetTimer.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,10 +502,6 @@ void loop() {
|
|||||||
connectionStatus = myESP.loop();
|
connectionStatus = myESP.loop();
|
||||||
timestamp = millis();
|
timestamp = millis();
|
||||||
|
|
||||||
// Timers
|
|
||||||
updateHATimer.update();
|
|
||||||
systemCheckTimer.update();
|
|
||||||
|
|
||||||
// update the Rx Tx and ERR LEDs
|
// update the Rx Tx and ERR LEDs
|
||||||
showLEDs();
|
showLEDs();
|
||||||
|
|
||||||
@@ -537,11 +528,10 @@ void loop() {
|
|||||||
* Shower Logic
|
* Shower Logic
|
||||||
*/
|
*/
|
||||||
if (Boiler_Status.shower_enabled) {
|
if (Boiler_Status.shower_enabled) {
|
||||||
showerResetTimer.update(); // update Ticker
|
|
||||||
|
|
||||||
// if already in cold mode, ignore all this logic until we're out of the cold blast
|
// if already in cold mode, ignore all this logic until we're out of the cold blast
|
||||||
if (!Boiler_Shower.isColdShot) {
|
if (!Boiler_Shower.isColdShot) {
|
||||||
// these values come from UBAMonitorFast - type 0x18) which is broadcasted every second so we're pretty accurate
|
// these values come from UBAMonitorFast - type 0x18) which is broadcasted every second so our timings are accurate enough
|
||||||
|
// and no need to fetch the values from the boiler
|
||||||
Boiler_Shower.showerOn =
|
Boiler_Shower.showerOn =
|
||||||
((EMS_Boiler.selBurnPow >= SHOWER_BURNPOWER_MIN) && (EMS_Boiler.selFlowTemp == 0) && EMS_Boiler.burnGas);
|
((EMS_Boiler.selBurnPow >= SHOWER_BURNPOWER_MIN) && (EMS_Boiler.selFlowTemp == 0) && EMS_Boiler.burnGas);
|
||||||
|
|
||||||
@@ -559,7 +549,8 @@ void loop() {
|
|||||||
if ((((timestamp - Boiler_Shower.timerStart) > SHOWER_MAX_DURATION) && !Boiler_Shower.isColdShot)
|
if ((((timestamp - Boiler_Shower.timerStart) > SHOWER_MAX_DURATION) && !Boiler_Shower.isColdShot)
|
||||||
&& Boiler_Status.shower_timer) {
|
&& Boiler_Status.shower_timer) {
|
||||||
_showerColdShotStart();
|
_showerColdShotStart();
|
||||||
showerResetTimer.start(); // start the timer for n seconds which will reset the water back to hot
|
// start the timer for n seconds which will reset the water back to hot
|
||||||
|
showerResetTimer.attach(SHOWER_OFF_DURATION, _showerColdShotStop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // shower is off
|
} else { // shower is off
|
||||||
@@ -594,6 +585,5 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// yield to prevent watchdog from timing out
|
// yield to prevent watchdog from timing out
|
||||||
// if using delay() this is not needed, but confuses the Ticker library
|
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user