mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 11:16:34 +00:00
Added the hdc1080 device driver.
This commit is contained in:
parent
3cf6b8bd8a
commit
3908865473
@ -113,6 +113,7 @@
|
||||
| USE_DHT12 | - | - | - | - | x | - | - |
|
||||
| USE_DS1624 | - | - | - | - | x | - | - |
|
||||
| USE_AHT1x | - | - | - | - | - | - | - |
|
||||
| USE_HDC1080 | - | - | - | - | - | - | - |
|
||||
| USE_WEMOS_MOTOR_V1 | - | - | - | - | x | - | - |
|
||||
| | | | | | | | |
|
||||
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
|
||||
|
@ -66,3 +66,4 @@ Index | Define | Driver | Device | Address(es) | Description
|
||||
42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor
|
||||
43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 | Temperature and humidity sensor
|
||||
44 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x2D - 0x30 | WEMOS motor shield v1.0.0 (6612FNG)
|
||||
92 | USE_HDC1080 | xsns_92 | HDC1080 | 0x40 | Digital Humidity Sensor with Temperature Sensor
|
||||
|
@ -494,6 +494,8 @@
|
||||
// #define USE_DS1624 // [I2cDriver42] Enable DS1624, DS1621 temperature sensor (I2C addresses 0x48 - 0x4F) (+1k2 code)
|
||||
// #define USE_AHT1x // [I2cDriver43] Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code)
|
||||
// #define USE_WEMOS_MOTOR_V1 // [I2cDriver44] Enable Wemos motor driver V1 (I2C addresses 0x2D - 0x30) (+0k7 code)
|
||||
// #define USE_HDC1080 // [I2cDriver92] Enable HDC1080 temperature/humidity sensor
|
||||
|
||||
// #define WEMOS_MOTOR_V1_ADDR 0x30 // Default I2C address 0x30
|
||||
// #define WEMOS_MOTOR_V1_FREQ 1000 // Default frequency
|
||||
|
||||
|
@ -1113,35 +1113,6 @@ void CmndSwitchDebounce(void)
|
||||
ResponseCmndNumber(Settings.switch_debounce);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the Serial port number of bits, parity and stop bits.
|
||||
* For the time being this command only has effect on the hardware
|
||||
* serial port (GPIO1 and GPIO3)
|
||||
*
|
||||
* Meaning of the values:
|
||||
*
|
||||
* 0 - 7N1 (7 data bits / no parity / 1 stop bit)
|
||||
* 1 - 7E1 (7 data bits / even parity / 1 stop bit)
|
||||
* 2 - 8N1 (8 data bits / no parity / 1 stop bit)
|
||||
* 3 - 8E1 (8 data bits / even parity / 1 stop bit)
|
||||
*
|
||||
*/
|
||||
|
||||
void CmndSerialConfig(void)
|
||||
{
|
||||
// a frugal validation to check if the provided serial port mode is valid:
|
||||
|
||||
if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 3) {
|
||||
uint8_t mode = (uint8_t) (XdrvMailbox.payload & 3);
|
||||
|
||||
SetSerialConfig(mode);
|
||||
}
|
||||
|
||||
SerialCfg config = SettingToSerialCfg(Settings.serial_config);
|
||||
|
||||
ResponseCmndNumber(config.mode);
|
||||
}
|
||||
|
||||
void CmndBaudrate(void)
|
||||
{
|
||||
if (XdrvMailbox.payload >= 300) {
|
||||
|
@ -257,6 +257,10 @@ void GetFeatures(void)
|
||||
#ifdef USE_HTU
|
||||
feature_sns1 |= 0x00000200; // xsns_08_htu21.ino
|
||||
#endif
|
||||
// TODO not sure if is the correct feature setting for this sensor:
|
||||
#ifdef USE_HDC1080
|
||||
feature_sns1 |= 0x00000200; // xsns_92_hdc1080.ino
|
||||
#endif
|
||||
#ifdef USE_BMP
|
||||
feature_sns1 |= 0x00000400; // xsns_09_bmp.ino
|
||||
#endif
|
||||
|
@ -182,6 +182,9 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
|
||||
#define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0k7 code)
|
||||
#define USE_DS1624 // Add I2C code for DS1624, DS1621 sensor
|
||||
//#define USE_AHT1x // Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code)
|
||||
#define USE_HDC1080 // Enable HDC1080 temperature/humidity sensor
|
||||
|
||||
|
||||
#define USE_WEMOS_MOTOR_V1 // Enable Wemos motor driver V1 (I2C addresses 0x2D - 0x30) (+0k7 code)
|
||||
#define WEMOS_MOTOR_V1_ADDR 0x30 // Default I2C address 0x30
|
||||
#define WEMOS_MOTOR_V1_FREQ 1000 // Default frequency
|
||||
|
358
tasmota/xsns_92_hdc1080.ino
Normal file
358
tasmota/xsns_92_hdc1080.ino
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
xsns_92_hdc1080.ino - Texas Instruments HDC1080 temperature and humidity sensor support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Luis Teixeira
|
||||
|
||||
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
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_HDC1080
|
||||
/*********************************************************************************************\
|
||||
* HDC1080 - Temperature and Humidy sensor
|
||||
*
|
||||
* Source: Luis Teixeira
|
||||
*
|
||||
* I2C Address: 0x40
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_92 92
|
||||
#define XI2C_92 92 // See I2CDEVICES.md
|
||||
|
||||
#define HDC1080_ADDR 0x40
|
||||
|
||||
// Registers:
|
||||
|
||||
#define HDC_REG_TEMP 0x00 // Temperature register
|
||||
#define HDC_REG_RH 0x01 // Humidity register
|
||||
#define HDC_REG_CONFIG 0x02 // Configuration register
|
||||
#define HDC_REG_SERIAL1 0xFB // First 2 bytes of the serial ID
|
||||
#define HDC_REG_SERIAL2 0xFC // Mid 2 bytes of the serial ID
|
||||
#define HDC_REG_SERIAL3 0xFD // Last bits of the serial ID
|
||||
#define HDC_REG_MAN_ID 0xFE // Manufacturer ID
|
||||
#define HDC_REG_DEV_ID 0xFF // Device ID
|
||||
|
||||
// Expected constant values of some of the registers:
|
||||
|
||||
#define HDC1080_MAN_ID 0x5449 // Manufacturer ID (Texas Instruments)
|
||||
#define HDC1080_DEV_ID 0x1050 // Device ID (valid for the HDC1080)
|
||||
|
||||
// Possible values for the configuration register fields:
|
||||
|
||||
#define HDC1080_HEAT_OFF 0x00
|
||||
#define HDC1080_HEAT_ON 0x01
|
||||
#define HDC1080_ACQ_SEQ_ON 1
|
||||
#define HDC1080_ACQ_SEQ_OFF 0
|
||||
#define HDC1080_MEAS_RES_14 0x00
|
||||
#define HDC1080_MEAS_RES_11 0x01
|
||||
#define HDC1080_MEAS_RES_8 0x02
|
||||
|
||||
#define HDC1080_CONV_TIME 15 // Assume 6.50 + 6.35 ms + x of conversion delay for this device
|
||||
#define HDC1080_TEMP_MULT 0.0025177
|
||||
#define HDC1080_RH_MULT 0.0025177
|
||||
#define HDC1080_TEMP_OFFSET 40
|
||||
|
||||
const char kHdcTypes[] PROGMEM = "HDC1080";
|
||||
|
||||
uint8_t hdc_address;
|
||||
uint8_t hdc_type = 0;
|
||||
|
||||
float hdc_temperature = 0;
|
||||
float hdc_humidity = 0;
|
||||
uint8_t hdc_valid = 0;
|
||||
char hdc_types[1];
|
||||
|
||||
/**
|
||||
* Reads the device ID register.
|
||||
*
|
||||
*/
|
||||
uint16_t HdcReadDeviceId(void) {
|
||||
uint16_t deviceID = 0;
|
||||
|
||||
deviceID = I2cRead16(HDC1080_ADDR, HDC_REG_DEV_ID);
|
||||
|
||||
return deviceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the acquisition mode of the sensor. The
|
||||
* HDC1080 supports the acquisition of temperature
|
||||
* and humidity in a single I2C transaction.
|
||||
*
|
||||
* MODE = 0 -> Temperature or Humidity is acquired.
|
||||
* MODE = 1 -> Temperature and Humidity are acquired in sequence, Temperature first
|
||||
*
|
||||
*/
|
||||
void HdcSetAcqMode(bool mode) {
|
||||
uint16_t current = I2cRead16(HDC1080_ADDR, HDC_REG_CONFIG);
|
||||
|
||||
// bit 12 of the register contains the MODE field
|
||||
// so we shift our value to that position and
|
||||
// apply the bit mask to preserve the remaining bits
|
||||
// of the register:
|
||||
|
||||
current &= (uint16_t) ((mode << 12) | 0xEFFF);
|
||||
|
||||
I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the temperature sampling resolution of the sensor.
|
||||
*
|
||||
* This particular device provides two options:
|
||||
*
|
||||
* TRES = 0 -> 14 bit resolution
|
||||
* TRES = 1 -> 11 bit resolution
|
||||
*
|
||||
*/
|
||||
void HdcSetTemperatureResolution(uint8_t resolution) {
|
||||
uint16_t current = I2cRead16(HDC1080_ADDR, HDC_REG_CONFIG);
|
||||
|
||||
// bit 10 of the register contains the TRES field
|
||||
// so we shift our value to that position and
|
||||
// apply the bit mask to preserve the remaining bits
|
||||
// of the register:
|
||||
|
||||
current &= (uint16_t) ((resolution << 10) | 0xFBFF);
|
||||
|
||||
I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the humidity sampling resolution of the sensor.
|
||||
*
|
||||
* This particular device provides three options:
|
||||
*
|
||||
* HRES = 0 -> 14 bit resolution
|
||||
* HRES = 1 -> 11 bit resolution
|
||||
* HRES = 2 -> 8 bit resolution
|
||||
*
|
||||
*/
|
||||
void HdcSetHumidityResolution(uint8_t resolution) {
|
||||
uint16_t current = I2cRead16(HDC1080_ADDR, HDC_REG_CONFIG);
|
||||
|
||||
// bits 9:8 of the register contain the HRES field
|
||||
// so we shift our value to that position and
|
||||
// apply the bit mask to preserve the remaining bits
|
||||
// of the register:
|
||||
|
||||
current &= (uint16_t) ((resolution << 8) | 0xFCFF);
|
||||
|
||||
I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a soft reset on the device.
|
||||
*
|
||||
* RST = 1 -> software reset
|
||||
*
|
||||
*/
|
||||
void HdcReset(void) {
|
||||
uint16_t current = I2cRead16(HDC1080_ADDR, HDC_REG_CONFIG);
|
||||
|
||||
// bits 9:8 of the register contain the RST flag
|
||||
// so we set it to 1:
|
||||
|
||||
current |= 0x8000;
|
||||
|
||||
I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, current);
|
||||
|
||||
delay(15); // Not sure how long it takes to reset. Assuming 15ms
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the heater in order to reduce the accumulated
|
||||
* offset when the sensor is exposed for long periods
|
||||
* at high humidity levels.
|
||||
*
|
||||
* HEAT = 0 -> heater off
|
||||
* HEAT = 1 -> heater on
|
||||
*
|
||||
*/
|
||||
void HdcHeater(uint8_t heater) {
|
||||
uint16_t current = I2cRead16(HDC1080_ADDR, HDC_REG_CONFIG);
|
||||
|
||||
// bits 13 of the register contain the HEAT flag
|
||||
// so we set it according to the value of the heater argument:
|
||||
|
||||
current &= (uint16_t) ((heater << 13) | 0xDFFF);
|
||||
|
||||
I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, current);
|
||||
}
|
||||
|
||||
void HdcInit(void)
|
||||
{
|
||||
HdcReset();
|
||||
HdcHeater(HDC1080_HEAT_OFF);
|
||||
HdcSetAcqMode(HDC1080_ACQ_SEQ_ON);
|
||||
HdcSetTemperatureResolution(HDC1080_MEAS_RES_14);
|
||||
HdcSetHumidityResolution(HDC1080_MEAS_RES_14);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a temperature and humidity measurement, and calls
|
||||
* the conversion function providing the results in the correct
|
||||
* unit according to the device settings.
|
||||
*
|
||||
*/
|
||||
bool HdcRead(void) {
|
||||
int8_t status = 0;
|
||||
uint16_t sensor_data[2];
|
||||
|
||||
// In this sensor we must start by performing a write to the
|
||||
// temperature register. This signals the sensor to begin a
|
||||
// measurement:
|
||||
|
||||
// TODO initialize the measurement mode and
|
||||
// read both registers in a single transaction:
|
||||
|
||||
Wire.beginTransmission(HDC1080_ADDR);
|
||||
Wire.write(HDC_REG_TEMP);
|
||||
|
||||
if (Wire.endTransmission() != 0) { // In case of error
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("HdcRead: failed to write to device for performing acquisition."));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
delay(HDC1080_CONV_TIME); // Sensor time at max resolution
|
||||
|
||||
// reads the temperature and humidity in a single transaction:
|
||||
|
||||
status = I2cReadBuffer(HDC1080_ADDR, HDC_REG_TEMP, (uint8_t*) sensor_data, 4);
|
||||
|
||||
if(status != 0) {
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: failed to read HDC_REG_TEMP. Status = %d"), status);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// read the temperature from the first 16 bits of the result
|
||||
|
||||
hdc_temperature = ConvertTemp(HDC1080_TEMP_MULT * (float) (sensor_data[0]) - HDC1080_TEMP_OFFSET);
|
||||
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: temperature successfully converted. Value = %f"), hdc_temperature);
|
||||
|
||||
// read the humidity from the last 16 bits of the result
|
||||
|
||||
hdc_humidity = HDC1080_RH_MULT * (float) (sensor_data[1]);
|
||||
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: humidity successfully converted. Value = %f"), hdc_humidity);
|
||||
|
||||
if (hdc_humidity > 100) { hdc_humidity = 100.0; }
|
||||
|
||||
if (hdc_humidity < 0) { hdc_humidity = 0.01; }
|
||||
|
||||
ConvertHumidity(hdc_humidity); // Set global humidity
|
||||
|
||||
hdc_valid = SENSOR_MAX_MISS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void HdcDetect(void)
|
||||
{
|
||||
hdc_address = HDC1080_ADDR;
|
||||
|
||||
if (I2cActive(hdc_address)) {
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcDetect: Address = 0x%02X already in use."), hdc_address);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
hdc_type = HdcReadDeviceId();
|
||||
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcDetect: detected device with id = 0x%04X"), hdc_type);
|
||||
|
||||
if (hdc_type == HDC1080_DEV_ID) {
|
||||
HdcInit();
|
||||
GetTextIndexed(hdc_types, sizeof(hdc_types), 0, kHdcTypes);
|
||||
I2cSetActiveFound(hdc_address, hdc_types);
|
||||
}
|
||||
}
|
||||
|
||||
void HdcEverySecond(void) {
|
||||
if (uptime &1) { // Every 2 seconds
|
||||
if (!HdcRead()) {
|
||||
AddLogMissed(hdc_types, hdc_valid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HdcShow(bool json) {
|
||||
if (hdc_valid) {
|
||||
char temperature[33];
|
||||
|
||||
dtostrfd(hdc_temperature, Settings.flag2.temperature_resolution, temperature);
|
||||
char humidity[33];
|
||||
dtostrfd(hdc_humidity, Settings.flag2.humidity_resolution, humidity);
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(JSON_SNS_TEMPHUM, hdc_type, temperature, humidity);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (0 == tele_period) {
|
||||
DomoticzTempHumSensor(temperature, humidity);
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_KNX
|
||||
if (0 == tele_period) {
|
||||
KnxSensor(KNX_TEMPERATURE, hdc_temperature);
|
||||
KnxSensor(KNX_HUMIDITY, hdc_humidity);
|
||||
}
|
||||
#endif // USE_KNX
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_TEMP, hdc_types, temperature, TempUnit());
|
||||
WSContentSend_PD(HTTP_SNS_HUM, hdc_types, humidity);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns92(uint8_t function)
|
||||
{
|
||||
if (!I2cEnabled(XI2C_92)) { return false; }
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (FUNC_INIT == function) {
|
||||
HdcDetect();
|
||||
}
|
||||
else if (hdc_type) {
|
||||
switch (function) {
|
||||
case FUNC_EVERY_SECOND:
|
||||
HdcEverySecond();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
HdcShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_SENSOR:
|
||||
HdcShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_HDC1080
|
||||
#endif // USE_I2C
|
||||
|
@ -178,7 +178,7 @@ a_features = [[
|
||||
"USE_INA219","USE_SHT3X","USE_MHZ19","USE_TSL2561",
|
||||
"USE_SENSEAIR","USE_PMS5003","USE_MGS","USE_NOVA_SDS",
|
||||
"USE_SGP30","USE_SR04","USE_SDM120","USE_SI1145",
|
||||
"USE_SDM630","USE_LM75AD","USE_APDS9960","USE_TM1638"
|
||||
"USE_SDM630","USE_LM75AD","USE_APDS9960","USE_TM1638", "USE_HDC1080"
|
||||
],[
|
||||
"USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050",
|
||||
"USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766",
|
||||
|
Loading…
x
Reference in New Issue
Block a user