mirror of https://github.com/arendst/Tasmota.git
Add support for Sensirion SHT4X using define USE_SHT3X (#15349)
This commit is contained in:
parent
d7ffd01f1f
commit
dae1b32995
|
@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
|
|||
## [11.1.0.4]
|
||||
### Added
|
||||
- Support for HYTxxx temperature and humidity sensor (#15715)
|
||||
- Support for Sensirion SHT4X using define USE_SHT3X (#15349)
|
||||
|
||||
### Changed
|
||||
- Restructured tasmota source directories taking benefit from PlatformIO Core v6.0.2
|
||||
|
|
|
@ -31,7 +31,8 @@ Index | Define | Driver | Device | Address(es) | Description
|
|||
13 | USE_ADS1115 | xsns_12 | ADS1115 | 0x48 - 0x4B | 4-channel 16-bit A/D converter
|
||||
14 | USE_INA219 | xsns_13 | INA219 | 0x40 - 0x41, 0x44 - 0x45 | Low voltage current sensor
|
||||
15 | USE_SHT3X | xsns_14 | SHT3X | 0x44 - 0x45 | Temperature and Humidity sensor
|
||||
15 | USE_SHT3X | xsns_14 | SHTC3 | 0x70 | Temperature and Humidity sensor
|
||||
15 | USE_SHT3X | xsns_14 | SHT4X | 0x44 - 0x45 | Temperature and Humidity sensor
|
||||
15 | USE_SHT3X | xsns_14 | SHTCX | 0x70 | Temperature and Humidity sensor
|
||||
16 | USE_TSL2561 | xsns_16 | TSL2561 | 0x29, 0x39, 0x49 | Light intensity sensor
|
||||
17 | USE_MGS | xsns_19 | Grove | 0x04 | Multichannel gas sensor
|
||||
18 | USE_SGP30 | xsns_21 | SGP30 | 0x58 | Gas (TVOC) and air quality sensor
|
||||
|
@ -102,4 +103,3 @@ Index | Define | Driver | Device | Address(es) | Description
|
|||
66 | USE_PCF85363 | xsns_99 | PCF85363 | 0x51 | Real time clock
|
||||
67 | USE_DS3502 | xdrv_61 | DS3502 | 0x28 - 0x2B | Digital potentiometer
|
||||
68 | USE_HYT | xsns_97 | HYTxxx | 0x28 | Temperature and Humidity sensor
|
||||
|
|
@ -114,6 +114,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
|
|||
- Command ``SspmDisplay 2`` to display Sonoff SPM energy data in GUI for user tab-selected relay modules [#13447](https://github.com/arendst/Tasmota/issues/13447)
|
||||
- Support for Sonoff MS01 soil moisture sensor [#15335](https://github.com/arendst/Tasmota/issues/15335)
|
||||
- Support for daisy chaining MAX7219 displays [#15345](https://github.com/arendst/Tasmota/issues/15345)
|
||||
- Support for Sensirion SHT4X using define USE_SHT3X [#15349](https://github.com/arendst/Tasmota/issues/15349)
|
||||
- Sonoff SPM delayed SetPowerOnState [#13447](https://github.com/arendst/Tasmota/issues/13447)
|
||||
- Support for Sonoff SPM v1.2.0
|
||||
- Support for Sonoff Zigbee Bridge Pro by Stephan Hadinger [#15701](https://github.com/arendst/Tasmota/issues/15701)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
xsns_14_sht3x.ino - SHT3X temperature and humidity sensor support for Tasmota
|
||||
xsns_14_sht3x.ino - SHT3X, SHT4X and SHTCX temperature and humidity sensor support for Tasmota
|
||||
|
||||
Copyright (C) 2021 Theo Arends
|
||||
Copyright (C) 2022 Theo Arends, Stefan Tibus
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,85 +20,141 @@
|
|||
#ifdef USE_I2C
|
||||
#ifdef USE_SHT3X
|
||||
/*********************************************************************************************\
|
||||
* SHT3X and SHTC3 - Temperature and Humidity
|
||||
* Sensirion I2C temperature and humidity sensors
|
||||
*
|
||||
* I2C Address: 0x44, 0x45 or 0x70 (SHTC3)
|
||||
* This driver supports the following sensors:
|
||||
* - SHT3x series: SHT30, SHT31, SHT35 (addresses: A: 0x44, B: 0x45)
|
||||
* - SHTC series: SHTC1, SHTC3 (address: 0x70)
|
||||
* - SHT4x series: SHT40, SHT41, SHT45 (addresses: A: 0x44, B: 0x45)
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_14 14
|
||||
#define XI2C_15 15 // See I2CDEVICES.md
|
||||
|
||||
#define SHT3X_ADDR_GND 0x44 // address pin low (GND)
|
||||
#define SHT3X_ADDR_VDD 0x45 // address pin high (VDD)
|
||||
#define SHTC3_ADDR 0x70 // address for shtc3 sensor
|
||||
#define SHT3X_ADDRESSES 2 // 2 addresses for SHT3x
|
||||
#define SHT3X_ADDR_GND 0x44 // Address A pin low (GND)
|
||||
#define SHT3X_ADDR_VDD 0x45 // Address B pin high (VDD)
|
||||
#define SHTCX_ADDRESSES 1 // 1 address for SHTCx
|
||||
#define SHTCX_ADDR 0x70 // Address for SHTCx sensors
|
||||
#define SHT4X_ADDRESSES 2 // 2 addresses for SHT4x
|
||||
#define SHT4X_ADDR_A 0x44 // Address SHT4x A
|
||||
#define SHT4X_ADDR_B 0x45 // Address SHT4x B
|
||||
|
||||
#define SHT3X_MAX_SENSORS 3
|
||||
#define SHT3X_MAX_SENSORS 3 // Only one of 0x44, 0x45 and 0x70
|
||||
|
||||
const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3";
|
||||
uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR };
|
||||
enum SHT3X_Types {
|
||||
SHT3X_TYPE_SHT3X,
|
||||
SHT3X_TYPE_SHTCX,
|
||||
SHT3X_TYPE_SHT4X
|
||||
};
|
||||
|
||||
const char kSht3xTypes[] PROGMEM = "SHT3X|SHTC3|SHT4X";
|
||||
uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTCX_ADDR };
|
||||
|
||||
uint8_t sht3x_count = 0;
|
||||
struct SHT3XSTRUCT {
|
||||
uint8_t address; // I2C bus address
|
||||
char types[6]; // Sensor type name and address - "SHT3X-0xXX"
|
||||
uint8_t type; // Sensor type
|
||||
uint8_t address; // I2C bus address
|
||||
char types[6]; // Sensor type name and address, e.g. "SHT3X"
|
||||
} sht3x_sensors[SHT3X_MAX_SENSORS];
|
||||
|
||||
bool Sht3xRead(float &t, float &h, uint8_t sht3x_address)
|
||||
{
|
||||
unsigned int data[6];
|
||||
uint8_t Sht3xComputeCrc(uint8_t data[], uint8_t len) {
|
||||
// Compute CRC as per datasheet
|
||||
uint8_t crc = 0xFF;
|
||||
|
||||
for (uint8_t x = 0; x < len; x++) {
|
||||
crc ^= data[x];
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (crc & 0x80) {
|
||||
crc = (crc << 1) ^ 0x31;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
bool Sht3xRead(uint32_t type, float &t, float &h, uint8_t i2c_address) {
|
||||
uint8_t data[6];
|
||||
|
||||
t = NAN;
|
||||
h = NAN;
|
||||
|
||||
Wire.beginTransmission(sht3x_address);
|
||||
if (SHTC3_ADDR == sht3x_address) {
|
||||
Wire.write(0x35); // Wake from
|
||||
Wire.write(0x17); // sleep
|
||||
Wire.endTransmission();
|
||||
Wire.beginTransmission(sht3x_address);
|
||||
Wire.write(0x78); // Disable clock stretching ( I don't think that wire library support clock stretching )
|
||||
Wire.write(0x66); // High resolution
|
||||
} else {
|
||||
Wire.write(0x2C); // Enable clock stretching
|
||||
Wire.write(0x06); // High repeatability
|
||||
Wire.beginTransmission(i2c_address);
|
||||
switch (type) {
|
||||
case SHT3X_TYPE_SHT3X:
|
||||
// TODO: Clock stretching is used for SHT3x but not for SHTC3. Why?
|
||||
Wire.write(0x2C); // Enable clock stretching
|
||||
Wire.write(0x06); // High repeatability measurement
|
||||
break;
|
||||
case SHT3X_TYPE_SHTCX:
|
||||
Wire.write(0x35); // Wake from
|
||||
Wire.write(0x17); // sleep
|
||||
Wire.endTransmission();
|
||||
Wire.beginTransmission(i2c_address);
|
||||
// TODO: Clock stretching is used for SHT3x but not for SHTC3. Why?
|
||||
Wire.write(0x78); // Disable clock stretching
|
||||
Wire.write(0x66); // Normal mode measurement
|
||||
break;
|
||||
case SHT3X_TYPE_SHT4X:
|
||||
Wire.write(0xFD); // High repeatability measurement
|
||||
break;
|
||||
}
|
||||
if (Wire.endTransmission() != 0) { // Stop I2C transmission
|
||||
if (Wire.endTransmission() != 0) { // Stop I2C transmission
|
||||
return false;
|
||||
}
|
||||
delay(30); // Timing verified with logic analyzer (10 is to short)
|
||||
Wire.requestFrom(sht3x_address, (uint8_t)6); // Request 6 bytes of data
|
||||
delay(30); // Timing verified with logic analyzer (10 is to short)
|
||||
Wire.requestFrom(i2c_address, (uint8_t)6); // Request 6 bytes of data
|
||||
for (uint32_t i = 0; i < 6; i++) {
|
||||
data[i] = Wire.read(); // cTemp msb, cTemp lsb, cTemp crc, humidity msb, humidity lsb, humidity crc
|
||||
data[i] = Wire.read(); // temperature (MSB, LSB, CRC), humidity (MSB, LSB, CRC)
|
||||
};
|
||||
if ((Sht3xComputeCrc(&data[0], 2) != data[2]) || (Sht3xComputeCrc(&data[3], 2) != data[5])) {
|
||||
return false;
|
||||
}
|
||||
t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45);
|
||||
h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0));
|
||||
return (!isnan(t) && !isnan(h) && (h != 0));
|
||||
return (!isnan(t) && !isnan(h));
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void Sht3xDetect(void)
|
||||
{
|
||||
void Sht3xDetect(void) {
|
||||
float t;
|
||||
float h;
|
||||
|
||||
for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) {
|
||||
if (!I2cSetDevice(sht3x_addresses[i])) { continue; }
|
||||
float t;
|
||||
float h;
|
||||
if (Sht3xRead(t, h, sht3x_addresses[i])) {
|
||||
sht3x_sensors[sht3x_count].address = sht3x_addresses[i];
|
||||
GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes);
|
||||
I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types);
|
||||
sht3x_count++;
|
||||
if (i < 2) { // 0x44 and 0x45
|
||||
sht3x_sensors[sht3x_count].type = SHT3X_TYPE_SHT3X;
|
||||
if (!Sht3xRead(sht3x_sensors[sht3x_count].type, t, h, sht3x_addresses[i])) {
|
||||
sht3x_sensors[sht3x_count].type = SHT3X_TYPE_SHT4X;
|
||||
if (!Sht3xRead(sht3x_sensors[sht3x_count].type, t, h, sht3x_addresses[i])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else { // 0x70
|
||||
sht3x_sensors[sht3x_count].type = SHT3X_TYPE_SHTCX;
|
||||
if (!Sht3xRead(sht3x_sensors[sht3x_count].type, t, h, sht3x_addresses[i])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
sht3x_sensors[sht3x_count].address = sht3x_addresses[i];
|
||||
GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), SHT3X_TYPE_SHT3X, kSht3xTypes);
|
||||
I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types);
|
||||
sht3x_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void Sht3xShow(bool json)
|
||||
{
|
||||
void Sht3xShow(bool json) {
|
||||
float t;
|
||||
float h;
|
||||
char types[11];
|
||||
|
||||
for (uint32_t i = 0; i < sht3x_count; i++) {
|
||||
float t;
|
||||
float h;
|
||||
if (Sht3xRead(t, h, sht3x_sensors[i].address)) {
|
||||
char types[11];
|
||||
if (Sht3xRead(sht3x_sensors[i].type, t, h, sht3x_sensors[i].address)) {
|
||||
t = ConvertTemp(t);
|
||||
h = ConvertHumidity(h);
|
||||
strlcpy(types, sht3x_sensors[i].types, sizeof(types));
|
||||
if (sht3x_count > 1) {
|
||||
snprintf_P(types, sizeof(types), PSTR("%s%c%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); // "SHT3X-0xXX"
|
||||
|
@ -112,8 +168,7 @@ void Sht3xShow(bool json)
|
|||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns14(uint8_t function)
|
||||
{
|
||||
bool Xsns14(uint8_t function) {
|
||||
if (!I2cEnabled(XI2C_15)) { return false; }
|
||||
|
||||
bool result = false;
|
||||
|
@ -137,4 +192,4 @@ bool Xsns14(uint8_t function)
|
|||
}
|
||||
|
||||
#endif // USE_SHT3X
|
||||
#endif // USE_I2C
|
||||
#endif // USE_I2C
|
Loading…
Reference in New Issue