mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
merge Junkers Tx logic
This commit is contained in:
15
CHANGELOG.md
15
CHANGELOG.md
@@ -5,20 +5,25 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [1.8.0dev] 2019-
|
## [1.8.0dev] 2019-05-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- MM50 Mixer
|
- MM50 Mixer
|
||||||
|
- tx_delay takes a value from 0 to 3 for the different Tx logic
|
||||||
|
|
||||||
|
0 = original classic ems logic
|
||||||
|
|
||||||
|
1 = @kwertie01 ems+ logic (https://github.com/proddy/EMS-ESP/issues/23#issuecomment-476872291)
|
||||||
|
|
||||||
|
2 = @susisstrolch logic [(pull request 113)](https://github.com/proddy/EMS-ESP/pull/113)
|
||||||
|
|
||||||
|
3 = @philrich logic for Junkers (https://github.com/proddy/EMS-ESP/files/3190563/ems-delay-rev-poll.patch.txt)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- runtime exceptions with latest 2.5.1 arduino core
|
- runtime exceptions with latest 2.5.1 arduino core
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Improved Tx code, by @Susis Strolch [(pull request 113)](https://github.com/proddy/EMS-ESP/pull/113). Use `set_txdelay 2`
|
|
||||||
|
|
||||||
## [1.7.0] 2019-05-11
|
## [1.7.0] 2019-05-11
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -496,7 +496,7 @@ void MyESP::_consoleShowHelp() {
|
|||||||
} else {
|
} else {
|
||||||
myDebug_P(PSTR("* Hostname: %s (%s)"), _getESPhostname().c_str(), WiFi.localIP().toString().c_str());
|
myDebug_P(PSTR("* Hostname: %s (%s)"), _getESPhostname().c_str(), WiFi.localIP().toString().c_str());
|
||||||
myDebug_P(PSTR("* WiFi SSID: %s (signal %d%%)"), WiFi.SSID().c_str(), getWifiQuality());
|
myDebug_P(PSTR("* WiFi SSID: %s (signal %d%%)"), WiFi.SSID().c_str(), getWifiQuality());
|
||||||
myDebug_P(PSTR("* MQTT is %s"), mqttClient.connected() ? "connected" : "disconnected");
|
myDebug_P(PSTR("* MQTT %s"), mqttClient.connected() ? "connected" : "disconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
myDebug_P(PSTR("*"));
|
myDebug_P(PSTR("*"));
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ command_t project_cmds[] = {
|
|||||||
{true, "shower_alert <on | off>", "send a warning of cold water after shower time is exceeded"},
|
{true, "shower_alert <on | off>", "send a warning of cold water after shower time is exceeded"},
|
||||||
{true, "publish_wait <seconds>", "set frequency for publishing to MQTT"},
|
{true, "publish_wait <seconds>", "set frequency for publishing to MQTT"},
|
||||||
{true, "heating_circuit <1 | 2>", "set the thermostat HC to work with if using multiple heating circuits"},
|
{true, "heating_circuit <1 | 2>", "set the thermostat HC to work with if using multiple heating circuits"},
|
||||||
{true, "tx_delay <n>", "0=normal, 1=ems+, 2=new logic"},
|
{true, "tx_delay <n>", "0=classic ems logic, 1=@kwertie01 ems+ logic, 2=@susisstrolch logic, 3=@philrich logic for Junkers"},
|
||||||
|
|
||||||
{false, "info", "show data captured on the EMS bus"},
|
{false, "info", "show data captured on the EMS bus"},
|
||||||
{false, "log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
|
{false, "log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
|
||||||
@@ -339,10 +339,10 @@ void showInfo() {
|
|||||||
if (ems_getBusConnected()) {
|
if (ems_getBusConnected()) {
|
||||||
myDebug_P(PSTR(" Bus is connected"));
|
myDebug_P(PSTR(" Bus is connected"));
|
||||||
|
|
||||||
myDebug_P(PSTR(" Rx: Poll=%d microsecs, # Rx telegrams read=%d, # CRC errors=%d"), ems_getPollFrequency(), EMS_Sys_Status.emsRxPgks, EMS_Sys_Status.emxCrcErr);
|
myDebug_P(PSTR(" Rx: Poll=%d microseconds, # Rx telegrams read=%d, # CRC errors=%d"), ems_getPollFrequency(), EMS_Sys_Status.emsRxPgks, EMS_Sys_Status.emxCrcErr);
|
||||||
|
|
||||||
if (ems_getTxCapable()) {
|
if (ems_getTxCapable()) {
|
||||||
myDebug_P(PSTR(" Tx: available, Tx delay is %d, # Tx telegrams sent=%d"), ems_getTxDelay(), EMS_Sys_Status.emsTxPkgs);
|
myDebug_P(PSTR(" Tx: available, Tx delay is %d, # successful write commands=%d"), ems_getTxDelay(), EMS_Sys_Status.emsTxPkgs);
|
||||||
} else {
|
} else {
|
||||||
myDebug_P(PSTR(" Tx: no signal"));
|
myDebug_P(PSTR(" Tx: no signal"));
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/ems.cpp
27
src/ems.cpp
@@ -221,6 +221,7 @@ void ems_init() {
|
|||||||
EMS_Sys_Status.emsPollFrequency = 0;
|
EMS_Sys_Status.emsPollFrequency = 0;
|
||||||
EMS_Sys_Status.txRetryCount = 0;
|
EMS_Sys_Status.txRetryCount = 0;
|
||||||
EMS_Sys_Status.emsTxDelay = 0;
|
EMS_Sys_Status.emsTxDelay = 0;
|
||||||
|
EMS_Sys_Status.emsReverse = false;
|
||||||
|
|
||||||
// thermostat
|
// thermostat
|
||||||
EMS_Thermostat.setpoint_roomTemp = EMS_VALUE_SHORT_NOTSET;
|
EMS_Thermostat.setpoint_roomTemp = EMS_VALUE_SHORT_NOTSET;
|
||||||
@@ -331,6 +332,13 @@ bool ems_getPoll() {
|
|||||||
|
|
||||||
void ems_setTxDelay(uint8_t delay) {
|
void ems_setTxDelay(uint8_t delay) {
|
||||||
EMS_Sys_Status.emsTxDelay = delay;
|
EMS_Sys_Status.emsTxDelay = delay;
|
||||||
|
|
||||||
|
// special case for Junkers. If tx_delay is 3 then set the reverse poll flag
|
||||||
|
// https://github.com/proddy/EMS-ESP/issues/103#issuecomment-495945850
|
||||||
|
if (delay == 3) {
|
||||||
|
EMS_Sys_Status.emsReverse = true;
|
||||||
|
myDebug_P(PSTR("Setting for Tx Junkers logic and enabled the poll reverse flag"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ems_getTxDelay() {
|
uint8_t ems_getTxDelay() {
|
||||||
@@ -557,8 +565,9 @@ void _ems_sendTelegram() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create header
|
// create the header
|
||||||
EMS_TxTelegram.data[0] = EMS_ID_ME; // src
|
EMS_TxTelegram.data[0] = (EMS_Sys_Status.emsReverse) ? EMS_ID_ME | 0x80 : EMS_ID_ME; // src
|
||||||
|
|
||||||
// dest
|
// dest
|
||||||
if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) {
|
if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) {
|
||||||
EMS_TxTelegram.data[1] = EMS_TxTelegram.dest;
|
EMS_TxTelegram.data[1] = EMS_TxTelegram.dest;
|
||||||
@@ -672,9 +681,10 @@ void _ems_readTelegram(uint8_t * telegram, uint8_t length) {
|
|||||||
// create the Rx package
|
// create the Rx package
|
||||||
static _EMS_RxTelegram EMS_RxTelegram;
|
static _EMS_RxTelegram EMS_RxTelegram;
|
||||||
static uint32_t _last_emsPollFrequency = 0;
|
static uint32_t _last_emsPollFrequency = 0;
|
||||||
EMS_RxTelegram.telegram = telegram;
|
|
||||||
EMS_RxTelegram.timestamp = millis();
|
EMS_RxTelegram.telegram = telegram;
|
||||||
EMS_RxTelegram.length = length;
|
EMS_RxTelegram.timestamp = millis();
|
||||||
|
EMS_RxTelegram.length = length;
|
||||||
|
|
||||||
// check if we just received a single byte
|
// check if we just received a single byte
|
||||||
// it could well be a Poll request from the boiler for us, which will have a value of 0x8B (0x0B | 0x80)
|
// it could well be a Poll request from the boiler for us, which will have a value of 0x8B (0x0B | 0x80)
|
||||||
@@ -684,12 +694,11 @@ void _ems_readTelegram(uint8_t * telegram, uint8_t length) {
|
|||||||
EMS_Sys_Status.emsPollFrequency = (timenow_microsecs - _last_emsPollFrequency);
|
EMS_Sys_Status.emsPollFrequency = (timenow_microsecs - _last_emsPollFrequency);
|
||||||
_last_emsPollFrequency = timenow_microsecs;
|
_last_emsPollFrequency = timenow_microsecs;
|
||||||
|
|
||||||
// check first for a Poll for us
|
|
||||||
uint8_t value = telegram[0]; // 1st byte of data package
|
uint8_t value = telegram[0]; // 1st byte of data package
|
||||||
|
|
||||||
if ((value & 0x7F) == EMS_ID_ME) {
|
// check first for a Poll for us
|
||||||
EMS_Sys_Status.emsTxCapable = true;
|
// the poll has the MSB set - seems to work on both EMS and Junkers
|
||||||
|
if (value == (EMS_ID_ME | 0x80)) {
|
||||||
// do we have something to send thats waiting in the Tx queue?
|
// do we have something to send thats waiting in the Tx queue?
|
||||||
// if so send it if the Queue is not in a wait state
|
// if so send it if the Queue is not in a wait state
|
||||||
if ((!EMS_TxQueue.isEmpty()) && (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_IDLE)) {
|
if ((!EMS_TxQueue.isEmpty()) && (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_IDLE)) {
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ typedef struct {
|
|||||||
bool emsTxDisabled; // true to prevent all Tx
|
bool emsTxDisabled; // true to prevent all Tx
|
||||||
uint8_t txRetryCount; // # times the last Tx was re-sent
|
uint8_t txRetryCount; // # times the last Tx was re-sent
|
||||||
uint8_t emsTxDelay; // handles Tx logic
|
uint8_t emsTxDelay; // handles Tx logic
|
||||||
|
bool emsReverse; // if true, poll logic is reversed
|
||||||
} _EMS_Sys_Status;
|
} _EMS_Sys_Status;
|
||||||
|
|
||||||
// The Tx send package
|
// The Tx send package
|
||||||
|
|||||||
@@ -175,7 +175,11 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() {
|
|||||||
// automatically be sent when the tx fifo is empty
|
// automatically be sent when the tx fifo is empty
|
||||||
tmp = (1 << UCBRK);
|
tmp = (1 << UCBRK);
|
||||||
USC0(EMSUART_UART) |= (tmp); // set bit
|
USC0(EMSUART_UART) |= (tmp); // set bit
|
||||||
delayMicroseconds(EMSUART_TX_BRK_WAIT);
|
if (EMS_Sys_Status.emsTxDelay <= 2) {
|
||||||
|
delayMicroseconds(EMSUART_TX_BRK_WAIT); // classic mode
|
||||||
|
} else if (EMS_Sys_Status.emsTxDelay == 3) {
|
||||||
|
delayMicroseconds(EMSUART_TX_WAIT_BRK - EMSUART_TX_LAG); // 1144 (11 Bits)
|
||||||
|
}
|
||||||
USC0(EMSUART_UART) &= ~(tmp); // clear bit
|
USC0(EMSUART_UART) &= ~(tmp); // clear bit
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,21 +197,32 @@ static inline void ICACHE_FLASH_ATTR emsuart_loopback(bool enable) {
|
|||||||
* 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) {
|
void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
|
||||||
// backwards compatibility
|
if (EMS_Sys_Status.emsTxDelay == 0) { // Classic logic
|
||||||
if (EMS_Sys_Status.emsTxDelay < 2) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
|
USF(EMSUART_UART) = buf[i];
|
||||||
|
}
|
||||||
|
emsuart_tx_brk(); // send <BRK>
|
||||||
|
} else if (EMS_Sys_Status.emsTxDelay == 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.emsTxDelay == 3) { // Junkers logic by @philrich
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
USF(EMSUART_UART) = buf[i];
|
USF(EMSUART_UART) = buf[i];
|
||||||
|
|
||||||
// check if we need to force a delay to slow down Tx
|
// just to be safe wait for tx fifo empty (needed?)
|
||||||
// https://github.com/proddy/EMS-ESP/issues/23#
|
while (((USS(EMSUART_UART) >> USTXC) & 0xff) != 0)
|
||||||
if (EMS_Sys_Status.emsTxDelay == 1) {
|
;
|
||||||
delayMicroseconds(EMSUART_TX_BRK_WAIT);
|
|
||||||
}
|
// wait until bits are sent on wire
|
||||||
|
delayMicroseconds(EMSUART_TX_WAIT_BYTE - EMSUART_TX_LAG + EMSUART_TX_WAIT_GAP);
|
||||||
}
|
}
|
||||||
emsuart_tx_brk(); // send <BRK>
|
emsuart_tx_brk(); // send <BRK>
|
||||||
} else {
|
} else if (EMS_Sys_Status.emsTxDelay == 2) { // smart Tx - take two - https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch
|
||||||
/* smart Tx - take two - https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch
|
|
||||||
* changed logic...
|
/*
|
||||||
* we emit the whole telegram, with Rx interrupt disabled, collecting busmaster response in FIFO.
|
* 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
|
* after sending the last char we poll the Rx status until either
|
||||||
* - size(Rx FIFO) == size(Tx-Telegram)
|
* - size(Rx FIFO) == size(Tx-Telegram)
|
||||||
@@ -227,8 +242,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wait until we received sizeof(telegram) or RxBRK (== collision detect)
|
// wait until we received sizeof(telegram) or RxBRK (== collision detect)
|
||||||
// while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < len) || !(USIS(EMSUART_UART) & (1 << UIBD)))
|
while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < len) || (USIS(EMSUART_UART) & (1 << UIBD))) {
|
||||||
while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < len) || (U0IS & (1 << UIBD))) {
|
|
||||||
delayMicroseconds(11 * EMSUART_BIT_TIME); // burn CPU cycles...
|
delayMicroseconds(11 * EMSUART_BIT_TIME); // burn CPU cycles...
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +250,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
|
|||||||
// on Rx-BRK (bus collision), we simply enable Rx and leave
|
// on Rx-BRK (bus collision), we simply enable Rx and leave
|
||||||
// otherwise, we send the final Tx-BRK in loopback and enable Rx-INT.
|
// otherwise, we send the final Tx-BRK in loopback and enable Rx-INT.
|
||||||
// worst case, we'll see an additional Rx-BRK...
|
// worst case, we'll see an additional Rx-BRK...
|
||||||
if (!(U0IS & (1 << UIBD))) {
|
if (!(USIS(EMSUART_UART) & (1 << UIBD))) {
|
||||||
// no bus collision - send terminating BRK signal
|
// no bus collision - send terminating BRK signal
|
||||||
emsuart_loopback(true);
|
emsuart_loopback(true);
|
||||||
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
|
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
|
||||||
@@ -260,6 +274,11 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
|
|||||||
* Send the Poll (our own ID) to Tx as a single byte and end with a <BRK>
|
* Send the Poll (our own ID) to Tx as a single byte and end with a <BRK>
|
||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR emsuart_tx_poll() {
|
void ICACHE_FLASH_ATTR emsuart_tx_poll() {
|
||||||
static uint8_t buf[] = {EMS_ID_ME};
|
static uint8_t buf[1];
|
||||||
|
if (EMS_Sys_Status.emsReverse) {
|
||||||
|
buf[0] = {EMS_ID_ME | 0x80};
|
||||||
|
} else {
|
||||||
|
buf[0] = {EMS_ID_ME};
|
||||||
|
}
|
||||||
emsuart_tx_buffer(buf, 1);
|
emsuart_tx_buffer(buf, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,12 @@
|
|||||||
#define EMS_MAXBUFFERS 10 // 4 buffers for circular filling to avoid collisions
|
#define EMS_MAXBUFFERS 10 // 4 buffers for circular filling to avoid collisions
|
||||||
#define EMS_MAXBUFFERSIZE 32 // max size of the buffer. packets are max 32 bytes
|
#define EMS_MAXBUFFERSIZE 32 // max size of the buffer. packets are max 32 bytes
|
||||||
|
|
||||||
// this is how long we drop the Tx signal to create a 11-bit Break of zeros (BRK)
|
#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)
|
||||||
// At 9600 baud, 11 bits will be 1144 microseconds
|
#define EMSUART_BIT_TIME 104 // bit time @9600 baud
|
||||||
// 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_BRK_WAIT 2070
|
#define EMSUART_TX_WAIT_BRK EMSUART_BIT_TIME * 11 // Time to send a BRK Signal (11 Bit)
|
||||||
#define EMSUART_BIT_TIME 104 // bit time @9600 baud
|
#define EMSUART_TX_WAIT_GAP EMSUART_BIT_TIME * 7 // Gap between to Bytes
|
||||||
|
#define EMSUART_TX_LAG 8 // Assumed Lag
|
||||||
|
|
||||||
#define EMSUART_recvTaskPrio 1
|
#define EMSUART_recvTaskPrio 1
|
||||||
#define EMSUART_recvTaskQueueLen 64
|
#define EMSUART_recvTaskQueueLen 64
|
||||||
|
|||||||
@@ -6,5 +6,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define APP_NAME "EMS-ESP"
|
#define APP_NAME "EMS-ESP"
|
||||||
#define APP_VERSION "1.8.0b3"
|
#define APP_VERSION "1.8.0b4"
|
||||||
#define APP_HOSTNAME "ems-esp"
|
#define APP_HOSTNAME "ems-esp"
|
||||||
|
|||||||
Reference in New Issue
Block a user