SCD30 Lowered I2C clock from 100k to 50k (#15438)

This commit is contained in:
Theo Arends 2024-09-19 11:15:04 +02:00
parent d0d075a1b4
commit a9f0623769
4 changed files with 62 additions and 13 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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
\*-------------------------------------------------------------------------------------------*/

View File

@ -69,26 +69,31 @@ struct {
} Scd30;
void Scd30Detect(void) {
if (!I2cSetDevice(SCD30_ADDRESS)) { return; }
I2cSetClock(50000);
if (I2cSetDevice(SCD30_ADDRESS)) {
scd30.begin();
uint8_t major = 0;
uint8_t minor = 0;
if (scd30.getFirmwareVersion(&major, &minor)) { return; }
if (scd30.getMeasurementInterval(&Scd30.interval)) { return; }
if (scd30.beginMeasuring()) { return; }
if (!scd30.getFirmwareVersion(&major, &minor)) {
if (!scd30.getMeasurementInterval(&Scd30.interval)) {
if (!scd30.beginMeasuring()) {
I2cSetActiveFound(SCD30_ADDRESS, "SCD30");
Scd30.found = true;
// 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,6 +134,7 @@ void Scd30Update(void) {
#ifdef SCD30_DEBUG
AddLog(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, Scd30.loop_count);
#endif
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);
};