diff --git a/tasmota/include/tasmota.h b/tasmota/include/tasmota.h index 4a2aaa813..6284b9c29 100644 --- a/tasmota/include/tasmota.h +++ b/tasmota/include/tasmota.h @@ -501,7 +501,7 @@ enum TuyaSupportedFunctions { TUYA_MCU_FUNC_NONE, TUYA_MCU_FUNC_LOWPOWER_MODE = 51, TUYA_MCU_FUNC_ENUM1 = 61, TUYA_MCU_FUNC_ENUM2, TUYA_MCU_FUNC_ENUM3, TUYA_MCU_FUNC_ENUM4, TUYA_MCU_FUNC_TEMP = 71, TUYA_MCU_FUNC_TEMPSET, TUYA_MCU_FUNC_HUM, TUYA_MCU_FUNC_HUMSET, - TUYA_MCU_FUNC_LX = 75, TUYA_MCU_FUNC_TVOC, TUYA_MCU_FUNC_CO2, TUYA_MCU_FUNC_ECO2, TUYA_MCU_FUNC_GAS, + TUYA_MCU_FUNC_LX = 75, TUYA_MCU_FUNC_TVOC, TUYA_MCU_FUNC_CO2, TUYA_MCU_FUNC_ECO2, TUYA_MCU_FUNC_GAS, TUYA_MCU_FUNC_PM25, TUYA_MCU_FUNC_TIMER1 = 81, TUYA_MCU_FUNC_TIMER2, TUYA_MCU_FUNC_TIMER3, TUYA_MCU_FUNC_TIMER4, TUYA_MCU_FUNC_MOTOR_DIR = 97, TUYA_MCU_FUNC_ERROR = 98, diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index 451448141..d2a8cd2c0 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -1561,7 +1561,7 @@ void SetModuleType(void) bool FlashPin(uint32_t pin) { #if defined(ESP32) && CONFIG_IDF_TARGET_ESP32C3 - return (pin > 10) && (pin < 18); // ESP32C3 has GPIOs 11-17 reserved for Flash + return (((pin > 10) && (pin < 12)) || ((pin > 13) && (pin < 18))); // ESP32C3 has GPIOs 11-17 reserved for Flash, with some boards GPIOs 12 13 are useable #elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) return (pin > 21) && (pin < 33); // ESP32S2 skip 22-32 #elif defined(CONFIG_IDF_TARGET_ESP32) @@ -1574,7 +1574,7 @@ bool FlashPin(uint32_t pin) bool RedPin(uint32_t pin) // pin may be dangerous to change, display in RED in template console { #if defined(ESP32) && CONFIG_IDF_TARGET_ESP32C3 - return false; // no red pin on ESP32C3 + return (12==pin)||(13==pin); // ESP32C3: GPIOs 12 13 are usually used for Flash (mode QIO/QOUT) #elif defined(CONFIG_IDF_TARGET_ESP32S2) return false; // no red pin on ESP32S3 #elif defined(CONFIG_IDF_TARGET_ESP32S3) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu.ino index f95dc86b9..12ee1e815 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu.ino @@ -102,8 +102,8 @@ struct TUYA { const char kTuyaSensors[] PROGMEM = // List of available sensors (can be expanded in the future) // 71 72 73 74 75 "" D_JSON_TEMPERATURE "|TempSet|" D_JSON_HUMIDITY "|HumSet|" D_JSON_ILLUMINANCE -// 76 77 78 79 80 81 82 83 84 - "|" D_JSON_TVOC "|" D_JSON_ECO2 "|" D_JSON_CO2 "|" D_JSON_GAS "||Timer1|Timer2|Timer3|TImer4"; +// 76 77 78 79 80 81 82 83 84 + "|" D_JSON_TVOC "|" D_JSON_ECO2 "|" D_JSON_CO2 "|" D_JSON_GAS "|" D_ENVIRONMENTAL_CONCENTRATION "|Timer1|Timer2|Timer3|TImer4"; const char kTuyaCommand[] PROGMEM = D_PRFX_TUYA "|" // Prefix D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE "|" D_CMND_TUYARGB "|" D_CMND_TUYA_ENUM "|" D_CMND_TUYA_ENUM_LIST "|TempSetRes"; @@ -426,7 +426,7 @@ inline bool TuyaFuncIdValid(uint8_t fnId) { (fnId >= TUYA_MCU_FUNC_MOTOR_DIR && fnId <= TUYA_MCU_FUNC_DUMMY) || (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE) || (fnId >= TUYA_MCU_FUNC_TEMP && fnId <= TUYA_MCU_FUNC_HUMSET) || - (fnId >= TUYA_MCU_FUNC_LX && fnId <= TUYA_MCU_FUNC_GAS) || + (fnId >= TUYA_MCU_FUNC_LX && fnId <= TUYA_MCU_FUNC_PM25) || (fnId >= TUYA_MCU_FUNC_TIMER1 && fnId <= TUYA_MCU_FUNC_TIMER4); } uint8_t TuyaGetFuncId(uint8_t dpid) { @@ -1484,6 +1484,9 @@ void TuyaSensorsShow(bool json) case 79: WSContentSend_PD(HTTP_SNS_GAS, "", Tuya.Sensors[8]); break; + case 80: + WSContentSend_PD(PSTR("{s}" D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"), Tuya.Sensors[9]); + break; case 81: case 82: case 83: diff --git a/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino b/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino index f06fddb2f..dff0e8445 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino @@ -1,5 +1,5 @@ /* - xsns_42_scd30.ino - SC30 CO2 sensor support for Tasmota + xsns_42_scd30.ino - SCD30 CO2 sensor support for Tasmota Copyright (C) 2021 Frogmore42 @@ -61,6 +61,7 @@ enum SCD30_Commands { // commands useable in console or rules FrogmoreScd30 scd30; +bool scd30InitOnce = false; bool scd30Found = false; bool scd30IsDataValid = false; int scd30ErrorState = SCD30_STATE_NO_ERROR; @@ -71,7 +72,7 @@ int scd30GoodMeas_count = 0; int scd30Reset_count = 0; int scd30CrcError_count = 0; int scd30Co2Zero_count = 0; -int i2cReset_count = 0; +int scd30i2cReset_count = 0; uint16_t scd30_CO2 = 0; uint16_t scd30_CO2EAvg = 0; float scd30_Humid = 0.0f; @@ -121,7 +122,7 @@ void Scd30Update(void) scd30CrcError_count++; #ifdef SCD30_DEBUG AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), - scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, scd30i2cReset_count); #endif break; @@ -129,7 +130,7 @@ void Scd30Update(void) scd30Co2Zero_count++; #ifdef SCD30_DEBUG AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), - scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, scd30i2cReset_count); #endif break; @@ -149,7 +150,7 @@ void Scd30Update(void) //scd30IsDataValid = false; #ifdef SCD30_DEBUG AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, scd30i2cReset_count); AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: got CRC error, try again, counter: %ld"), scd30Loop_count); #endif scd30ErrorState = ERROR_SCD30_NO_ERROR; @@ -160,7 +161,7 @@ void Scd30Update(void) //scd30IsDataValid = false; #ifdef SCD30_DEBUG AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, scd30i2cReset_count); AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: not answering, sending soft reset, counter: %ld"), scd30Loop_count); #endif scd30Reset_count++; @@ -185,10 +186,10 @@ void Scd30Update(void) //scd30IsDataValid = false; #ifdef SCD30_DEBUG AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, scd30i2cReset_count); AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: clearing i2c bus")); #endif - i2cReset_count++; + scd30i2cReset_count++; error = scd30.clearI2CBus(); if (error) { scd30ErrorState = SCD30_STATE_ERROR_I2C_RESET; @@ -399,9 +400,16 @@ bool Xsns42(byte function) bool result = false; + // https://github.com/arendst/Tasmota/issues/15438 and datasheet (The boot-up time is < 2 s.) +/* if (FUNC_INIT == function) { Scd30Detect(); } +*/ + if (!scd30InitOnce && (FUNC_EVERY_SECOND == function) && (TasmotaGlobal.uptime > 2)) { + scd30InitOnce = true; + Scd30Detect(); + } else if (scd30Found) { switch (function) { case FUNC_EVERY_SECOND: