esp32 uart timing, RC35 thermostat mqtt enhancement, fix type_id display

This commit is contained in:
MichaelDvP
2020-05-29 18:17:04 +02:00
parent bf5172eefb
commit f6854b8ad4
7 changed files with 185 additions and 72 deletions

View File

@@ -2,9 +2,9 @@
; For EMS-ESP ; For EMS-ESP
[platformio] [platformio]
; default_envs = esp8266 default_envs = esp8266
; default_envs = esp32 ; default_envs = esp32
default_envs = esp32_d1 ; default_envs = esp32_d1
# override any settings with your own local ones in pio_local.ini # override any settings with your own local ones in pio_local.ini
extra_configs = pio_local.ini extra_configs = pio_local.ini
@@ -74,7 +74,7 @@ upload_protocol = espota
upload_flags = upload_flags =
--port=8266 --port=8266
--auth=neo --auth=neo
upload_port = 192.168.0.23 upload_port = 192.168.0.20
[env:esp8266] [env:esp8266]
build_type = release build_type = release

View File

@@ -228,7 +228,8 @@ std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegr
} }
for (const auto & tf : telegram_functions_) { for (const auto & tf : telegram_functions_) {
if ((tf.telegram_type_id_ & 0x7F) == (telegram->type_id & 0x7F)) { // if ((tf.telegram_type_id_ & 0x7F) == (telegram->type_id & 0x7F)) {
if (tf.telegram_type_id_ == telegram->type_id && (telegram->type_id < 0xF0)) {
return uuid::read_flash_string(tf.telegram_type_name_); return uuid::read_flash_string(tf.telegram_type_name_);
} }
} }

View File

@@ -87,8 +87,7 @@ void Mixing::show_values(uuid::console::Shell & shell) {
// publish values via MQTT // publish values via MQTT
// ideally we should group up all the mixing units together into a nested JSON but for now we'll send them individually // ideally we should group up all the mixing units together into a nested JSON but for now we'll send them individually
void Mixing::publish_values() { void Mixing::publish_values() {
static DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_MEDIUM); DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_SMALL);
// StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
JsonObject rootMixing = doc.to<JsonObject>(); JsonObject rootMixing = doc.to<JsonObject>();
JsonObject dataMixing; JsonObject dataMixing;
@@ -141,13 +140,11 @@ void Mixing::publish_values() {
char topic[30]; char topic[30];
char s[3]; // for formatting strings char s[3]; // for formatting strings
strlcpy(topic, "mixing_data", 30); strlcpy(topic, "mixing_data", 30);
strlcat(topic, Helpers::itoa(s, hc_), 30); // append hc to topic strlcat(topic, Helpers::itoa(s, device_id() - 0x20 + 1), 30); // append hc to topic
Mqtt::publish(topic, doc); Mqtt::publish(topic, doc);
return; return;
} }
char topic[30]; Mqtt::publish("mixing_data", doc);
strlcpy(topic, "mixing_data", 30);
Mqtt::publish(topic, doc);
} }
// heating circuits 0x02D7, 0x02D8 etc... // heating circuits 0x02D7, 0x02D8 etc...

View File

@@ -221,6 +221,47 @@ void Thermostat::thermostat_cmd(const char * message) {
LOG_DEBUG(F("MQTT error: payload %s, error %s"), message, error.c_str()); LOG_DEBUG(F("MQTT error: payload %s, error %s"), message, error.c_str());
return; return;
} }
for (const auto & hc : heating_circuits_) {
char hc_name[6], s[3]; // hc{1-4}
strlcpy(hc_name, "hc", 6);
uint8_t hc_num = hc->hc_num();
strlcat(hc_name, Helpers::itoa(s, hc_num), 6);
if (nullptr != doc[hc_name]["mode"]) {
std::string mode = doc[hc_name]["mode"]; // first check mode
set_mode(mode, hc_num);
}
if (float f = doc[hc_name]["temp"]) {
set_temperature(f, HeatingCircuit::Mode::AUTO, hc_num);
}
if (float f = doc[hc_name]["nighttemp"]) {
set_temperature(f, HeatingCircuit::Mode::NIGHT, hc_num);
}
if (float f = doc[hc_name]["daytemp"]) {
set_temperature(f, HeatingCircuit::Mode::DAY, hc_num);
}
if (float f = doc[hc_name]["nofrosttemp"]) {
set_temperature(f, HeatingCircuit::Mode::NOFROST, hc_num);
}
if (float f = doc[hc_name]["summertemp"]) {
set_temperature(f, HeatingCircuit::Mode::SUMMER, hc_num);
}
if (float f = doc[hc_name]["designtemp"]) {
set_temperature(f, HeatingCircuit::Mode::DESIGN, hc_num);
}
if (float f = doc[hc_name]["offsettemp"]) {
set_temperature(f, HeatingCircuit::Mode::OFFSET, hc_num);
}
if (float f = doc[hc_name]["holidaytemp"]) { //
set_temperature(f, HeatingCircuit::Mode::HOLIDAY, hc_num);
}
if (float f = doc[hc_name]["remotetemp"]) {
if(f > 100 || f < 0) {
hc->remotetemp = EMS_VALUE_SHORT_NOTSET;
} else {
hc->remotetemp = (uint16_t) (f * 10);
}
}
}
const char * command = doc["cmd"]; const char * command = doc["cmd"];
if (command == nullptr) { if (command == nullptr) {
@@ -301,6 +342,27 @@ void Thermostat::thermostat_cmd(const char * message) {
} }
return; return;
} }
if (strcmp(command, "summertemp") == 0) {
float f = doc["data"];
if (f) {
set_temperature(f, HeatingCircuit::Mode::SUMMER, hc_num);
}
return;
}
if (strcmp(command, "designtemp") == 0) {
float f = doc["data"];
if (f) {
set_temperature(f, HeatingCircuit::Mode::DESIGN, hc_num);
}
return;
}
if (strcmp(command, "offettemp") == 0) {
float f = doc["data"];
if (f) {
set_temperature(f, HeatingCircuit::Mode::OFFSET, hc_num);
}
return;
}
} }
void Thermostat::thermostat_cmd_temp(const char * message) { void Thermostat::thermostat_cmd_temp(const char * message) {
@@ -358,8 +420,8 @@ void Thermostat::publish_values() {
JsonObject rootThermostat = doc.to<JsonObject>(); JsonObject rootThermostat = doc.to<JsonObject>();
JsonObject dataThermostat; JsonObject dataThermostat;
// optional, add external temp. I don't think anyone actually is interested in this // optional, add external temp. I don't think anyone (except MichaelDvP) actually is interested in this
if ((flags == EMS_DEVICE_FLAG_RC35) && ((mqtt_format_ == Settings::MQTT_format::SINGLE) || (mqtt_format_ == Settings::MQTT_format::MY))) { if ((flags == EMS_DEVICE_FLAG_RC35 || flags == EMS_DEVICE_FLAG_RC30_1) && (mqtt_format_ == Settings::MQTT_format::SINGLE || mqtt_format_ == Settings::MQTT_format::MY)) {
if (datetime_.size()) { if (datetime_.size()) {
rootThermostat["time"] = datetime_.c_str(); rootThermostat["time"] = datetime_.c_str();
} }
@@ -367,10 +429,32 @@ void Thermostat::publish_values() {
rootThermostat["dampedtemp"] = dampedoutdoortemp; rootThermostat["dampedtemp"] = dampedoutdoortemp;
} }
if (tempsensor1 != EMS_VALUE_USHORT_NOTSET) { if (tempsensor1 != EMS_VALUE_USHORT_NOTSET) {
rootThermostat["tempsensor1"] = (float)tempsensor1 / 10; rootThermostat["inttemp1"] = (float)tempsensor1 / 10;
} }
if (tempsensor2 != EMS_VALUE_USHORT_NOTSET) { if (tempsensor2 != EMS_VALUE_USHORT_NOTSET) {
rootThermostat["tempsensor2"] = (float)tempsensor2 / 10; rootThermostat["inttemp2"] = (float)tempsensor2 / 10;
}
if (ibaCalIntTemperature != EMS_VALUE_INT_NOTSET) {
rootThermostat["intoffset"] = (float)ibaCalIntTemperature / 2;
}
if (ibaMinExtTemperature != EMS_VALUE_INT_NOTSET) {
rootThermostat["minexttemp"] = (float)ibaMinExtTemperature; // min ext temp for heating curve, in deg.
}
if (ibaBuildingType != EMS_VALUE_UINT_NOTSET) {
if (ibaBuildingType == 0) {
rootThermostat["building"] = "light";
} else if (ibaBuildingType == 1) {
rootThermostat["building"] = "medium";
} else if (ibaBuildingType == 2) {
rootThermostat["building"] = "heavy";
}
}
if (mqtt_format_ == Settings::MQTT_format::SINGLE) {
Mqtt::publish("thermostat_data", doc);
rootThermostat = doc.to<JsonObject>(); // clear object
} }
} }
@@ -470,14 +554,14 @@ void Thermostat::publish_values() {
dataThermostat["modetype"] = mode_tostring(hc->get_mode_type(flags)); dataThermostat["modetype"] = mode_tostring(hc->get_mode_type(flags));
} }
// if format is single, send immediately and quit // if format is single, send immediately and clear object for next hc
if (mqtt_format_ == Settings::MQTT_format::SINGLE) { if (mqtt_format_ == Settings::MQTT_format::SINGLE) {
char topic[30]; char topic[30];
char s[3]; // for formatting strings char s[3]; // for formatting strings
strlcpy(topic, "thermostat_data", 30); strlcpy(topic, "thermostat_data", 30);
strlcat(topic, Helpers::itoa(s, hc->hc_num()), 30); // append hc to topic strlcat(topic, Helpers::itoa(s, hc->hc_num()), 30); // append hc to topic
Mqtt::publish(topic, doc); Mqtt::publish(topic, doc);
return; rootThermostat = doc.to<JsonObject>(); // clear object
} }
} }
@@ -652,15 +736,24 @@ std::string Thermostat::mode_tostring(uint8_t mode) const {
case HeatingCircuit::Mode::HEAT: case HeatingCircuit::Mode::HEAT:
return read_flash_string(F("heat")); return read_flash_string(F("heat"));
break; break;
// case HeatingCircuit::Mode::HOLIDAY: case HeatingCircuit::Mode::HOLIDAY:
// return read_flash_string(F("holiday")); return read_flash_string(F("holiday"));
// break; break;
case HeatingCircuit::Mode::NOFROST: case HeatingCircuit::Mode::NOFROST:
return read_flash_string(F("nofrost")); return read_flash_string(F("nofrost"));
break; break;
case HeatingCircuit::Mode::AUTO: case HeatingCircuit::Mode::AUTO:
return read_flash_string(F("auto")); return read_flash_string(F("auto"));
break; break;
case HeatingCircuit::Mode::SUMMER:
return read_flash_string(F("summer"));
break;
case HeatingCircuit::Mode::OFFSET:
return read_flash_string(F("offset"));
break;
case HeatingCircuit::Mode::DESIGN:
return read_flash_string(F("design"));
break;
default: default:
case HeatingCircuit::Mode::UNKNOWN: case HeatingCircuit::Mode::UNKNOWN:
return read_flash_string(F("unknown")); return read_flash_string(F("unknown"));
@@ -869,19 +962,14 @@ void Thermostat::process_EasyMonitor(std::shared_ptr<const Telegram> telegram) {
// Settings Parameters - 0xA5 - RC30_1 // Settings Parameters - 0xA5 - RC30_1
void Thermostat::process_IBASettings(std::shared_ptr<const Telegram> telegram) { void Thermostat::process_IBASettings(std::shared_ptr<const Telegram> telegram) {
uint8_t extTemp = 100; // Min. ext temperature is coded as int8, 0xF6=-10, 0x0 = 0, 0xFF=-1. 100 is out of permissible range
// 22 - display line on RC35 // 22 - display line on RC35
telegram->read_value(ibaMainDisplay, telegram->read_value(ibaMainDisplay,
0); // display on Thermostat: 0 int. temp, 1 int. setpoint, 2 ext. temp., 3 burner temp., 4 ww temp, 5 functioning mode, 6 time, 7 data, 9 smoke temp 0); // display on Thermostat: 0 int. temp, 1 int. setpoint, 2 ext. temp., 3 burner temp., 4 ww temp, 5 functioning mode, 6 time, 7 data, 9 smoke temp
telegram->read_value(ibaLanguage, 1); // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian telegram->read_value(ibaLanguage, 1); // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian
telegram->read_value(ibaCalIntTemperature, 2); // offset int. temperature sensor, by * 0.1 Kelvin telegram->read_value(ibaCalIntTemperature, 2); // offset int. temperature sensor, by * 0.1 Kelvin
telegram->read_value(ibaBuildingType, 6); // building type: 0 = light, 1 = medium, 2 = heavy telegram->read_value(ibaBuildingType, 6); // building type: 0 = light, 1 = medium, 2 = heavy
telegram->read_value(extTemp, 5); // min ext temp for heating curve, in deg., 0xF6=-10, 0x0 = 0, 0xFF=-1 telegram->read_value(ibaMinExtTemperature, 5); // min ext temp for heating curve, in deg., 0xF6=-10, 0x0 = 0, 0xFF=-1
if (extTemp != 100) { telegram->read_value(ibaClockOffset, 12); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
// code as signed short, to benefit from negative value rendering
ibaMinExtTemperature = (int16_t)(extTemp > 127) ? (extTemp - 256) : extTemp;
}
telegram->read_value(ibaClockOffset, 12); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
} }
// type 0x6F - FR10/FR50/FR100 Junkers // type 0x6F - FR10/FR50/FR100 Junkers
@@ -945,7 +1033,7 @@ void Thermostat::process_RC30Set(std::shared_ptr<const Telegram> telegram) {
// type 0x3E (HC1), 0x48 (HC2), 0x52 (HC3), 0x5C (HC4) - data from the RC35 thermostat (0x10) - 16 bytes // type 0x3E (HC1), 0x48 (HC2), 0x52 (HC3), 0x5C (HC4) - data from the RC35 thermostat (0x10) - 16 bytes
void Thermostat::process_RC35Monitor(std::shared_ptr<const Telegram> telegram) { void Thermostat::process_RC35Monitor(std::shared_ptr<const Telegram> telegram) {
// exit if the 15th byte (second from last) is 0x00, which I think is calculated flow setpoint temperature // exit if the 15th byte (second from last) is 0x00, which I think is calculated flow setpoint temperature
// with weather controlled RC35s this value can be zero and our setpoint temps will be incorrect // with weather controlled RC35s this value is >=5, otherwise can be zero and our setpoint temps will be incorrect
// see https://github.com/proddy/EMS-ESP/issues/373#issuecomment-627907301 // see https://github.com/proddy/EMS-ESP/issues/373#issuecomment-627907301
if (telegram->message_data[14] == 0x00) { if (telegram->message_data[14] == 0x00) {
return; return;
@@ -953,7 +1041,7 @@ void Thermostat::process_RC35Monitor(std::shared_ptr<const Telegram> telegram) {
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram); std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
telegram->read_value8(hc->setpoint_roomTemp, 2); // is * 2, force to single byte telegram->read_value8(hc->setpoint_roomTemp, 2); // is * 2, force to single byte, is 0 in summermode
telegram->read_value(hc->curr_roomTemp, 3); // is * 10 - or 0x7D00 if thermostat is mounted on boiler telegram->read_value(hc->curr_roomTemp, 3); // is * 10 - or 0x7D00 if thermostat is mounted on boiler
telegram->read_value(hc->mode_type, 1, 1); telegram->read_value(hc->mode_type, 1, 1);
telegram->read_value(hc->summer_mode, 1, 0); telegram->read_value(hc->summer_mode, 1, 0);
@@ -975,10 +1063,12 @@ void Thermostat::process_RC35Set(std::shared_ptr<const Telegram> telegram) {
telegram->read_value(hc->daytemp, 2); // is * 2 telegram->read_value(hc->daytemp, 2); // is * 2
telegram->read_value(hc->nighttemp, 1); // is * 2 telegram->read_value(hc->nighttemp, 1); // is * 2
telegram->read_value(hc->holidaytemp, 3); // is * 2 telegram->read_value(hc->holidaytemp, 3); // is * 2
telegram->read_value(hc->heatingtype, 0); // byte 0 bit floor heating = 3 telegram->read_value(hc->heatingtype, 0); // 0- off, 1-radiator, 2-convector, 3-floor
telegram->read_value(hc->designtemp, 17); telegram->read_value(hc->summertemp, 22); // is * 1
telegram->read_value(hc->offsettemp, 6); telegram->read_value(hc->nofrosttemp, 23); // is * 1
telegram->read_value(hc->designtemp, 17); // is * 1
telegram->read_value(hc->offsettemp, 6); // is * 2
} }
// process_RCTime - type 0x06 - date and time from a thermostat - 14 bytes long // process_RCTime - type 0x06 - date and time from a thermostat - 14 bytes long
@@ -1206,10 +1296,29 @@ void Thermostat::set_temperature(const float temperature, const uint8_t mode, co
case HeatingCircuit::Mode::HOLIDAY: // change the holiday temp case HeatingCircuit::Mode::HOLIDAY: // change the holiday temp
offset = EMS_OFFSET_RC35Set_temp_holiday; offset = EMS_OFFSET_RC35Set_temp_holiday;
break; break;
case HeatingCircuit::Mode::OFFSET: // change the offset temp
offset = EMS_OFFSET_RC35Set_temp_offset;
break;
case HeatingCircuit::Mode::DESIGN:
offset = EMS_OFFSET_RC35Set_temp_design;
break;
case HeatingCircuit::Mode::SUMMER:
offset = EMS_OFFSET_RC35Set_temp_summer;
break;
case HeatingCircuit::Mode::NOFROST:
offset = EMS_OFFSET_RC35Set_temp_nofrost;
break;
default: default:
case HeatingCircuit::Mode::AUTO: // automatic selection, if no type is defined, we use the standard code case HeatingCircuit::Mode::AUTO: // automatic selection, if no type is defined, we use the standard code
if (model == EMS_DEVICE_FLAG_RC35) { if (model == EMS_DEVICE_FLAG_RC35) {
offset = EMS_OFFSET_RC35Set_seltemp; // https://github.com/proddy/EMS-ESP/issues/310 uint8_t mode_ = hc->get_mode(flags());
if (mode_ == HeatingCircuit::Mode::NIGHT) {
offset = EMS_OFFSET_RC35Set_temp_night;
} else if (mode_ == HeatingCircuit::Mode::DAY) {
offset = EMS_OFFSET_RC35Set_temp_day;
} else {
offset = EMS_OFFSET_RC35Set_seltemp; // https://github.com/proddy/EMS-ESP/issues/310
}
} else { } else {
uint8_t mode_type = hc->get_mode_type(flags()); uint8_t mode_type = hc->get_mode_type(flags());
offset = (mode_type == HeatingCircuit::Mode::NIGHT) ? EMS_OFFSET_RC35Set_temp_night : EMS_OFFSET_RC35Set_temp_day; offset = (mode_type == HeatingCircuit::Mode::NIGHT) ? EMS_OFFSET_RC35Set_temp_night : EMS_OFFSET_RC35Set_temp_day;

View File

@@ -57,9 +57,12 @@ class Thermostat : public EMSdevice {
uint8_t holidaytemp = EMS_VALUE_UINT_NOTSET; uint8_t holidaytemp = EMS_VALUE_UINT_NOTSET;
uint8_t heatingtype = EMS_VALUE_UINT_NOTSET; // type of heating: 1 radiator, 2 convectors, 3 floors, 4 room supply uint8_t heatingtype = EMS_VALUE_UINT_NOTSET; // type of heating: 1 radiator, 2 convectors, 3 floors, 4 room supply
uint8_t circuitcalctemp = EMS_VALUE_UINT_NOTSET; uint8_t circuitcalctemp = EMS_VALUE_UINT_NOTSET;
uint8_t summertemp = EMS_VALUE_UINT_NOTSET;
uint8_t nofrosttemp = EMS_VALUE_UINT_NOTSET;
uint8_t designtemp = EMS_VALUE_UINT_NOTSET; // heatingcurve design temp at MinExtTemp
uint8_t offsettemp = 100; // heatingcurve offest temp at roomtemp signed!
uint16_t remotetemp = EMS_VALUE_SHORT_NOTSET; // for simulating a RC20 remote
uint8_t designtemp = EMS_VALUE_UINT_NOTSET; // heatingcurve design temp at MinExtTemp
uint8_t offsettemp = 100; // heatingcurve offest temp at roomtemp signed!
uint8_t hc_num() const { uint8_t hc_num() const {
return hc_num_; return hc_num_;
@@ -76,7 +79,7 @@ class Thermostat : public EMSdevice {
return set_typeid_; return set_typeid_;
} }
enum Mode : uint8_t { UNKNOWN, OFF, MANUAL, AUTO, DAY, NIGHT, HEAT, NOFROST, ECO, HOLIDAY, COMFORT, OFFSET, DESIGN }; enum Mode : uint8_t { UNKNOWN, OFF, MANUAL, AUTO, DAY, NIGHT, HEAT, NOFROST, ECO, HOLIDAY, COMFORT, OFFSET, DESIGN, SUMMER };
private: private:
uint8_t hc_num_; uint8_t hc_num_;
@@ -159,6 +162,10 @@ class Thermostat : public EMSdevice {
static constexpr uint8_t EMS_OFFSET_RC35Set_heatingtype = 0; // e.g. floor heating = 3 static constexpr uint8_t EMS_OFFSET_RC35Set_heatingtype = 0; // e.g. floor heating = 3
static constexpr uint8_t EMS_OFFSET_RC35Set_circuitcalctemp = 14; // calculated circuit temperature static constexpr uint8_t EMS_OFFSET_RC35Set_circuitcalctemp = 14; // calculated circuit temperature
static constexpr uint8_t EMS_OFFSET_RC35Set_seltemp = 37; // selected temp static constexpr uint8_t EMS_OFFSET_RC35Set_seltemp = 37; // selected temp
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_offset = 6;
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_design = 17;
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_summer = 22;
static constexpr uint8_t EMS_OFFSET_RC35Set_temp_nofrost = 23;
static constexpr uint8_t EMS_OFFSET_EasyStatusMessage_setpoint = 10; // setpoint temp static constexpr uint8_t EMS_OFFSET_EasyStatusMessage_setpoint = 10; // setpoint temp
static constexpr uint8_t EMS_OFFSET_EasyStatusMessage_curr = 8; // current temp static constexpr uint8_t EMS_OFFSET_EasyStatusMessage_curr = 8; // current temp

View File

@@ -29,9 +29,9 @@
namespace emsesp { namespace emsesp {
static intr_handle_t uart_handle; static intr_handle_t uart_handle;
static RingbufHandle_t buf_handle = NULL; static RingbufHandle_t buf_handle = NULL;
static bool drop_first_rx = true; static bool drop_next_rx = true;
static uint8_t tx_mode_ = 0xFF; static uint8_t tx_mode_ = 0xFF;
/* /*
* Task to handle the incoming data * Task to handle the incoming data
@@ -57,19 +57,20 @@ void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
if (EMS_UART.int_st.brk_det) { if (EMS_UART.int_st.brk_det) {
EMS_UART.int_clr.brk_det = 1; // clear flag EMS_UART.int_clr.brk_det = 1; // clear flag
EMS_UART.conf0.txd_brk = 0; // if it was break from sending, clear bit
length = 0; length = 0;
while (EMS_UART.status.rxfifo_cnt) { while (EMS_UART.status.rxfifo_cnt) {
uint8_t rx = EMS_UART.fifo.rw_byte; // read all bytes into buffer uint8_t rx = EMS_UART.fifo.rw_byte; // read all bytes from fifo
if (length < EMS_MAXBUFFERSIZE) { if (length < EMS_MAXBUFFERSIZE) {
rxbuf[length++] = rx; rxbuf[length++] = rx;
} else {
drop_next_rx = true; // we have a overflow
} }
} }
if ((!drop_first_rx) && ((length == 2) || ((length > 4)))) { if ((!drop_next_rx) && ((length == 2) || (length > 4))) {
int baseType = 0; int baseType = 0;
xRingbufferSendFromISR(buf_handle, rxbuf, length - 1, &baseType); xRingbufferSendFromISR(buf_handle, rxbuf, length - 1, &baseType);
} }
drop_first_rx = false; drop_next_rx = false;
} }
} }
/* /*
@@ -91,14 +92,15 @@ void EMSuart::start(uint8_t tx_mode) {
ESP_ERROR_CHECK(uart_param_config(EMSUART_UART, &uart_config)); ESP_ERROR_CHECK(uart_param_config(EMSUART_UART, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(EMSUART_UART, EMSUART_TXPIN, EMSUART_RXPIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); ESP_ERROR_CHECK(uart_set_pin(EMSUART_UART, EMSUART_TXPIN, EMSUART_RXPIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
EMS_UART.int_ena.val = 0; // disable all intr. EMS_UART.int_ena.val = 0; // disable all intr.
EMS_UART.int_clr.val = 0xFFFFFFFF; // clear all intr. flags EMS_UART.int_clr.val = 0xFFFFFFFF; // clear all intr. flags
EMS_UART.idle_conf.tx_brk_num = 11; // breaklength 11 bit EMS_UART.idle_conf.tx_brk_num = 11; // breaklength 11 bit
drop_first_rx = true; EMS_UART.idle_conf.rx_idle_thrhd = 256;
buf_handle = xRingbufferCreate(128, RINGBUF_TYPE_NOSPLIT); drop_next_rx = true;
buf_handle = xRingbufferCreate(128, RINGBUF_TYPE_NOSPLIT);
ESP_ERROR_CHECK(uart_isr_register(EMSUART_UART, emsuart_rx_intr_handler, NULL, ESP_INTR_FLAG_IRAM, &uart_handle)); ESP_ERROR_CHECK(uart_isr_register(EMSUART_UART, emsuart_rx_intr_handler, NULL, ESP_INTR_FLAG_IRAM, &uart_handle));
xTaskCreate(emsuart_recvTask, "emsuart_recvTask", 2048, NULL, 12, NULL); xTaskCreate(emsuart_recvTask, "emsuart_recvTask", 2048, NULL, 12, NULL);
EMS_UART.int_ena.brk_det = 1; // activate only break EMS_UART.int_ena.brk_det = 1; // activate only break
} }
/* /*
@@ -114,19 +116,17 @@ void EMSuart::stop() {
void EMSuart::restart() { void EMSuart::restart() {
if (EMS_UART.int_raw.brk_det) { if (EMS_UART.int_raw.brk_det) {
EMS_UART.int_clr.brk_det = 1; // clear flag EMS_UART.int_clr.brk_det = 1; // clear flag
drop_first_rx = true; // and drop first frame drop_next_rx = true; // and drop first frame
} }
EMS_UART.int_ena.brk_det = 1; // activate only break EMS_UART.int_ena.brk_det = 1; // activate only break
}; };
/* /*
* Sends a 1-byte poll, ending with a <BRK> * Sends a 1-byte poll, ending with a <BRK>
*/ */
void EMSuart::send_poll(uint8_t data) { void EMSuart::send_poll(uint8_t data) {
EMS_UART.conf0.txd_brk = 0; // just to make sure the bit is cleared EMS_UART.fifo.rw_byte = data;
EMS_UART.fifo.rw_byte = data; EMS_UART.conf0.txd_brk = 1; // <brk> after send
//EMS_UART.idle_conf.tx_brk_num = 11; // breaklength 11 bit
EMS_UART.conf0.txd_brk = 1; // sending ends in a break
} }
/* /*
@@ -136,13 +136,10 @@ void EMSuart::send_poll(uint8_t data) {
*/ */
EMSUART_STATUS EMSuart::transmit(uint8_t * buf, uint8_t len) { EMSUART_STATUS EMSuart::transmit(uint8_t * buf, uint8_t len) {
if (len > 0) { if (len > 0) {
EMS_UART.conf0.txd_brk = 0; // just to make sure the bit is cleared
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
EMS_UART.fifo.rw_byte = buf[i]; EMS_UART.fifo.rw_byte = buf[i];
} }
//uart_tx_chars(EMSUART_UART, (const char *)buf, len); EMS_UART.conf0.txd_brk = 1; // <brk> after send
//EMS_UART.idle_conf.tx_brk_num = 11; // breaklength 11 bit
EMS_UART.conf0.txd_brk = 1; // sending ends in a break
} }
return EMS_TX_STATUS_OK; return EMS_TX_STATUS_OK;
} }

View File

@@ -28,10 +28,10 @@ os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue
EMSuart::EMSRxBuf_t * pEMSRxBuf; EMSuart::EMSRxBuf_t * pEMSRxBuf;
EMSuart::EMSRxBuf_t * paEMSRxBuf[EMS_MAXBUFFERS]; EMSuart::EMSRxBuf_t * paEMSRxBuf[EMS_MAXBUFFERS];
uint8_t emsRxBufIdx = 0; uint8_t emsRxBufIdx = 0;
uint8_t phantomBreak = 0; uint8_t phantomBreak = 0;
uint8_t tx_mode_ = 0xFF; uint8_t tx_mode_ = 0xFF;
bool drop_first_rx = true; bool drop_next_rx = true;
// //
// Main interrupt handler // Main interrupt handler
@@ -67,17 +67,19 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
uint8_t rx = USF(EMSUART_UART); uint8_t rx = USF(EMSUART_UART);
if (length < EMS_MAXBUFFERSIZE) { if (length < EMS_MAXBUFFERSIZE) {
uart_buffer[length++] = rx; uart_buffer[length++] = rx;
} else {
drop_next_rx = true;
} }
} }
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK> bit ETS_UART_INTR_DISABLE(); // disable all interrupts and clear them
ETS_UART_INTR_DISABLE(); // disable all interrupts and clear them
USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt
if (!drop_first_rx) { USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
if (!drop_next_rx) {
pEMSRxBuf->length = length; pEMSRxBuf->length = length;
os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, pEMSRxBuf->length); // copy data into transfer buffer, including the BRK 0x00 at the end os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, pEMSRxBuf->length); // copy data into transfer buffer, including the BRK 0x00 at the end
// rx_idle_ = true; // check set the status flag stating BRK has been received and we can start a new package // rx_idle_ = true; // check set the status flag stating BRK has been received and we can start a new package
} }
drop_first_rx = false; drop_next_rx = false;
ETS_UART_INTR_ENABLE(); // re-enable UART interrupts ETS_UART_INTR_ENABLE(); // re-enable UART interrupts
system_os_post(EMSUART_recvTaskPrio, 0, 0); // call emsuart_recvTask() at next opportunity system_os_post(EMSUART_recvTaskPrio, 0, 0); // call emsuart_recvTask() at next opportunity
@@ -109,7 +111,7 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_recvTask(os_event_t * events) {
// ignore double BRK at the end, possibly from the Tx loopback // ignore double BRK at the end, possibly from the Tx loopback
// also telegrams with no data value // also telegrams with no data value
// then transmit EMS buffer, excluding the BRK // then transmit EMS buffer, excluding the BRK
if ((length > 4) && (length <= EMS_MAXBUFFERSIZE + 1)) { if (length > 4) {
EMSESP::incoming_telegram((uint8_t *)pCurrent->buffer, length - 1); EMSESP::incoming_telegram((uint8_t *)pCurrent->buffer, length - 1);
} }
} }
@@ -188,7 +190,7 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
ETS_UART_INTR_ATTACH(emsuart_rx_intr_handler, nullptr); ETS_UART_INTR_ATTACH(emsuart_rx_intr_handler, nullptr);
ETS_UART_INTR_ENABLE(); ETS_UART_INTR_ENABLE();
drop_first_rx = true; drop_next_rx = true;
// LOG_INFO(F("UART service for Rx/Tx started")); // LOG_INFO(F("UART service for Rx/Tx started"));
} }
@@ -204,9 +206,9 @@ void ICACHE_FLASH_ATTR EMSuart::stop() {
* re-start UART0 driver * re-start UART0 driver
*/ */
void ICACHE_FLASH_ATTR EMSuart::restart() { void ICACHE_FLASH_ATTR EMSuart::restart() {
if (USIS(EMSUART_UART) & ((1 << UIBD))) { if (USIR(EMSUART_UART) & ((1 << UIBD))) {
USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt
drop_first_rx = true; drop_next_rx = true;
} }
ETS_UART_INTR_ENABLE(); ETS_UART_INTR_ENABLE();
// emsuart_flush_fifos(); // emsuart_flush_fifos();
@@ -247,7 +249,7 @@ void ICACHE_FLASH_ATTR EMSuart::tx_brk() {
*/ */
void EMSuart::send_poll(uint8_t data) { void EMSuart::send_poll(uint8_t data) {
if (tx_mode_ == EMS_TXMODE_NEW) { if (tx_mode_ == EMS_TXMODE_NEW) {
USC0(EMSUART_UART) &= ~(1 << UCBRK); // make sure <BRK> bit is cleared USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
USF(EMSUART_UART) = data; USF(EMSUART_UART) = data;
USC0(EMSUART_UART) |= (1 << UCBRK); // send <BRK> at the end USC0(EMSUART_UART) |= (1 << UCBRK); // send <BRK> at the end
} else { } else {
@@ -269,7 +271,7 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
// new code from Michael. See https://github.com/proddy/EMS-ESP/issues/380 // new code from Michael. See https://github.com/proddy/EMS-ESP/issues/380
if (tx_mode_ == EMS_TXMODE_NEW) { if (tx_mode_ == EMS_TXMODE_NEW) {
USC0(EMSUART_UART) &= ~(1 << UCBRK); // make sure <BRK> bit is cleared USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
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];
} }