This commit is contained in:
proddy
2018-05-17 21:57:46 +02:00
parent 73c0c2a145
commit 615c5417de
9 changed files with 123 additions and 113 deletions

View File

@@ -58,8 +58,7 @@ void _showerColdShotStop();
#define TOPIC_BOILER_DATA MQTT_BOILER "boiler_data" // for sending boiler values
#define TOPIC_SHOWERTIME MQTT_BOILER "showertime" // for sending shower time results
// all on
// thermostat support, shower timing and shower alert all enabled
#define BOILER_THERMOSTAT_ENABLED 1
#define BOILER_SHOWER_ENABLED 1
#define BOILER_SHOWER_TIMER 0
@@ -71,10 +70,6 @@ const unsigned long SHOWER_MAX_DURATION = 420000; // 7 minutes, before trigger
const unsigned long SHOWER_OFF_DURATION = 3000; // 3 seconds long for cold water
const uint8_t SHOWER_BURNPOWER_MIN = 80;
// for debugging...
//const unsigned long SHOWER_MIN_DURATION = 10000; // 10 seconds
//const unsigned long SHOWER_MAX_DURATION = 15000; // 15 seconds
typedef struct {
bool wifi_connected;
bool boiler_online;
@@ -96,8 +91,7 @@ netInfo homeNet = {.mqttHost = MQTT_IP,
.mqttPass = MQTT_PASS,
.mqttPort = 1883,
.ssid = WIFI_SSID,
.pass = WIFI_PASSWORD
};
.pass = WIFI_PASSWORD};
ESPHelper myESP(&homeNet);
@@ -176,6 +170,7 @@ void showInfo() {
}
myDebug("\nBoiler stats:\n");
// UBAMonitorWWMessage & UBAParameterWW
myDebug(" Warm Water activated: %s\n", (EMS_Boiler.wWActivated ? "yes" : "no"));
myDebug(" Warm Water selected temperature: %d C\n", EMS_Boiler.wWSelTemp);
@@ -195,7 +190,7 @@ void showInfo() {
myDebug(" Return temperature: %s C\n", _float_to_char(s, EMS_Boiler.retTemp));
myDebug(" Gas: %s\n", EMS_Boiler.burnGas ? "on" : "off");
myDebug(" Circulating pump: %s\n", EMS_Boiler.heatPmp ? "on" : "off");
myDebug(" Boiler pump: %s\n", EMS_Boiler.heatPmp ? "on" : "off");
myDebug(" Fan: %s\n", EMS_Boiler.fanWork ? "on" : "off");
myDebug(" Ignition: %s\n", EMS_Boiler.ignWork ? "on" : "off");
myDebug(" Circulation pump: %s\n", EMS_Boiler.wWCirc ? "on" : "off");
@@ -233,8 +228,8 @@ void showInfo() {
_float_to_char(s, EMS_Thermostat.curr_roomTemp));
}
// show the Shower Info
if (Boiler_Status.shower_enabled) {
// show the Shower Info
myDebug("Shower stats:\n Shower is %s\n", (Boiler_Shower.showerOn ? "on" : "off"));
char s[70];
uint8_t sec = (uint8_t)((Boiler_Shower.duration / 1000) % 60);
@@ -250,10 +245,11 @@ void showInfo() {
void publishValues() {
myDebug("Publishing data to MQTT topics\n");
char s[20]; // for formatting strings
// Boiler values as one JSON object
StaticJsonBuffer<512> jsonBuffer;
char data[512];
char s[20];
JsonObject & root = jsonBuffer.createObject();
root["wWCurTmp"] = _float_to_char(s, EMS_Boiler.wWCurTmp);
root["wWHeat"] = EMS_Boiler.wWHeat ? "on" : "off";
@@ -284,7 +280,6 @@ void publishValues() {
}
}
// extra commands options for telnet debug window
void myDebugCallback() {
char * cmd = myESP.consoleGetLastCommand();
@@ -369,14 +364,13 @@ void WIFIcallback() {
emsuart_init();
}
// Initialize the boiler settings
void _initBoiler() {
// default settings
ems_setThermostatEnabled(BOILER_THERMOSTAT_ENABLED);
Boiler_Status.shower_enabled = BOILER_SHOWER_ENABLED;
Boiler_Status.shower_timer = BOILER_SHOWER_TIMER;
// init boiler
Boiler_Status.wifi_connected = false;
Boiler_Status.boiler_online = true; // assume we have a connection, it will be checked in the loop() anyway
@@ -427,7 +421,7 @@ void setup() {
enableHeartbeat(ems_getLogVerbose());
}
// flash ERR LEDs
// flash LEDs
// Using a faster way to write to pins as digitalWrite does a lot of overhead like pin checking & disabling interrupts
void showLEDs() {
// update Ticker
@@ -466,6 +460,7 @@ void heartbeat() {
}
// enables or disables the heartbeat LED
// using the Ticker library
void enableHeartbeat(bool on) {
heartbeat_state = (on) ? LOW : HIGH;
heartbeat();
@@ -503,8 +498,6 @@ void _showerColdShotStop() {
// Main loop
//
void loop() {
// my myESP to maintain the wifi, mqtt and debugging
yield();
connectionStatus = myESP.loop();
timestamp = millis();
@@ -558,7 +551,7 @@ void loop() {
} else {
// check if the shower has been on too long
if ((((timestamp - Boiler_Shower.timerStart) > SHOWER_MAX_DURATION) && !Boiler_Shower.isColdShot)
&& Boiler_Status.shower_timer) {
&& Boiler_Status.shower_timer) {
_showerColdShotStart();
showerResetTimer.start(); // start the timer for n seconds which will reset the water back to hot
}

View File

@@ -1,7 +1,7 @@
/*
* ems.cpp
* handles all the EMS messages
* handles all the processing of the EMS messages
* Paul Derbyshire - https://github.com/proddy/EMS-ESP-Boiler
*/
@@ -32,7 +32,6 @@ const _EMS_Types EMS_Types[MAX_TYPECALLBACK] =
{EMS_ID_THERMOSTAT, EMS_TYPE_RC20Temperature, "RC20Temperature", 10, _process_RC20Temperature}
};
// reserve space for the data we collect from the Boiler and Thermostat
_EMS_Boiler EMS_Boiler;
_EMS_Thermostat EMS_Thermostat;
@@ -55,8 +54,7 @@ const uint8_t ems_crc_table[] =
0xF7, 0xE9, 0xEB, 0xED, 0xEF, 0xE1, 0xE3, 0xE5, 0xE7
};
extern ESPHelper myESP;
extern ESPHelper myESP; // needed for the DEBUG statements below
#define myDebug(x, ...) myESP.printf(x, ##__VA_ARGS__);
// constants timers
@@ -79,7 +77,7 @@ void ems_init() {
EMS_Sys_Status.emsRefreshed = false;
EMS_Sys_Status.emsPollEnabled = false; // start up with Poll disabled
EMS_Sys_Status.emsThermostatEnabled = true; // there is a RCxx thermostat active
EMS_Sys_Status.emsThermostatEnabled = true; // there is a RCxx thermostat active as default
EMS_Sys_Status.emsLogVerbose = false; // Verbose logging is off
EMS_Thermostat.hour = 0;
@@ -89,9 +87,10 @@ void ems_init() {
EMS_Thermostat.month = 0;
EMS_Thermostat.year = 0;
// UBAParameterWW
EMS_Boiler.wWActivated = false; // Warm Water activated
EMS_Boiler.wWSelTemp = 0; // Warm Water selected temperature
EMS_Boiler.wWCircPump = false; // Warm Water circulation pump Available
EMS_Boiler.wWCircPump = false; // Warm Water circulation pump available
EMS_Boiler.wWDesiredTemp = 0; // Warm Water desired temperature
// UBAMonitorFast
@@ -101,7 +100,7 @@ void ems_init() {
EMS_Boiler.burnGas = false; // Gas on/off
EMS_Boiler.fanWork = false; // Fan on/off
EMS_Boiler.ignWork = false; // Ignition on/off
EMS_Boiler.heatPmp = false; // Circulating pump on/off
EMS_Boiler.heatPmp = false; // Boiler pump on/off
EMS_Boiler.wWHeat = false; // 3-way valve on WW
EMS_Boiler.wWCirc = false; // Circulation on/off
EMS_Boiler.selBurnPow = 0; // Burner max power

View File

@@ -15,15 +15,17 @@
#define EMS_ID_ME 0x0B // Fixed - our device, hardcoded as "Service Key"
// EMS Telegram Types
#define EMS_TYPE_NONE 0x00 // none
#define EMS_TYPE_UBAMonitorFast 0x18 // is an automatic monitor broadcast
#define EMS_TYPE_UBAMonitorSlow 0x19 // is an automatic monitor broadcast
#define EMS_TYPE_UBAMonitorWWMessage 0x34 // is an automatic monitor broadcast
#define EMS_TYPE_UBAParameterWW 0x33 // is an automatic monitor broadcast
#define EMS_TYPE_NONE 0x00 // none
#define EMS_TYPE_UBAMonitorFast 0x18 // is an automatic monitor broadcast
#define EMS_TYPE_UBAMonitorSlow 0x19 // is an automatic monitor broadcast
#define EMS_TYPE_UBAMonitorWWMessage 0x34 // is an automatic monitor broadcast
#define EMS_TYPE_UBAMaintenanceStatusMessage 0x1c // is an automatic monitor broadcast
#define EMS_TYPE_UBAParameterWW 0x33
#define EMS_TYPE_UBATotalUptimeMessage 0x14
#define EMS_TYPE_UBAMaintenanceSettingsMessage 0x15
#define EMS_TYPE_UBAParametersMessage 0x16
#define EMS_TYPE_UBAMaintenanceStatusMessage 0x1c
// EMS Telegram types from Thermostat
// types 1A and 35 and used for errors from Thermostat

View File

@@ -16,8 +16,7 @@ _EMSRxBuf * pEMSRxBuf;
_EMSRxBuf * paEMSRxBuf[EMS_MAXBUFFERS];
uint8_t emsRxBufIdx = 0;
// queues
os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen];
os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue
//
// Main interrupt handler
@@ -27,15 +26,14 @@ static void emsuart_rx_intr_handler(void * para) {
static uint16_t length;
static uint8_t uart_buffer[EMS_MAXBUFFERSIZE];
// is a new buffer? if so init the thing
// is a new buffer? if so init the thing for a new telegram
if (EMS_Sys_Status.emsRxStatus == EMS_RX_IDLE) {
EMS_Sys_Status.emsRxStatus = EMS_RX_ACTIVE; // status set to active
length = 0;
}
// fill IRQ buffer, by emptying FIFO
// fill IRQ buffer, by emptying Rx FIFO
if (U0IS & ((1 << UIFF) | (1 << UITO) | (1 << UIBD))) {
// get data from Rx
while ((USS(EMSUART_UART) >> USRXC) & 0xFF) {
uart_buffer[length++] = USF(EMSUART_UART);
}
@@ -46,10 +44,8 @@ static void emsuart_rx_intr_handler(void * para) {
}
// BREAK detection = End of EMS data block
if (USIS(EMSUART_UART) & ((1 << UIBD))) {
// disable all interrupts and clear them
ETS_UART_INTR_DISABLE();
ETS_UART_INTR_DISABLE(); // disable all interrupts and clear them
U0IC = (1 << UIBD); // INT clear the BREAK detect interrupt
@@ -126,13 +122,11 @@ void ICACHE_FLASH_ATTR emsuart_init() {
USIE(EMSUART_UART) = 0; // disable all interrupts
// enable rx break, fifo full and timeout.
// not frame error UIFR or overflow UIOF. Frame errors are too frequent
// and overflow never happens because our buffer is only max 32 bytes
// not frame error UIFR (because they are too frequent) or overflow UIOF because our buffer is only max 32 bytes
USIE(EMSUART_UART) = (1 << UIBD) | (1 << UIFF) | (1 << UITO);
// set up interrupt callbacks for Rx and Tx
// set up interrupt callbacks for Rx
system_os_task(emsuart_recvTask, EMSUART_recvTaskPrio, recvTaskQueue, EMSUART_recvTaskQueueLen);
//system_os_task(emsuart_sendTask, sendTaskPrio, sendTaskQueue, sendTaskQueueLen);
// disable esp debug which will go to Tx and mess up the line
// system_set_os_print(0); // https://github.com/espruino/Espruino/issues/655
@@ -140,7 +134,7 @@ void ICACHE_FLASH_ATTR emsuart_init() {
ETS_UART_INTR_ATTACH(emsuart_rx_intr_handler, NULL);
ETS_UART_INTR_ENABLE();
// when all ready swap RX and TX (to use GPIO13 (D7) and GPIO15 (D8) )
// when all ready swap Rx and Tx pins (to use GPIO13 (D7) and GPIO15 (D8) )
system_uart_swap();
}
@@ -157,14 +151,15 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() {
USC0(EMSUART_UART) |= (tmp); // set bits
USC0(EMSUART_UART) &= ~(tmp); // clear bits
// To create a 11-bit <BRK> we set TXD_BRK bit so the break signal will automatically be sent when the tx fifo is empty
USC0(EMSUART_UART) |= (1 << UCBRK); // set bit
delayMicroseconds(EMS_TX_BRK_WAIT);
// To create a 11-bit <BRK> we set TXD_BRK bit so the break signal will
// automatically be sent when the tx fifo is empty
USC0(EMSUART_UART) |= (1 << UCBRK); // set bit
delayMicroseconds(EMS_TX_BRK_WAIT); // 2070 - based on trial and error using an oscilloscope
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear bit
}
/*
* Send to tx, ending with a BRK
/*
* Send to Tx, ending with a BRK
*/
void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
for (uint8_t i = 0; i < len; i++) {
@@ -174,7 +169,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
}
/*
* Send the Poll (our ID) to Tx as a single byte and ending with a <BRK>
* Send the Poll (our own ID) to Tx as a single byte and end with a <BRK>
*/
void ICACHE_FLASH_ATTR emsaurt_tx_poll() {
USF(EMSUART_UART) = EMS_ID_ME;

View File

@@ -13,11 +13,11 @@
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
#define EMS_MAXBUFFERS 4 // 4 buffers for circular filling to avoid collisions
#define EMS_MAXBUFFERSIZE 128 // max size of the buffer. packets are 32 bits
#define EMS_MAXBUFFERSIZE 128 // max size of the buffer. packets are max 32 bytes
// for how long we drop the Tx signal to create a 11-bit Break of zeros
// this is how long we drop the Tx signal to create a 11-bit Break of zeros
// At 9600 baud, 11 bits will be 1144 microseconds
// the BRK from UBA is roughly 1.039ms, so accounting for hardware lag use 2078 (for half-duplex) - 8 (lag)
// the BRK from Boiler is roughly 1.039ms, so accounting for hardware lag using around 2078 (for half-duplex) - 8 (lag)
#define EMS_TX_BRK_WAIT 2070
#define EMSUART_recvTaskPrio 1