-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding driver for the Texas Instruments HDC1080 #7888
Changes from all commits
7c857b0
18f5143
83f9c7b
871fd1f
3cf6b8b
3908865
cb2cc9b
2a06a6b
e9d201a
4910e03
725b989
78a608d
2926981
b7907ae
b758699
99a0061
2441acd
a5ebdd3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Disable HDC for now as I need to tests it's consequences first. This also is in line with your change in BUILD.md where you rightfully disabled the sensor in all binaries. |
||
|
||
#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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,349 @@ | ||
/* | ||
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_65 65 | ||
#define XI2C_45 45 // 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_RST_ON 0x8000 | ||
#define HDC1080_HEAT_ON 0x2000 | ||
#define HDC1080_MODE_ON 0x1000 // acquision mode (temperature + humidity) | ||
#define HDC1080_TRES_11 0x400 | ||
#define HDC1080_HRES_11 0x100 | ||
#define HDC1080_HRES_8 0x80 | ||
|
||
// Constants: | ||
|
||
#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.0 | ||
|
||
const char* hdc_type_name = "HDC1080"; | ||
uint16_t hdc_manufacturer_id = 0; | ||
uint16_t hdc_device_id = 0; | ||
|
||
float hdc_temperature = 0.0; | ||
float hdc_humidity = 0.0; | ||
|
||
uint8_t hdc_valid = 0; | ||
|
||
bool is_reading = false; | ||
uint32_t hdc_next_read; | ||
|
||
/** | ||
* Reads the device ID register. | ||
* | ||
*/ | ||
uint16_t HdcReadDeviceId(void) { | ||
return I2cRead16(HDC1080_ADDR, HDC_REG_DEV_ID); | ||
} | ||
|
||
/** | ||
* Reads the manufacturer ID register. | ||
* | ||
*/ | ||
uint16_t HdcReadManufacturerId(void) { | ||
return I2cRead16(HDC1080_ADDR, HDC_REG_MAN_ID); | ||
} | ||
|
||
/** | ||
* Overwrites the configuration register with the provided config | ||
*/ | ||
void HdcConfig(uint16_t config) { | ||
I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, config); | ||
} | ||
|
||
/** | ||
* Performs a soft reset on the device. | ||
* | ||
* RST = 1 -> software reset | ||
* | ||
*/ | ||
void HdcReset(void) { | ||
uint16_t current = I2cRead16(HDC1080_ADDR, HDC_REG_CONFIG); | ||
|
||
// bit 15 of the configuration register contains the RST flag | ||
// so we set it to 1: | ||
|
||
current |= 0x8000; | ||
|
||
I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, current); | ||
|
||
delay(HDC1080_CONV_TIME); // Not sure how long it takes to reset. Assuming this value. | ||
} | ||
|
||
/** | ||
* Performs the write portion of the HDC1080 sensor transaction. This | ||
* action of writing to a register signals the beginning of the operation | ||
* (e.g. data acquisition). | ||
* | ||
* addr: the address of the I2C device we are talking to. | ||
* reg: the register where we are writing to. | ||
* | ||
* returns: 0 if the transmission was successfully completed, != 0 otherwise. | ||
*/ | ||
int8_t HdcTransactionOpen(uint8_t addr, uint8_t reg) { | ||
Wire.beginTransmission((uint8_t) addr); | ||
Wire.write((uint8_t) reg); | ||
return Wire.endTransmission(); | ||
} | ||
|
||
/** | ||
* Performs the read portion of the HDC1080 sensor transaction. | ||
* | ||
* addr: the address of the I2C device we are talking to. | ||
* reg_data: the pointer to the memory location where we will place the bytes that were read from the device | ||
* len: the number of bytes we expect to read | ||
* | ||
* returns: if the read operation was successful. != 0 otherwise. | ||
*/ | ||
int8_t HdcTransactionClose(uint8_t addr, uint8_t *reg_data, uint16_t len) { | ||
if (len != Wire.requestFrom((uint8_t) addr, (uint8_t) len)) { | ||
return 1; | ||
} | ||
|
||
while (len--) { | ||
*reg_data = (uint8_t)Wire.read(); | ||
reg_data++; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/** | ||
* The various initialization steps for this sensor. | ||
* | ||
*/ | ||
void HdcInit(void) { | ||
HdcReset(); | ||
HdcConfig(HDC1080_MODE_ON); | ||
} | ||
|
||
/** | ||
* Triggers the single transaction read of the T/RH sensor. | ||
* | ||
*/ | ||
bool HdcTriggerRead(void) { | ||
int8_t status = HdcTransactionOpen(HDC1080_ADDR, HDC_REG_TEMP); | ||
|
||
hdc_next_read = millis() + HDC1080_CONV_TIME; | ||
|
||
if(status) { | ||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcTriggerRead: failed to open the transaction for HDC_REG_TEMP. Status = %d"), status); | ||
|
||
return false; | ||
} | ||
|
||
is_reading = true; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is where you should put |
||
return true; | ||
} | ||
|
||
/** | ||
* Performs a temperature and humidity measurement, and calls | ||
* the conversion function providing the results in the correct | ||
* unit according to the device settings. | ||
* | ||
* returns: false if something failed during the read process. | ||
* | ||
*/ | ||
bool HdcRead(void) { | ||
int8_t status = 0; | ||
uint8_t sensor_data[4]; | ||
uint16_t temp_data = 0; | ||
uint16_t rh_data = 0; | ||
|
||
is_reading = false; | ||
|
||
status = HdcTransactionClose(HDC1080_ADDR, sensor_data, 4); | ||
|
||
if(status) { | ||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: failed to read HDC_REG_TEMP. Status = %d"), status); | ||
|
||
return false; | ||
} | ||
|
||
temp_data = (uint16_t) ((sensor_data[0] << 8) | sensor_data[1]); | ||
rh_data = (uint16_t) ((sensor_data[2] << 8) | sensor_data[3]); | ||
|
||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: temperature raw data: 0x%04x; humidity raw data: 0x%04x"), temp_data, rh_data); | ||
|
||
// read the temperature from the first 16 bits of the result | ||
|
||
hdc_temperature = ConvertTemp(HDC1080_TEMP_MULT * (float) (temp_data) - HDC1080_TEMP_OFFSET); | ||
|
||
hdc_humidity = HDC1080_RH_MULT * (float) (rh_data); | ||
|
||
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; | ||
} | ||
|
||
/** | ||
* Performs the detection of the HTC1080 sensor. | ||
* | ||
*/ | ||
|
||
void HdcDetect(void) { | ||
if (I2cActive(HDC1080_ADDR)) { | ||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcDetect: Address = 0x%02X already in use."), HDC1080_ADDR); | ||
|
||
return; | ||
} | ||
|
||
hdc_manufacturer_id = HdcReadManufacturerId(); | ||
hdc_device_id = HdcReadDeviceId(); | ||
|
||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcDetect: detected device with manufacturerId = 0x%04X and deviceId = 0x%04X"), hdc_manufacturer_id, hdc_device_id); | ||
|
||
if (hdc_device_id == HDC1080_DEV_ID) { | ||
HdcInit(); | ||
I2cSetActiveFound(HDC1080_ADDR, hdc_type_name); | ||
} | ||
} | ||
|
||
/** | ||
* As the name suggests, this function is called every second | ||
* for performing driver related logic. | ||
* | ||
*/ | ||
void HdcEverySecond(void) { | ||
if (uptime &1) { // Every 2 seconds | ||
if (!HdcTriggerRead()) { | ||
AddLogMissed((char*) hdc_type_name, hdc_valid); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Tasmota boilerplate for presenting the sensor data in the web UI, JSON for | ||
* the MQTT messages, and so on. | ||
* | ||
*/ | ||
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_name, 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_type_name, temperature, TempUnit()); | ||
WSContentSend_PD(HTTP_SNS_HUM, hdc_type_name, humidity); | ||
#endif // USE_WEBSERVER | ||
} | ||
} | ||
} | ||
|
||
/*********************************************************************************************\ | ||
* Interface | ||
\*********************************************************************************************/ | ||
|
||
bool Xsns65(uint8_t function) | ||
{ | ||
if (!I2cEnabled(XI2C_45)) { | ||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("Xsns65: I2C driver not enabled for this device.")); | ||
|
||
return false; | ||
} | ||
|
||
bool result = false; | ||
|
||
if (FUNC_INIT == function) { | ||
HdcDetect(); | ||
} | ||
else if (hdc_device_id) { | ||
switch (function) { | ||
case FUNC_EVERY_50_MSECOND: | ||
if(is_reading && TimeReached(hdc_next_read)) { | ||
if(!HdcRead()) { | ||
AddLogMissed((char*) hdc_type_name, hdc_valid); | ||
} | ||
} | ||
break; | ||
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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be a
[I2cDriver45]
? Looks like an artifact from the first patch.