diff --git a/CHANGELOG.md b/CHANGELOG.md index b2ed4dc3d..9abc2314f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. - Refactored I2C drivers HTU21, BH1750, SHT3x, iAQ and HYT - Add command entered to command error and command unknown message - ESP32 platform update from 2024.08.11 to 2024.09.10 and Framework (Arduino Core) from v3.0.4 to v3.0.5 (#22163) +- SCD30 Lowered I2C clock from 100k to 50k (#15438) ### Fixed - Shutter missing HOLD on shutterbutton (#22108) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5da816b04..4511b678e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -148,6 +148,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Energy BL09xx command ``CurrentSet`` input changed from Ampere to milliAmpere - Energy force Apparent Power equals Active Power when (Calculated) Apparent Power is less than Active Power [#20653](https://github.com/arendst/Tasmota/issues/20653) - Refactored I2C drivers HTU21, BH1750, SHT3x, iAQ and HYT +- SCD30 Lowered I2C clock from 100k to 50k [#15438](https://github.com/arendst/Tasmota/issues/15438) ### Fixed - Crash when calling TasmotaSerial destructor when initialized with incorrect arguments [#22036](https://github.com/arendst/Tasmota/issues/22036) diff --git a/tasmota/tasmota_support/support_a_i2c.ino b/tasmota/tasmota_support/support_a_i2c.ino index 660ce2fd1..8adabdba1 100644 --- a/tasmota/tasmota_support/support_a_i2c.ino +++ b/tasmota/tasmota_support/support_a_i2c.ino @@ -20,8 +20,16 @@ uint32_t i2c_active[2][4] = { 0 }; #endif uint32_t i2c_buffer = 0; +struct I2Ct { + uint32_t frequency[2]; + int8_t sda[2]; + int8_t scl[2]; + int8_t active_bus; +} I2C; + bool I2cBegin(int sda, int scl, uint32_t bus = 0, uint32_t frequency = 100000); bool I2cBegin(int sda, int scl, uint32_t bus, uint32_t frequency) { + I2C.frequency[bus] = frequency; bool result = true; #ifdef ESP8266 Wire.begin(sda, scl); @@ -51,6 +59,24 @@ TwoWire& I2cGetWire(uint8_t bus = 0) { } } +bool I2cSetClock(uint32_t frequency = 0, uint32_t bus = 0); +bool I2cSetClock(uint32_t frequency, uint32_t bus) { + TwoWire& myWire = I2cGetWire(bus); + if (&myWire == nullptr) { return false; } // No valid I2c bus + + if (0 == frequency) { + if (0 == I2C.frequency[bus]) { + I2C.frequency[bus] = 100000; // Tasmota default I2C bus speed + } + } else { + I2C.frequency[bus] = frequency; + } + if (frequency != I2C.frequency[bus]) { + myWire.setClock(I2C.frequency[bus]); + } + return true; +} + /*-------------------------------------------------------------------------------------------*\ * Return code: 0 = Error, 1 = OK \*-------------------------------------------------------------------------------------------*/ diff --git a/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino b/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino index f67416bd2..cd4bf9d2d 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_42_scd30.ino @@ -69,26 +69,31 @@ struct { } Scd30; void Scd30Detect(void) { - if (!I2cSetDevice(SCD30_ADDRESS)) { return; } + I2cSetClock(50000); + if (I2cSetDevice(SCD30_ADDRESS)) { + scd30.begin(); - scd30.begin(); + uint8_t major = 0; + uint8_t minor = 0; + if (!scd30.getFirmwareVersion(&major, &minor)) { + if (!scd30.getMeasurementInterval(&Scd30.interval)) { + if (!scd30.beginMeasuring()) { + I2cSetActiveFound(SCD30_ADDRESS, "SCD30"); + Scd30.found = true; - uint8_t major = 0; - uint8_t minor = 0; - if (scd30.getFirmwareVersion(&major, &minor)) { return; } - if (scd30.getMeasurementInterval(&Scd30.interval)) { return; } - if (scd30.beginMeasuring()) { return; } - - I2cSetActiveFound(SCD30_ADDRESS, "SCD30"); - Scd30.found = true; - -// AddLog(LOG_LEVEL_DEBUG, PSTR("SCD: FW v%d.%d"), major, minor); +// AddLog(LOG_LEVEL_DEBUG, PSTR("SCD: FW v%d.%d"), major, minor); + } + } + } + } + I2cSetClock(); } // gets data from the sensor every 3 seconds or so to give the sensor time to gather new data void Scd30Update(void) { Scd30.loop_count++; if (Scd30.loop_count > (Scd30.interval - 1)) { + I2cSetClock(50000); uint32_t error = 0; switch (Scd30.error_state) { case SCD30_STATE_NO_ERROR: { @@ -129,7 +134,8 @@ void Scd30Update(void) { #ifdef SCD30_DEBUG AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, Scd30.loop_count); #endif - return; + I2cSetClock(); + return; } break; } @@ -200,6 +206,7 @@ void Scd30Update(void) { Scd30.error_state = SCD30_STATE_ERROR_SOFT_RESET; // try again } } + I2cSetClock(); if (Scd30.loop_count > (SCD30_MAX_MISSED_READS * Scd30.interval)) { Scd30.data_valid = false; @@ -213,41 +220,49 @@ void Scd30Update(void) { void CmndScd30Altitude(void) { uint16_t value = 0; + I2cSetClock(50000); if (XdrvMailbox.data_len > 0) { value = XdrvMailbox.payload; scd30.setAltitudeCompensation(value); } else { scd30.getAltitudeCompensation(&value); } + I2cSetClock(); ResponseCmndNumber(value); }; void CmndScd30AutoMode(void) { uint16_t value = 0; + I2cSetClock(50000); if (XdrvMailbox.data_len > 0) { value = XdrvMailbox.payload; scd30.setCalibrationType(value); } else { scd30.getCalibrationType(&value); } + I2cSetClock(); ResponseCmndNumber(value); }; void CmndScd30Calibrate(void) { uint16_t value = 0; + I2cSetClock(50000); if (XdrvMailbox.data_len > 0) { value = XdrvMailbox.payload; scd30.setForcedRecalibrationFactor(value); } else { scd30.getForcedRecalibrationFactor(&value); } + I2cSetClock(); ResponseCmndNumber(value); }; void CmndScd30Firmware(void) { uint8_t major = 0; uint8_t minor = 0; + I2cSetClock(50000); int error = scd30.getFirmwareVersion(&major, &minor); + I2cSetClock(); if (!error) { float firmware = major + ((float)minor / 100); ResponseCmndFloat(firmware, 2); @@ -256,6 +271,7 @@ void CmndScd30Firmware(void) { void CmndScd30Interval(void) { uint16_t value = 0; + I2cSetClock(50000); if (XdrvMailbox.data_len > 0) { value = XdrvMailbox.payload; int error = scd30.setMeasurementInterval(value); @@ -264,28 +280,33 @@ void CmndScd30Interval(void) { } } scd30.getMeasurementInterval(&value); + I2cSetClock(); ResponseCmndNumber(value); }; void CmndScd30Pressure(void) { uint16_t value = 0; + I2cSetClock(50000); if (XdrvMailbox.data_len > 0) { value = XdrvMailbox.payload; scd30.setAmbientPressure(value); } else { scd30.getAmbientPressure(&value); } + I2cSetClock(); ResponseCmndNumber(value); }; void CmndScd30TempOffset(void) { uint16_t value = 0; + I2cSetClock(50000); if (XdrvMailbox.data_len > 0) { value = XdrvMailbox.payload; scd30.setTemperatureOffset(value); } else { scd30.getTemperatureOffset(&value); } + I2cSetClock(); ResponseCmndNumber(value); };