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

@@ -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"