# HDC1080 — Driver and daemon component for ESP-IDF
ESP-IDF hdc1080 sensor component service/driver for the [Texas Instruments HDC1080](https://www.ti.com/product/HDC1080) temperature and humidity sensor. Initialize once, then read values whenever you need them. The driver handles all I2C communication, polling, and error management internally as a daemon.
## ESP-IDF Compatibility
| ESP-IDF Version | Status |
|-----------------|--------|
| >= 5.2 | Required (new I2C master driver) |
| 6.0+ | Compatible |
## Supported Targets
Any ESP-IDF target with I2C support (ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-H2, etc.). No target-specific code is used.
## Features
- **Automatic polling** at a configurable rate (default 800 ms via Kconfig).
- **Optional I2C bus management** — driver can set up the bus for you, or use your existing bus.
- **Thread-safe** data store protected by FreeRTOS mutex.
- **Status byte** with error tracking and user-acknowledge pattern.
- **Derived values** (dew point, SVP, VPD) computed automatically each poll cycle.
- **Handle-based API** for clean lifecycle management.
- Chip identity verification during init.
- Configurable sensor resolution (temperature and humidity).
- On-chip heater control.
## Application and Component Workflow
```
/* APPLICATION */
- Configure
- Init
- Read
- De-Init (if required otherwise just let it go and read when you need)
/* COMPONENT INTERNALLY */
- Periodic timer is set
- Conversion is triggered
- One shot timer is set to wait for conversion
- Results are read, computed
- Data is stored using a mutex making it thread safe
```
## Installation
### Via ESP Component Manager
```yaml
dependencies:
grstat/hdc1080:
version: ">=1.0.0"
```
### As a Project Component
Clone and copy into your `components/` directory.
### As a Git Dependency
```yaml
dependencies:
hdc1080:
git: "https://github.com/grstat/esp32-hdc1080.git"
version: ">=1.0.0"
```
## Quick Start
```c
#include "hdc1080.h"
void app_main(void) {
// 1. INIT (driver handles I2C setup if CONFIG_HDC1080_MANAGE_I2C=y)
hdc1080_init_config_t config = {
.sensor_cfg = {
.humidity_resolution = HDC1080_HRES_14BIT,
.temperature_resolution = HDC1080_TRES_14BIT,
.mode_of_acquisition = HDC1080_MODE_BOTH,
.heater = HDC1080_HEATER_OFF,
},
};
hdc1080_handle_t sensor;
hdc1080_init(&config, &sensor);
// 2. READ VALUES (anytime, from any task)
float temp, humidity;
hdc1080_get_temperature(sensor, &temp);
hdc1080_get_humidity(sensor, &humidity);
// 3. CLEANUP
hdc1080_deinit(sensor);
}
```
## Configuration Options (Menuconfig)
Access via `idf.py menuconfig` → **Component config → HDC1080 Driver Configuration**:
| Option | Default | Description |
|--------|---------|-------------|
| `CONFIG_HDC1080_MANAGE_I2C` | y | Let the driver manage the I2C bus |
| `CONFIG_HDC1080_I2C_SCL` | 22 | SCL GPIO (if managing I2C) |
| `CONFIG_HDC1080_I2C_SDA` | 21 | SDA GPIO (if managing I2C) |
| `CONFIG_HDC1080_I2C_PORT` | 0 | I2C port number (if managing I2C) |
| `CONFIG_HDC1080_I2C_FREQ_HZ` | 400000 | I2C frequency (if managing I2C) |
| `CONFIG_HDC1080_POLL_RATE_MS` | 800 | How often to poll the sensor (ms) |
| `CONFIG_HDC1080_CONVERSION_TIME_US` | 15000 | Conversion wait time (µs) |
## API Reference
### Lifecycle
| Function | Description |
|----------|-------------|
| `hdc1080_init()` | Initialize, verify chip, start polling |
| `hdc1080_deinit()` | Stop polling, free all resources |
### Data Getters
| Function | Returns |
|----------|---------|
| `hdc1080_get_readings()` | Temperature + humidity + status (all at once) |
| `hdc1080_get_temperature()` | Temperature in °C |
| `hdc1080_get_humidity()` | Relative humidity in % |
| `hdc1080_get_dewpoint()` | Dew point in °C |
| `hdc1080_get_svp()` | Saturation vapor pressure in kPa |
| `hdc1080_get_vpd()` | Vapor pressure deficit in kPa |
### Status & Error Handling
| Function | Description |
|----------|-------------|
| `hdc1080_get_status()` | Get current status code |
| `hdc1080_get_error_text()` | Get human-readable error string |
| `hdc1080_clear_error()` | Acknowledge error, resume polling |
## Error Handling Pattern
When an I2C error occurs:
1. The status byte is set to the error code.
2. Polling **pauses** (no more I2C traffic until acknowledged).
3. Getter functions still return the **last known good** values.
4. Your code checks `hdc1080_get_status()` and handles the error.
5. Call `hdc1080_clear_error()` to acknowledge and resume polling.
6. On the next poll cycle, the driver retries the read.
```c
hdc1080_status_t status;
hdc1080_get_status(sensor, &status);
if (status != HDC1080_STATUS_OK) {
ESP_LOGE(TAG, "Sensor error: %s", hdc1080_get_error_text(status));
hdc1080_clear_error(sensor); // ACKNOWLEDGE AND RETRY
}
```
### Status Codes
| Code | Meaning |
|------|---------|
| `HDC1080_STATUS_OK` | Last read successful |
| `HDC1080_STATUS_I2C_ERROR` | I2C bus communication failure |
| `HDC1080_STATUS_NACK` | Sensor did not acknowledge (disconnected?) |
| `HDC1080_STATUS_TIMEOUT` | I2C transaction timed out |
| `HDC1080_STATUS_NOT_READY` | No data yet (just initialized) |
| `HDC1080_STATUS_ID_MISMATCH` | Wrong chip on the bus |
## Thread Safety
All API functions are thread-safe. You can call getters from any task at any time. Internal state is protected by RTOS mutex(s) with priority inheritance.
**NOT INTERRUPT SAFE !! Do NOT call from ISR** — the mutex cannot be taken from interrupt context.
## Shared I2C Bus
If you have other devices on the same I2C bus, disable `CONFIG_HDC1080_MANAGE_I2C` in menuconfig. Then create the bus yourself and pass the device handle:
```c
// You manage the bus
i2c_master_dev_handle_t my_dev_handle;
// ... create bus, add device at 0x40 ...
hdc1080_init_config_t config = {
.dev_handle = my_dev_handle,
.sensor_cfg = { /* ... */ },
};
hdc1080_handle_t sensor;
hdc1080_init(&config, &sensor);
```
## Hardware Requirements
- **Sensor:** HDC1080 (I2C address 0x40)
- **Bus:** I2C, up to 400 kHz
- **Voltage:** 3.3V
- **Pins:** SDA, SCL, VCC, GND
## Resource Usage
| Resource | Usage |
|----------|-------|
| Heap | ~300 bytes (device struct + mutex + timer internals) |
| esp_timer | 2 timers (periodic poll + one-shot conversion) |
| FreeRTOS | 2 mutexes (data store + I2C access) |
| Tasks | None created |
| I2C bus | Managed or shared (configurable) |
## Project Structure
```
├── CMakeLists.txt
├── Kconfig # All driver configuration
├── hdc1080.c # Implementation
├── include/hdc1080.h # Public API
├── idf_component.yml # Component manager manifest
├── examples/hdc1080_example_main/
├── CHANGELOG.md
├── LICENSE
└── README.md
```
## Limitations
- **Single sensor per bus** — HDC1080 has a fixed I2C address (0x40), this is a limitation of the sensor itself
- **No ISR support** — mutexes use priority inheritance.
- **Polling only** — no interrupt, again a limitation of the sensor itself
- **Derived values use float** — requires FPU or software float.
## Example
See [`examples/hdc1080_example_main/`](examples/hdc1080_example_main/) for a complete working example.
## License
MIT. See [LICENSE](LICENSE).
idf.py add-dependency "grstat/hdc1080^1.0.2"