add tx_mode back as new tx code can cause resets

This commit is contained in:
Paul
2019-06-26 22:02:16 +02:00
parent 5740a8ee0d
commit 4e50d13bd1
8 changed files with 171 additions and 78 deletions

View File

@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added back -DCRASH in Debug build target for capturing any ESP8266 stack dumps during crashes
- Web Interface, for checking stats and setting wifi credentials. See wiki for more details.
- reset firmware option. If the reset button on the ESP is pressed during boot up sequence (the LED is flashing very fast) all settings are erased and goes into AP mode.
- Added tx_mode back with options 0,1 and 2 until we've fixed option 2 that works for everyone and doesn't reset ESP
### Fixed

View File

@@ -9,7 +9,7 @@
#ifndef MyEMS_h
#define MyEMS_h
#define MYESP_VERSION "1.1.18"
#define MYESP_VERSION "1.1.19"
#include <ArduinoJson.h>
#include <ArduinoOTA.h>

View File

@@ -106,6 +106,7 @@ command_t project_cmds[] = {
{true, "shower_alert <on | off>", "stop hot water to send 3 cold burst warnings after max shower time is exceeded"},
{true, "publish_time <seconds>", "set frequency for publishing data to MQTT (0=off)"},
{true, "heating_circuit <1 | 2>", "set the main thermostat HC to work with (if using multiple heating circuits)"},
{true, "tx_mode <n>", "0=classic ems logic, 1=@kwertie01 ems+ logic, 2=@susisstrolch logic, 3=@philrich logic for Junkers"},
{false, "info", "show current captured on the devices"},
{false, "log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
@@ -323,7 +324,7 @@ void showInfo() {
myDebug_P(PSTR(" System logging set to Verbose"));
} else if (sysLog == EMS_SYS_LOGGING_THERMOSTAT) {
myDebug_P(PSTR(" System logging set to Thermostat only"));
} else if (sysLog == EMS_SYS_LOGGING_SOLARMODULE ) {
} else if (sysLog == EMS_SYS_LOGGING_SOLARMODULE) {
myDebug_P(PSTR(" System logging set to Solar Module only"));
} else {
myDebug_P(PSTR(" System logging set to None"));
@@ -1032,6 +1033,8 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) {
EMSESP_Status.shower_alert = json["shower_alert"];
EMSESP_Status.publish_time = json["publish_time"] | DEFAULT_PUBLISHTIME;
ems_setTxMode(json["tx_mode"]);
EMSESP_Status.listen_mode = json["listen_mode"];
ems_setTxDisabled(EMSESP_Status.listen_mode);
@@ -1053,6 +1056,7 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) {
json["shower_alert"] = EMSESP_Status.shower_alert;
json["publish_time"] = EMSESP_Status.publish_time;
json["heating_circuit"] = EMSESP_Status.heating_circuit;
json["tx_mode"] = ems_getTxMode();
return true;
}
@@ -1182,6 +1186,12 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
myDebug_P(PSTR("Error. Usage: set heating_circuit <1 | 2>"));
}
}
// tx delay/ tx mode
if (((strcmp(setting, "tx_mode") == 0) || (strcmp(setting, "tx_delay") == 0)) && (wc == 2)) {
ems_setTxMode(atoi(value));
ok = true;
}
}
if (action == MYESP_FSACTION_LIST) {
@@ -1208,6 +1218,7 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
myDebug_P(PSTR(" shower_timer=%s"), EMSESP_Status.shower_timer ? "on" : "off");
myDebug_P(PSTR(" shower_alert=%s"), EMSESP_Status.shower_alert ? "on" : "off");
myDebug_P(PSTR(" publish_time=%d"), EMSESP_Status.publish_time);
myDebug_P(PSTR(" tx_mode=%d"), ems_getTxMode());
}
return ok;
@@ -1301,9 +1312,9 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
ems_setLogging(EMS_SYS_LOGGING_THERMOSTAT);
ok = true;
} else if (strcmp(second_cmd, "s") == 0) {
ems_setLogging(EMS_SYS_LOGGING_SOLARMODULE );
ems_setLogging(EMS_SYS_LOGGING_SOLARMODULE);
ok = true;
}else if (strcmp(second_cmd, "r") == 0) {
} else if (strcmp(second_cmd, "r") == 0) {
ems_setLogging(EMS_SYS_LOGGING_RAW);
ok = true;
} else if (strcmp(second_cmd, "n") == 0) {
@@ -1553,7 +1564,7 @@ void WebCallback(char * body) {
strlcpy(body, "<b>EMS devices found:</b><br>", MYESP_MAXCHARBUFFER);
char buffer[MYESP_MAXCHARBUFFER] = {0};
uint8_t num_devices = ems_printDevices_s(buffer, MYESP_MAXCHARBUFFER);
uint8_t num_devices = ems_printDevices_s(buffer, MYESP_MAXCHARBUFFER);
if (num_devices == 0) {
strlcat(body, "no compatible EMS devices detected yet. (wait a few seconds)", MYESP_MAXCHARBUFFER);
} else {

View File

@@ -234,6 +234,7 @@ void ems_init() {
EMS_Sys_Status.emsPollFrequency = 0;
EMS_Sys_Status.txRetryCount = 0;
EMS_Sys_Status.emsReverse = false;
EMS_Sys_Status.emsTxMode = 0;
// thermostat
EMS_Thermostat.setpoint_roomTemp = EMS_VALUE_SHORT_NOTSET;
@@ -304,17 +305,17 @@ void ems_init() {
EMS_Boiler.pump_mod_min = EMS_VALUE_INT_NOTSET; // Boiler circuit pump modulation min. power
// Solar Module values
EMS_SolarModule.collectorTemp = EMS_VALUE_SHORT_NOTSET; // collector temp from SM10/SM100
EMS_SolarModule.bottomTemp = EMS_VALUE_SHORT_NOTSET; // bottom temp from SM10/SM100
EMS_SolarModule.pumpModulation = EMS_VALUE_INT_NOTSET; // modulation solar pump SM10/SM100
EMS_SolarModule.pump = EMS_VALUE_INT_NOTSET; // pump active
EMS_SolarModule.setpoint_maxBottomTemp = EMS_VALUE_SHORT_NOTSET; //setpoint for maximum solar boiler temperature
EMS_SolarModule.EnergyLastHour = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.EnergyToday = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.EnergyTotal = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.device_id = EMS_ID_NONE;
EMS_SolarModule.model_id = EMS_MODEL_NONE;
EMS_SolarModule.product_id = EMS_ID_NONE;
EMS_SolarModule.collectorTemp = EMS_VALUE_SHORT_NOTSET; // collector temp from SM10/SM100
EMS_SolarModule.bottomTemp = EMS_VALUE_SHORT_NOTSET; // bottom temp from SM10/SM100
EMS_SolarModule.pumpModulation = EMS_VALUE_INT_NOTSET; // modulation solar pump SM10/SM100
EMS_SolarModule.pump = EMS_VALUE_INT_NOTSET; // pump active
EMS_SolarModule.setpoint_maxBottomTemp = EMS_VALUE_SHORT_NOTSET; //setpoint for maximum solar boiler temperature
EMS_SolarModule.EnergyLastHour = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.EnergyToday = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.EnergyTotal = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.device_id = EMS_ID_NONE;
EMS_SolarModule.model_id = EMS_MODEL_NONE;
EMS_SolarModule.product_id = EMS_ID_NONE;
// Other EMS devices values
EMS_Other.HPModulation = EMS_VALUE_INT_NOTSET;
@@ -353,6 +354,23 @@ bool ems_getPoll() {
return EMS_Sys_Status.emsPollEnabled;
}
void ems_setTxMode(uint8_t mode) {
EMS_Sys_Status.emsTxMode = mode;
// special case for Junkers. If tx_mode is 3 then set the reverse poll flag
// https://github.com/proddy/EMS-ESP/issues/103#issuecomment-495945850
if (mode == 3) {
EMS_Sys_Status.emsReverse = true;
myDebug_P(PSTR("Forcing emsReverse for Junkers"));
} else {
EMS_Sys_Status.emsReverse = false;
}
}
uint8_t ems_getTxMode() {
return EMS_Sys_Status.emsTxMode;
}
bool ems_getEmsRefreshed() {
return EMS_Sys_Status.emsRefreshed;
}
@@ -428,11 +446,11 @@ void ems_setLogging(_EMS_SYS_LOGGING loglevel) {
myDebug_P(PSTR("System Logging set to Thermostat only"));
} else if (loglevel == EMS_SYS_LOGGING_SOLARMODULE) {
myDebug_P(PSTR("System Logging set to Solar Module only"));
}else if (loglevel == EMS_SYS_LOGGING_RAW) {
} else if (loglevel == EMS_SYS_LOGGING_RAW) {
myDebug_P(PSTR("System Logging set to Raw mode"));
}
}
}
}
/**
* Calculate CRC checksum using lookup table for speed
@@ -1506,12 +1524,10 @@ void _process_ISM1StatusMessage(_EMS_RxTelegram * EMS_RxTelegram) {
* Junkers ISM1 Solar Module - type 0x0001 EMS+ for setting values
*/
void _process_ISM1Set(_EMS_RxTelegram * EMS_RxTelegram) {
if (EMS_RxTelegram->offset == 6) {
// e.g. 90 30 FF 06 00 01 50 (CRC=2C)
// to implement: change max solar boiler temperature
EMS_SolarModule.setpoint_maxBottomTemp = _toByte(0);
// e.g. 90 30 FF 06 00 01 50 (CRC=2C)
// to implement: change max solar boiler temperature
EMS_SolarModule.setpoint_maxBottomTemp = _toByte(0);
}
}

View File

@@ -79,12 +79,12 @@ typedef enum {
/* EMS logging */
typedef enum {
EMS_SYS_LOGGING_NONE, // no messages
EMS_SYS_LOGGING_RAW, // raw data mode
EMS_SYS_LOGGING_BASIC, // only basic read/write messages
EMS_SYS_LOGGING_THERMOSTAT, // only telegrams sent from thermostat
EMS_SYS_LOGGING_NONE, // no messages
EMS_SYS_LOGGING_RAW, // raw data mode
EMS_SYS_LOGGING_BASIC, // only basic read/write messages
EMS_SYS_LOGGING_THERMOSTAT, // only telegrams sent from thermostat
EMS_SYS_LOGGING_SOLARMODULE, // only telegrams sent from thermostat
EMS_SYS_LOGGING_VERBOSE // everything
EMS_SYS_LOGGING_VERBOSE // everything
} _EMS_SYS_LOGGING;
// status/counters since last power on
@@ -104,6 +104,7 @@ typedef struct {
bool emsTxDisabled; // true to prevent all Tx
uint8_t txRetryCount; // # times the last Tx was re-sent
bool emsReverse; // if true, poll logic is reversed
uint8_t emsTxMode; // handles Tx logic
} _EMS_Sys_Status;
// The Tx send package
@@ -267,11 +268,11 @@ typedef struct {
// SM Solar Module - SM10/SM100/ISM1
typedef struct {
int16_t collectorTemp; // collector temp
int16_t bottomTemp; // bottom temp
uint8_t pumpModulation; // modulation solar pump
uint8_t pump; // pump active
int16_t setpoint_maxBottomTemp; // setpoint for maximum collector temp
int16_t collectorTemp; // collector temp
int16_t bottomTemp; // bottom temp
uint8_t pumpModulation; // modulation solar pump
uint8_t pump; // pump active
int16_t setpoint_maxBottomTemp; // setpoint for maximum collector temp
int16_t EnergyLastHour;
int16_t EnergyToday;
int16_t EnergyTotal;
@@ -331,20 +332,22 @@ void ems_testTelegram(uint8_t test_num);
void ems_startupTelegrams();
bool ems_checkEMSBUSAlive();
void ems_clearDeviceList();
void ems_setTxMode(uint8_t mode);
void ems_setThermostatTemp(float temperature, uint8_t temptype = 0);
void ems_setThermostatMode(uint8_t mode);
void ems_setThermostatHC(uint8_t hc);
void ems_setWarmWaterTemp(uint8_t temperature);
void ems_setFlowTemp(uint8_t temperature);
void ems_setWarmWaterActivated(bool activated);
void ems_setWarmTapWaterActivated(bool activated);
void ems_setPoll(bool b);
void ems_setLogging(_EMS_SYS_LOGGING loglevel);
void ems_setEmsRefreshed(bool b);
void ems_setWarmWaterModeComfort(uint8_t comfort);
void ems_setModels();
void ems_setTxDisabled(bool b);
void ems_setThermostatTemp(float temperature, uint8_t temptype = 0);
void ems_setThermostatMode(uint8_t mode);
void ems_setThermostatHC(uint8_t hc);
void ems_setWarmWaterTemp(uint8_t temperature);
void ems_setFlowTemp(uint8_t temperature);
void ems_setWarmWaterActivated(bool activated);
void ems_setWarmTapWaterActivated(bool activated);
void ems_setPoll(bool b);
void ems_setLogging(_EMS_SYS_LOGGING loglevel);
void ems_setEmsRefreshed(bool b);
void ems_setWarmWaterModeComfort(uint8_t comfort);
void ems_setModels();
void ems_setTxDisabled(bool b);
uint8_t ems_getTxMode();
char * ems_getThermostatDescription(char * buffer);
char * ems_getBoilerDescription(char * buffer);

View File

@@ -159,6 +159,35 @@ void ICACHE_FLASH_ATTR emsuart_start() {
ETS_UART_INTR_ENABLE();
}
/*
* Send a BRK signal
* Which is a 11-bit set of zero's (11 cycles)
*/
void ICACHE_FLASH_ATTR emsuart_tx_brk() {
uint32_t tmp;
// must make sure Tx FIFO is empty
while (((USS(EMSUART_UART) >> USTXC) & 0xFF) != 0)
;
tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask
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
tmp = (1 << UCBRK);
USC0(EMSUART_UART) |= (tmp); // set bit
if (EMS_Sys_Status.emsTxMode <= 1) { // classic mode and ems+ (0, 1)
delayMicroseconds(EMSUART_TX_BRK_WAIT);
} else if (EMS_Sys_Status.emsTxMode == 3) { // junkers mode
delayMicroseconds(EMSUART_TX_WAIT_BRK - EMSUART_TX_LAG); // 1144 (11 Bits)
}
USC0(EMSUART_UART) &= ~(tmp); // clear bit
}
/*
* Send to Tx, ending with a <BRK>
*/
@@ -166,7 +195,33 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
if (len == 0)
return;
/*
// temp code until we get mode 2 working without resets
if (EMS_Sys_Status.emsTxMode == 0) { // classic mode logic
for (uint8_t i = 0; i < len; i++) {
USF(EMSUART_UART) = buf[i];
}
emsuart_tx_brk(); // send <BRK>
} else if (EMS_Sys_Status.emsTxMode == 1) { // With extra tx delay for EMS+
for (uint8_t i = 0; i < len; i++) {
USF(EMSUART_UART) = buf[i];
delayMicroseconds(EMSUART_TX_BRK_WAIT); // https://github.com/proddy/EMS-ESP/issues/23#
}
emsuart_tx_brk(); // send <BRK>
} else if (EMS_Sys_Status.emsTxMode == 3) { // Junkers logic by @philrich
for (uint8_t i = 0; i < len; i++) {
USF(EMSUART_UART) = buf[i];
// just to be safe wait for tx fifo empty (needed?)
while (((USS(EMSUART_UART) >> USTXC) & 0xff) != 0)
;
// wait until bits are sent on wire
delayMicroseconds(EMSUART_TX_WAIT_BYTE - EMSUART_TX_LAG + EMSUART_TX_WAIT_GAP);
}
emsuart_tx_brk(); // send <BRK>
} else if (EMS_Sys_Status.emsTxMode == 2) {
/*
* based on code from https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch
* we emit the whole telegram, with Rx interrupt disabled, collecting busmaster response in FIFO.
* after sending the last char we poll the Rx status until either
@@ -174,42 +229,43 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
* - <BRK> is detected
* At end of receive we re-enable Rx-INT and send a Tx-BRK in loopback mode.
*/
ETS_UART_INTR_DISABLE(); // disable rx interrupt
ETS_UART_INTR_DISABLE(); // disable rx interrupt
// clear Rx status register
USC0(EMSUART_UART) |= (1 << UCRXRST); // reset uart rx fifo
emsuart_flush_fifos();
// clear Rx status register
USC0(EMSUART_UART) |= (1 << UCRXRST); // reset uart rx fifo
emsuart_flush_fifos();
// throw out the telegram...
for (uint8_t i = 0; i < len;) {
USF(EMSUART_UART) = buf[i++]; // send each Tx byte
// wait for echo from busmaster
while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < i || (USIS(EMSUART_UART) & (1 << UIBD)))) {
delayMicroseconds(EMSUART_BIT_TIME); // burn CPU cycles...
}
}
// we got the whole telegram in the Rx buffer
// on Rx-BRK (bus collision), we simply enable Rx and leave it
// otherwise we send the final Tx-BRK in the loopback and re=enable Rx-INT.
// worst case, we'll see an additional Rx-BRK...
if (!(USIS(EMSUART_UART) & (1 << UIBD))) {
// no bus collision - send terminating BRK signal
USC0(EMSUART_UART) |= (1 << UCLBE); // enable loopback
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
// wait until BRK detected...
while (!(USIS(EMSUART_UART) & (1 << UIBD))) {
delayMicroseconds(EMSUART_BIT_TIME);
// throw out the telegram...
for (uint8_t i = 0; i < len;) {
USF(EMSUART_UART) = buf[i++]; // send each Tx byte
// wait for echo from busmaster
while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < i || (USIS(EMSUART_UART) & (1 << UIBD)))) {
delayMicroseconds(EMSUART_BIT_TIME); // burn CPU cycles...
}
}
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK>
// we got the whole telegram in the Rx buffer
// on Rx-BRK (bus collision), we simply enable Rx and leave it
// otherwise we send the final Tx-BRK in the loopback and re=enable Rx-INT.
// worst case, we'll see an additional Rx-BRK...
if (!(USIS(EMSUART_UART) & (1 << UIBD))) {
// no bus collision - send terminating BRK signal
USC0(EMSUART_UART) |= (1 << UCLBE); // enable loopback
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
USC0(EMSUART_UART) &= ~(1 << UCLBE); // disable loopback
// wait until BRK detected...
while (!(USIS(EMSUART_UART) & (1 << UIBD))) {
delayMicroseconds(EMSUART_BIT_TIME);
}
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK>
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
USC0(EMSUART_UART) &= ~(1 << UCLBE); // disable loopback
}
ETS_UART_INTR_ENABLE(); // receive anything from FIFO...
}
ETS_UART_INTR_ENABLE(); // receive anything from FIFO...
}
/*

View File

@@ -18,6 +18,12 @@
#define EMSUART_BIT_TIME 104 // bit time @9600 baud
#define EMSUART_TX_BRK_WAIT 2070 // the BRK from Boiler master is roughly 1.039ms, so accounting for hardware lag using around 2078 (for half-duplex) - 8 (lag)
#define EMSUART_TX_WAIT_BYTE EMSUART_BIT_TIME * 10 // Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit)
#define EMSUART_TX_WAIT_BRK EMSUART_BIT_TIME * 11 // Time to send a BRK Signal (11 Bit)
#define EMSUART_TX_WAIT_GAP EMSUART_BIT_TIME * 7 // Gap between to Bytes
#define EMSUART_TX_LAG 8
#define EMSUART_recvTaskPrio 1
#define EMSUART_recvTaskQueueLen 64

View File

@@ -6,5 +6,5 @@
#pragma once
#define APP_NAME "EMS-ESP"
#define APP_VERSION "1.8.1b4"
#define APP_VERSION "1.8.1b5"
#define APP_HOSTNAME "ems-esp"