diff --git a/lib/TasmotaSerial-1.3.0/README.md b/lib/TasmotaSerial-1.2.0/README.md similarity index 100% rename from lib/TasmotaSerial-1.3.0/README.md rename to lib/TasmotaSerial-1.2.0/README.md diff --git a/lib/TasmotaSerial-1.3.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-1.2.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-1.3.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-1.2.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-1.3.0/keywords.txt b/lib/TasmotaSerial-1.2.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-1.3.0/keywords.txt rename to lib/TasmotaSerial-1.2.0/keywords.txt diff --git a/lib/TasmotaSerial-1.3.0/library.json b/lib/TasmotaSerial-1.2.0/library.json similarity index 100% rename from lib/TasmotaSerial-1.3.0/library.json rename to lib/TasmotaSerial-1.2.0/library.json diff --git a/lib/TasmotaSerial-1.3.0/library.properties b/lib/TasmotaSerial-1.2.0/library.properties similarity index 100% rename from lib/TasmotaSerial-1.3.0/library.properties rename to lib/TasmotaSerial-1.2.0/library.properties diff --git a/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp similarity index 77% rename from lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp index 801384f23..c189442e6 100644 --- a/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp @@ -29,51 +29,51 @@ extern "C" { // As the Arduino attachInterrupt has no parameter, lists of objects // and callbacks corresponding to each possible GPIO pins have to be defined -TasmotaSerial *tms_obj_list[16]; +TasmotaSerial *ObjList[16]; #ifdef TM_SERIAL_USE_IRAM -void ICACHE_RAM_ATTR tms_isr_0() { tms_obj_list[0]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_1() { tms_obj_list[1]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_2() { tms_obj_list[2]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_3() { tms_obj_list[3]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_4() { tms_obj_list[4]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_5() { tms_obj_list[5]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_0() { ObjList[0]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_1() { ObjList[1]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_2() { ObjList[2]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_3() { ObjList[3]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_4() { ObjList[4]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_5() { ObjList[5]->rxRead(); }; // Pin 6 to 11 can not be used -void ICACHE_RAM_ATTR tms_isr_12() { tms_obj_list[12]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_13() { tms_obj_list[13]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_14() { tms_obj_list[14]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_15() { tms_obj_list[15]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_12() { ObjList[12]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_13() { ObjList[13]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_14() { ObjList[14]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_15() { ObjList[15]->rxRead(); }; #else -void tms_isr_0() { tms_obj_list[0]->rxRead(); }; -void tms_isr_1() { tms_obj_list[1]->rxRead(); }; -void tms_isr_2() { tms_obj_list[2]->rxRead(); }; -void tms_isr_3() { tms_obj_list[3]->rxRead(); }; -void tms_isr_4() { tms_obj_list[4]->rxRead(); }; -void tms_isr_5() { tms_obj_list[5]->rxRead(); }; +void sws_isr_0() { ObjList[0]->rxRead(); }; +void sws_isr_1() { ObjList[1]->rxRead(); }; +void sws_isr_2() { ObjList[2]->rxRead(); }; +void sws_isr_3() { ObjList[3]->rxRead(); }; +void sws_isr_4() { ObjList[4]->rxRead(); }; +void sws_isr_5() { ObjList[5]->rxRead(); }; // Pin 6 to 11 can not be used -void tms_isr_12() { tms_obj_list[12]->rxRead(); }; -void tms_isr_13() { tms_obj_list[13]->rxRead(); }; -void tms_isr_14() { tms_obj_list[14]->rxRead(); }; -void tms_isr_15() { tms_obj_list[15]->rxRead(); }; +void sws_isr_12() { ObjList[12]->rxRead(); }; +void sws_isr_13() { ObjList[13]->rxRead(); }; +void sws_isr_14() { ObjList[14]->rxRead(); }; +void sws_isr_15() { ObjList[15]->rxRead(); }; #endif // TM_SERIAL_USE_IRAM static void (*ISRList[16])() = { - tms_isr_0, - tms_isr_1, - tms_isr_2, - tms_isr_3, - tms_isr_4, - tms_isr_5, + sws_isr_0, + sws_isr_1, + sws_isr_2, + sws_isr_3, + sws_isr_4, + sws_isr_5, NULL, NULL, NULL, NULL, NULL, NULL, - tms_isr_12, - tms_isr_13, - tms_isr_14, - tms_isr_15 + sws_isr_12, + sws_isr_13, + sws_isr_14, + sws_isr_15 }; TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin) @@ -91,7 +91,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin) // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE; pinMode(m_rx_pin, INPUT); - tms_obj_list[m_rx_pin] = this; + ObjList[m_rx_pin] = this; attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING); } if (m_tx_pin > -1) { diff --git a/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.h b/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.h similarity index 100% rename from lib/TasmotaSerial-1.3.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-1.2.0/src/TasmotaSerial.h diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 2ce37d699..cadfdfda2 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -5,7 +5,6 @@ * Fix rule power trigger when no backlog command is used (#2613) * Fix several timer data input and output errors (#2597, #2620) * Fix KNX config error (#2628) - * Fix sensor MHZ-19 vanishing data over time (#2659) * Add Portuguese in Brazil language file * Add rule state test for On/Off in addition to 0/1 (#2613) * Updated Italian language file (#2618) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index e1d27221b..4bb42331f 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -90,7 +90,6 @@ #define D_JSON_PRESSUREATSEALEVEL "SeaPressure" #define D_JSON_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_JSON_PROGRAMSIZE "ProgramSize" -#define D_JSON_RESET "Reset" #define D_JSON_RESTARTING "Restarting" #define D_JSON_RESTARTREASON "RestartReason" #define D_JSON_RSSI "RSSI" diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 52765f4b5..4cbf88c9e 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -24,7 +24,7 @@ /*********************************************************************************************\ * MH-Z19 - CO2 sensor * - * Adapted from EspEasy plugin P049 by Dmitry (rel22 ___ inbox.ru) + * Adapted from EspEasy plugin P049 by Dmitry (rel22 ___ inbox.ru) ********************************************************************************************** * Filter usage * @@ -64,20 +64,17 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT #define CO2_HIGH 1200 // Above this CO2 value show red light #endif -#define MHZ19_READ_TIMEOUT 400 // Must be way less than 1000 but enough to read 9 bytes at 9600 bps +#define MHZ19_READ_TIMEOUT 500 // Must be way less than 1000 #define MHZ19_RETRY_COUNT 8 TasmotaSerial *MhzSerial; const char kMhzTypes[] PROGMEM = "MHZ19|MHZ19B"; -enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET }; -const uint8_t kMhzCommands[][2] PROGMEM = { - {0x86,0x00}, // mhz_cmnd_read_ppm - {0x79,0xA0}, // mhz_cmnd_abc_enable - {0x79,0x00}, // mhz_cmnd_abc_disable - {0x87,0x00}, // mhz_cmnd_zeropoint - {0x8D,0x00}}; // mhz_cmnd_reset +const uint8_t mhz_cmnd_read_ppm[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; +const uint8_t mhz_cmnd_abc_enable[9] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6}; +const uint8_t mhz_cmnd_abc_disable[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86}; +const uint8_t mhz_cmnd_zeropoint[9] = {0xff, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78}; uint8_t mhz_type = 1; uint16_t mhz_last_ppm = 0; @@ -87,41 +84,13 @@ bool mhz_abc_must_apply = false; char mhz_types[7]; float mhz_temperature = 0; +uint8_t mhz_timer = 0; uint8_t mhz_retry = MHZ19_RETRY_COUNT; -uint8_t mhz_received = 0; + uint8_t mhz_state = 0; /*********************************************************************************************/ -byte MhzCalculateChecksum(byte *array) -{ - byte checksum = 0; - for (byte i = 1; i < 8; i++) { - checksum += array[i]; - } - checksum = 255 - checksum; - return (checksum +1); -} - -size_t MhzSendCmd(byte command_id) -{ - uint8_t mhz_send[9] = { 0 }; - - mhz_send[0] = 0xFF; // Start byte, fixed - mhz_send[1] = 0x01; // Sensor number, 0x01 by default - memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(kMhzCommands[0])); -/* - mhz_send[4] = 0x00; - mhz_send[5] = 0x00; - mhz_send[6] = 0x00; - mhz_send[7] = 0x00; -*/ - mhz_send[8] = MhzCalculateChecksum(mhz_send); - return MhzSerial->write(mhz_send, sizeof(mhz_send)); -} - -/*********************************************************************************************/ - bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) { if (1 == s) { @@ -157,84 +126,89 @@ bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) return true; } -void MhzEverySecond() +void Mhz50ms() { mhz_state++; - if (8 == mhz_state) { // Every 8 sec start a MH-Z19 measuring cycle (which takes 1005 +5% ms) + if (4 == mhz_state) { // Every 200 mSec mhz_state = 0; - if (mhz_retry) { - mhz_retry--; - if (!mhz_retry) { - mhz_last_ppm = 0; - mhz_temperature = 0; - } - } - - MhzSerial->flush(); // Sync reception - MhzSendCmd(MHZ_CMND_READPPM); - mhz_received = 0; - } - - if ((mhz_state > 2) && !mhz_received) { // Start reading response after 3 seconds every second until received uint8_t mhz_response[9]; - unsigned long start = millis(); - uint8_t counter = 0; - while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { - if (MhzSerial->available() > 0) { - mhz_response[counter++] = MhzSerial->read(); + mhz_timer++; + if (6 == mhz_timer) { // MH-Z19 measuring cycle takes 1005 +5% ms + mhz_timer = 0; + + MhzSerial->flush(); + MhzSerial->write(mhz_cmnd_read_ppm, 9); + } + + if (1 == mhz_timer) { + if (mhz_retry) { + mhz_retry--; + if (!mhz_retry) { + mhz_last_ppm = 0; + mhz_temperature = 0; + } + } + + unsigned long start = millis(); + uint8_t counter = 0; + while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { + if (MhzSerial->available() > 0) { + mhz_response[counter++] = MhzSerial->read(); + } + } + + AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); + + if (counter < 9) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); + return; + } + + byte crc = 0; + for (uint8_t i = 1; i < 8; i++) { + crc += mhz_response[i]; + } + crc = 255 - crc; + crc++; + if (mhz_response[8] != crc) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); + return; + } + if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 bad response")); + return; + } + + uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; + if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 + if (!mhz_abc_enable) { + // After bootup of the sensor the ABC will be enabled. + // Thus only actively disable after bootup. + mhz_abc_must_apply = true; + } } else { - delay(5); - } - } + uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; + mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); + uint8_t s = mhz_response[5]; + mhz_type = (s) ? 1 : 2; + if (MhzCheckAndApplyFilter(ppm, s)) { + mhz_retry = MHZ19_RETRY_COUNT; + LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); - AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); - - if (counter < 9) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); - return; - } - - byte crc = MhzCalculateChecksum(mhz_response); - if (mhz_response[8] != crc) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); - return; - } - if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 bad response")); - return; - } - - mhz_received = 1; - - uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; - if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 - if (!mhz_abc_enable) { - // After bootup of the sensor the ABC will be enabled. - // Thus only actively disable after bootup. - mhz_abc_must_apply = true; - } - } else { - uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; - mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); - uint8_t s = mhz_response[5]; - mhz_type = (s) ? 1 : 2; - if (MhzCheckAndApplyFilter(ppm, s)) { - mhz_retry = MHZ19_RETRY_COUNT; - LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); - - if (0 == s || 64 == s) { // Reading is stable. - if (mhz_abc_must_apply) { - mhz_abc_must_apply = false; - if (mhz_abc_enable) { - MhzSendCmd(MHZ_CMND_ABCENABLE); - } else { - MhzSendCmd(MHZ_CMND_ABCDISABLE); + if (0 == s || 64 == s) { // Reading is stable. + if (mhz_abc_must_apply) { + mhz_abc_must_apply = false; + if (mhz_abc_enable) { + MhzSerial->write(mhz_cmnd_abc_enable, 9); // Sent sensor ABC Enable + } else { + MhzSerial->write(mhz_cmnd_abc_disable, 9); // Sent sensor ABC Disable + } } } - } + } } } @@ -251,8 +225,6 @@ void MhzEverySecond() 2 - Manual start = ABC Off 3 - Optional filter settings - - 9 - Reset */ bool MhzCommandSensor() @@ -261,13 +233,9 @@ bool MhzCommandSensor() switch (XdrvMailbox.payload) { case 2: - MhzSendCmd(MHZ_CMND_ZEROPOINT); + MhzSerial->write(mhz_cmnd_zeropoint, 9); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); break; - case 9: - MhzSendCmd(MHZ_CMND_RESET); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); - break; default: serviced = false; } @@ -282,7 +250,7 @@ void MhzInit() mhz_type = 0; if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD]); - if (MhzSerial->begin(9600)) { + if (MhzSerial->begin()) { mhz_type = 1; } } @@ -320,8 +288,8 @@ boolean Xsns15(byte function) case FUNC_INIT: MhzInit(); break; - case FUNC_EVERY_SECOND: - MhzEverySecond(); + case FUNC_EVERY_50_MSECOND: + Mhz50ms(); break; case FUNC_COMMAND: if (XSNS_15 == XdrvMailbox.index) {