diff --git a/app/src/main.c b/app/src/main.c index df7e5cd..221a545 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -116,12 +116,12 @@ int main(void) } LOG_INF("Initialized %s\n", lis->name); - // hdc = DEVICE_DT_GET(DT_NODELABEL(hdc1080)); - // if (!device_is_ready(dev)) - // { - // printf("Device %s not ready\n", hdc->name); - // return 0; - // } + hdc = DEVICE_DT_GET(DT_NODELABEL(hdc1080)); + if (!device_is_ready(hdc)) + { + printf("Device %s not ready\n", hdc->name); + return 0; + } while (1) { @@ -219,18 +219,24 @@ int main(void) return 0; } - // ret = sensor_sample_fetch(hdc); - // if (ret < 0) - // { - // LOG_ERR("Could not fetch sample (%d)", ret); - // return 0; - // } - // ret = sensor_channel_get(ina, SENSOR_CHAN_HUMIDITY, &humidity); - // if (ret < 0) - // { - // LOG_ERR("Could not get sample (%d)", ret); - // return 0; - // } + ret = sensor_sample_fetch(hdc); + if (ret < 0) + { + LOG_ERR("Could not fetch sample (%d)", ret); + return 0; + } + ret = sensor_channel_get(hdc, SENSOR_CHAN_AMBIENT_TEMP, &temperature); + if (ret < 0) + { + LOG_ERR("Could not get sample (%d)", ret); + return 0; + } + ret = sensor_channel_get(hdc, SENSOR_CHAN_HUMIDITY, &humidity); + if (ret < 0) + { + LOG_ERR("Could not get sample (%d)", ret); + return 0; + } sprintf(str_v, "V :%7.5f", voltage.val1 + voltage.val2 * 1e-6); sprintf(str_i, "I :%7.5f", current.val1 + current.val2 * 1e-6); @@ -245,21 +251,21 @@ int main(void) // printf("%s\t%s\t%s\t%s\n", str_v, str_i, str_p, str_t); cfb_framebuffer_clear(dev, false); - if (cfb_print(dev, str_ax, 0, 0)) + if (cfb_print(dev, str_t, 0, 0)) { printf("Failed to print a string\n"); continue; } - if (cfb_print(dev, str_ay, 0, 16)) - { - printf("Failed to print a string\n"); - continue; - } - if (cfb_print(dev, str_az, 0, 16 * 2)) + if (cfb_print(dev, str_h, 0, 16)) { printf("Failed to print a string\n"); continue; } + // if (cfb_print(dev, str_az, 0, 16 * 2)) + // { + // printf("Failed to print a string\n"); + // continue; + // } // if (cfb_print(dev, str_az_ref, 0, 16 * 3)) // { // printf("Failed to print a string\n"); diff --git a/boards/bh/mellifera_rev1/mellifera_rev1.dts b/boards/bh/mellifera_rev1/mellifera_rev1.dts index b3f6697..2bcba69 100644 --- a/boards/bh/mellifera_rev1/mellifera_rev1.dts +++ b/boards/bh/mellifera_rev1/mellifera_rev1.dts @@ -165,7 +165,7 @@ }; hdc1080: hdc1080@40 { - compatible = "ti,hdc20xx"; // FIXME: add proper support for this part. Hopefully these parts are close enough + compatible = "ti,hdc1080"; reg = <0x40>; }; diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 1b12c15..dde47f6 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -3,3 +3,4 @@ add_subdirectory_ifdef(CONFIG_EXAMPLE_SENSOR example_sensor) add_subdirectory_ifdef(CONFIG_BMX055 bmx055) +add_subdirectory_ifdef(CONFIG_HDC1080 hdc1080) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 52e2f51..60499d0 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -4,4 +4,5 @@ if SENSOR rsource "example_sensor/Kconfig" rsource "bmx055/Kconfig" +rsource "hdc1080/Kconfig" endif # SENSOR diff --git a/drivers/sensor/hdc1080/CMakeLists.txt b/drivers/sensor/hdc1080/CMakeLists.txt new file mode 100644 index 0000000..cafff00 --- /dev/null +++ b/drivers/sensor/hdc1080/CMakeLists.txt @@ -0,0 +1,2 @@ +zephyr_library() +zephyr_library_sources(hdc1080.c) diff --git a/drivers/sensor/hdc1080/Kconfig b/drivers/sensor/hdc1080/Kconfig new file mode 100644 index 0000000..6e337a7 --- /dev/null +++ b/drivers/sensor/hdc1080/Kconfig @@ -0,0 +1,6 @@ +config HDC1080 + bool "HDC1080" + default y + depends on DT_HAS_TI_HDC1080_ENABLED + help + Enable driver for HDC1080. diff --git a/drivers/sensor/hdc1080/hdc1080.c b/drivers/sensor/hdc1080/hdc1080.c new file mode 100644 index 0000000..747ee3c --- /dev/null +++ b/drivers/sensor/hdc1080/hdc1080.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_hdc1080 + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(hdc1080, CONFIG_SENSOR_LOG_LEVEL); + +const uint8_t REG_TEMPERATURE = 0x00; +const uint8_t REG_HUMIDITY = 0x01; +const uint8_t REG_CONFIGURATION = 0x02; +const uint8_t REG_SERIAL_ID_0 = 0xFB; +const uint8_t REG_SERIAL_ID_1 = 0xFC; +const uint8_t REG_SERIAL_ID_2 = 0xFD; +const uint8_t REG_MANUFACTURER_ID = 0xFE; +const uint8_t REG_DEVICE_ID = 0xFF; + +#define CONFIG_RST (1 << 15) ///< Software reset. This bit self clears +#define CONFIG_HEAT (1 << 13) ///< Enable heater +#define CONFIG_MODE_SEQUENTIAL (1 << 12) ///< Temperature and humidity measured in sequence, temperature first +#define CONFIG_BTST (1 << 11) ///< 1 = battery voltage < 2.8V +#define CONFIG_TRES_14BIT (0 << 10) ///< Temperature resolution +#define CONFIG_TRES_11BIT (1 << 10) ///< Temperature resolution +#define CONFIG_HRES_14BIT (0b00 << 8) ///< Humidity resolution +#define CONFIG_HRES_11BIT (0b01 << 8) ///< Humidity resolution +#define CONFIG_HRES_8BIT (0b10 << 8) ///< Humidity resolution + +struct hdc1080_data +{ + int16_t temperature; + uint16_t humidity; +}; + +struct hdc1080_config +{ + struct i2c_dt_spec bus; + uint8_t temperature_bits; + uint8_t humidity_bits; +}; + +static int hdc1080_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + const struct hdc1080_config *config = dev->config; + struct hdc1080_data *data = dev->data; + int ret; + + // Trigger measurement + uint8_t reg_addr = REG_TEMPERATURE; + i2c_write_dt(&config->bus, ®_addr, 1); + + // Wait for conversion + float temperature_conversion_time; ///< microseconds + switch (config->temperature_bits) + { + case 11: + temperature_conversion_time = 3650; + break; + case 14: + temperature_conversion_time = 6350; + break; + default: + temperature_conversion_time = 0; + break; + } + float humidity_conversion_time; ///< microseconds + switch (config->humidity_bits) + { + case 8: + humidity_conversion_time = 2500; + break; + case 11: + humidity_conversion_time = 3850; + break; + case 14: + humidity_conversion_time = 6500; + break; + default: + humidity_conversion_time = 0; + break; + } + k_busy_wait(temperature_conversion_time + humidity_conversion_time); + + // Read data + uint8_t rdata[4]; + ret = i2c_read_dt(&config->bus, rdata, sizeof(rdata)); + if (ret < 0) + { + LOG_ERR("Failed to read temperature and humidity!"); + return ret; + } + data->temperature = sys_get_be16(&rdata[0]); + data->humidity = sys_get_be16(&rdata[2]); + + return 0; +} + +static int hdc1080_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct hdc1080_data *data = dev->data; + + switch (chan) + { + case SENSOR_CHAN_AMBIENT_TEMP: + { + double temperature = data->temperature * 160.0 / (1 << 16) - 40; + val->val1 = temperature; + val->val2 = (temperature - val->val1) * 1e6; + break; + } + case SENSOR_CHAN_HUMIDITY: + { + double humidity = data->humidity * 100.0 / (1 << 16); + val->val1 = humidity; + val->val2 = (humidity - val->val1) * 1e6; + break; + } + default: + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api hdc1080_api = { + .sample_fetch = &hdc1080_sample_fetch, + .channel_get = &hdc1080_channel_get, +}; + +static int hdc1080_init(const struct device *dev) +{ + const struct hdc1080_config *const config = dev->config; + int ret; + + if (!device_is_ready(config->bus.bus)) + { + LOG_ERR("I2C bus %s is not ready", config->bus.bus->name); + return -ENODEV; + } + + uint8_t id[2]; + ret = i2c_burst_read_dt(&config->bus, REG_MANUFACTURER_ID, id, sizeof(id)); + if (ret < 0) + { + LOG_ERR("Failed to read manufacturer/device ID registers"); + return ret; + } + uint16_t manufacturer_id = sys_get_be16(&id[0]); + const uint16_t MANUFACTURER_ID = 0x5449; + if (manufacturer_id != MANUFACTURER_ID) + { + LOG_ERR("Manufacturer ID read from %s incorrect. Read 0x%02X, expected 0x%02X", dev->name, manufacturer_id, MANUFACTURER_ID); + } + + ret = i2c_burst_read_dt(&config->bus, REG_DEVICE_ID, id, sizeof(id)); + if (ret < 0) + { + LOG_ERR("Failed to read manufacturer/device ID registers"); + return ret; + } + uint16_t device_id = sys_get_be16(&id[2]); + const uint16_t DEVICE_ID = 0x1050; + if (device_id != DEVICE_ID) + { + LOG_ERR("Device ID read from %s incorrect. Read 0x%02X, expected 0x%02X", dev->name, device_id, DEVICE_ID); + } + + // Write configuration + uint16_t cfg = 0; + switch (config->temperature_bits) + { + case 14: + cfg |= CONFIG_TRES_14BIT; + break; + case 11: + cfg |= CONFIG_TRES_11BIT; + break; + default: + LOG_ERR("Invalid temperature resolution: %d bits", config->temperature_bits); + return -1; + } + switch (config->humidity_bits) + { + case 14: + cfg |= CONFIG_HRES_14BIT; + break; + case 11: + cfg |= CONFIG_HRES_11BIT; + break; + case 8: + cfg |= CONFIG_HRES_8BIT; + break; + default: + LOG_ERR("Invalid humidity resolution: %d bits", config->humidity_bits); + return -1; + } + uint8_t wdata[2]; + sys_put_be16(cfg, wdata); + i2c_burst_write_dt(&config->bus, REG_CONFIGURATION, wdata, sizeof(wdata)); + + return 0; +} + +#define HDC1080_INIT(i) \ + static struct hdc1080_data hdc1080_data_##i; \ + \ + static const struct hdc1080_config hdc1080_config_##i = { \ + .bus = I2C_DT_SPEC_INST_GET(i), \ + .temperature_bits = 14, \ + .humidity_bits = 14, \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(i, &hdc1080_init, NULL, \ + &hdc1080_data_##i, \ + &hdc1080_config_##i, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &hdc1080_api); + +DT_INST_FOREACH_STATUS_OKAY(HDC1080_INIT) diff --git a/dts/bindings/sensor/ti,hdc1080.yaml b/dts/bindings/sensor/ti,hdc1080.yaml new file mode 100644 index 0000000..c3ee95b --- /dev/null +++ b/dts/bindings/sensor/ti,hdc1080.yaml @@ -0,0 +1,7 @@ +description: | + TODO: add a description + +compatible: "ti,hdc1080" + +include: [sensor-device.yaml, i2c-device.yaml] +