Contiki-NG
Loading...
Searching...
No Matches
hdc-1000-sensor.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30/**
31 * \addtogroup sensortag-hdc-sensor
32 * @{
33 *
34 * \file
35 * Driver for the Sensortag HDC1000 sensor.
36 * \author
37 * Edvard Pettersen <e.pettersen@ti.com>
38 */
39/*---------------------------------------------------------------------------*/
40#include "contiki.h"
41#include "sys/ctimer.h"
42#include "lib/sensors.h"
43#include "dev/i2c-arch.h"
44/*---------------------------------------------------------------------------*/
45#include "board-conf.h"
46#include "hdc-1000-sensor.h"
47/*---------------------------------------------------------------------------*/
48#include <Board.h>
49
50#include <ti/drivers/I2C.h>
51/*---------------------------------------------------------------------------*/
52#include <stdint.h>
53#include <string.h>
54#include <stdbool.h>
55#include <stdio.h>
56/*---------------------------------------------------------------------------*/
57#define DEBUG 0
58#if DEBUG
59#define PRINTF(...) printf(__VA_ARGS__)
60#else
61#define PRINTF(...)
62#endif
63/*---------------------------------------------------------------------------*/
64/*
65 * Disable the entire file if sensors are disabled, as it could potentially
66 * create compile errors with missing defines from either the Board file or
67 * configuration defines.
68 */
69#if BOARD_SENSORS_ENABLE
70/*---------------------------------------------------------------------------*/
71#ifndef Board_HDC1000_ADDR
72#error "Board file doesn't define the I2C address Board_HDC1000_ADDR"
73#endif
74/* Sensor I2C address */
75#define HDC1000_I2C_ADDRESS Board_HDC1000_ADDR
76/*---------------------------------------------------------------------------*/
77/* Registers */
78#define HDC1000_REG_TEMP 0x00 /* Temperature */
79#define HDC1000_REG_HUM 0x01 /* Humidity */
80#define HDC1000_REG_CONFIG 0x02 /* Configuration */
81
82#if CONTIKI_BOARD_SENSORTAG_CC1352R1
83#define HDC2080_REG_CONFIG 0x0e /* Configuration for HDC 2080 */
84#define HDC2080_MEA_CONFIG 0x0f /* Measure Configuration for HDC 2080 */
85#endif
86
87#define HDC1000_REG_SERID_H 0xFB /* Serial ID high */
88#define HDC1000_REG_SERID_M 0xFC /* Serial ID middle */
89#define HDC1000_REG_SERID_L 0xFD /* Serial ID low */
90#define HDC1000_REG_MANF_ID 0xFE /* Manufacturer ID */
91#define HDC1000_REG_DEV_ID 0xFF /* Device ID */
92/*---------------------------------------------------------------------------*/
93/* Fixed values */
94#define HDC1000_VAL_MANF_ID 0x5449
95#define HDC1000_VAL_DEV_ID 0x1000
96#define HDC1000_VAL_CONFIG 0x1000 /* 14 bit, acquired in sequence */
97/*---------------------------------------------------------------------------*/
98/* Byte swap of 16-bit register value */
99#define HI_UINT16(a) (((a) >> 8) & 0xFF)
100#define LO_UINT16(a) ((a) & 0xFF)
101
102#define SWAP16(v) ((LO_UINT16(v) << 8) | HI_UINT16(v))
103
104#define LSB16(v) (HI_UINT16(v)), (LO_UINT16(v))
105/*---------------------------------------------------------------------------*/
106static I2C_Handle i2c_handle;
107/*---------------------------------------------------------------------------*/
108/* Raw data as returned from the sensor (Big Endian) */
109#if CONTIKI_BOARD_SENSORTAG_CC1352R1
110typedef struct {
115} HDC_1000_SensorData;
116#else
117typedef struct {
118 uint16_t temp;
119 uint16_t hum;
120} HDC_1000_SensorData;
121#endif
122
123static HDC_1000_SensorData sensor_data;
124/*---------------------------------------------------------------------------*/
125static volatile HDC_1000_SENSOR_STATUS sensor_status = HDC_1000_SENSOR_STATUS_DISABLED;
126/*---------------------------------------------------------------------------*/
127/*
128 * Maximum measurement durations in clock ticks. We use 14bit resolution, thus:
129 * - Tmp: 6.35ms
130 * - RH: 6.5ms
131 */
132#define MEASUREMENT_DURATION 2
133
134/*
135 * Wait SENSOR_STARTUP_DELAY clock ticks between activation and triggering a
136 * reading (max 15ms)
137 */
138#define SENSOR_STARTUP_DELAY 3
139
140static struct ctimer startup_timer;
141/*---------------------------------------------------------------------------*/
142/**
143 * \brief Initialize the HDC-1000 sensor driver.
144 * \return true if I2C operation successful; else, return false.
145 */
146static bool
148{
149 bool rv;
150
151 i2c_handle = i2c_arch_acquire(Board_I2C0);
152
153 if(!i2c_handle) {
154 return false;
155 }
156
157 /* Enable reading data in one operation */
158#if CONTIKI_BOARD_SENSORTAG_CC1352R1
159 /* From TI HDC 2080 Programming PDF */
161#else
162 uint8_t config_data[] = { HDC1000_REG_CONFIG, LSB16(HDC1000_VAL_CONFIG) };
163#endif
164
165 rv = i2c_arch_write(i2c_handle, HDC1000_I2C_ADDRESS, config_data,
166 sizeof(config_data));
167
168 i2c_arch_release(i2c_handle);
169
170 return rv;
171}
172/*---------------------------------------------------------------------------*/
173/**
174 * \brief Start measurement.
175 * \return true if I2C operation successful; else, return false.
176 */
177static bool
178start(void)
179{
180 bool rv;
181#if CONTIKI_BOARD_SENSORTAG_CC1352R1
182 uint8_t temp_reg[] = { HDC2080_MEA_CONFIG, 0x01 };
183#else
184 uint8_t temp_reg[] = { HDC1000_REG_TEMP };
185#endif
186
187 i2c_handle = i2c_arch_acquire(Board_I2C0);
188
189 if(!i2c_handle) {
190 return false;
191 }
192
193 rv = i2c_arch_write(i2c_handle, HDC1000_I2C_ADDRESS, temp_reg,
194 sizeof(temp_reg));
195
196 i2c_arch_release(i2c_handle);
197
198 return rv;
199}
200/*---------------------------------------------------------------------------*/
201/**
202 * \brief Convert raw data to temperature and humidity.
203 * \param temp Output variable to store converted temperature.
204 * \param hum Output variable to store converted humidity.
205 */
206static void
208{
209#if CONTIKI_BOARD_SENSORTAG_CC1352R1
210 int32_t raw_temp = sensor_data.temp_high * 256 + sensor_data.temp_low;
211 int32_t raw_hum = sensor_data.hum_high * 256 + sensor_data.hum_low;
212#else
213 int32_t raw_temp = SWAP16(sensor_data.temp);
214 int32_t raw_hum = SWAP16(sensor_data.hum);
215#endif
216
217 /* Convert temperature to degrees C */
218 *temp = (raw_temp * 100 * 165) / 65536 - 4000;
219 /* Convert relative humidity to a %RH value */
220 *hum = (raw_hum * 100 * 100) / 65536;
221}
222/*---------------------------------------------------------------------------*/
223/**
224 * \brief Callback when sensor is ready to read data from.
225 */
226static void
227notify_ready(void *unused)
228{
229 /* Unused args */
230 (void)unused;
231
232 i2c_handle = i2c_arch_acquire(Board_I2C0);
233
234 if(!i2c_handle) {
235 return;
236 }
237
238 /* Latch readings */
239#if CONTIKI_BOARD_SENSORTAG_CC1352R1
240 uint8_t temp_reg[] = { HDC1000_REG_TEMP };
241 if(i2c_arch_write_read(i2c_handle, HDC1000_I2C_ADDRESS, temp_reg,
242 sizeof(temp_reg), &sensor_data, sizeof(sensor_data))) {
243#else
244 if(i2c_arch_read(i2c_handle, HDC1000_I2C_ADDRESS, &sensor_data,
245 sizeof(sensor_data))) {
246#endif
248 } else {
249 sensor_status = HDC_1000_SENSOR_STATUS_I2C_ERROR;
250 }
251
252 i2c_arch_release(i2c_handle);
253
254 sensors_changed(&hdc_1000_sensor);
255}
256/*---------------------------------------------------------------------------*/
257/**
258 * \brief Returns a reading from the sensor.
259 * \param type HDC_1000_SENSOR_TYPE_TEMP or HDC_1000_SENSOR_TYPE_HUMID.
260 * \return Temperature (centi degrees C) or Humidity (centi %RH).
261 */
262static int
263value(int type)
264{
265 int32_t temp = 0;
266 int32_t hum = 0;
267
268 if(sensor_status != HDC_1000_SENSOR_STATUS_READINGS_READY) {
269 PRINTF("Sensor disabled or starting up (%d)\n", sensor_status);
270 return HDC_1000_READING_ERROR;
271 }
272
273 switch(type) {
274 case HDC_1000_SENSOR_TYPE_TEMP:
275 case HDC_1000_SENSOR_TYPE_HUMID:
276 convert(&temp, &hum);
277 PRINTF("HDC: t=%d h=%d\n", (int)temp, (int)hum);
278
279 if(type == HDC_1000_SENSOR_TYPE_TEMP) {
280 return (int)temp;
281 } else if(type == HDC_1000_SENSOR_TYPE_HUMID) {
282 return (int)hum;
283 } else {
284 return HDC_1000_READING_ERROR;
285 }
286
287 default:
288 PRINTF("Invalid type\n");
289 return HDC_1000_READING_ERROR;
290 }
291}
292/*---------------------------------------------------------------------------*/
293/**
294 * \brief Configuration function for the HDC1000 sensor.
295 * \param type Activate, enable or disable the sensor. See below.
296 * \param enable Either enable or disable the sensor.
297 * When type == SENSORS_HW_INIT we turn on the hardware.
298 * When type == SENSORS_ACTIVE and enable==1 we enable the sensor.
299 * When type == SENSORS_ACTIVE and enable==0 we disable the sensor.
300 */
301static int
302configure(int type, int enable)
303{
304 switch(type) {
305 case SENSORS_HW_INIT:
306 memset(&sensor_data, 0, sizeof(sensor_data));
307
308 if(sensor_init()) {
310 } else {
311 sensor_status = HDC_1000_SENSOR_STATUS_I2C_ERROR;
312 }
313 break;
314
315 case SENSORS_ACTIVE:
316 /* Must be initialised first */
317 if(sensor_status == HDC_1000_SENSOR_STATUS_DISABLED) {
318 break;
319 }
320
321 if(enable) {
322 if(!start()) {
323 sensor_status = HDC_1000_SENSOR_STATUS_I2C_ERROR;
324 break;
325 }
326 ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL);
328 } else {
329 ctimer_stop(&startup_timer);
331 }
332 break;
333
334 default:
335 break;
336 }
337 return sensor_status;
338}
339/*---------------------------------------------------------------------------*/
340/**
341 * \brief Returns the status of the sensor.
342 * \param type SENSORS_ACTIVE or SENSORS_READY.
343 * \return One of the SENSOR_STATUS_xyz defines.
344 */
345static int
346status(int type)
347{
348 switch(type) {
349 case SENSORS_ACTIVE:
350 case SENSORS_READY:
351 return sensor_status;
352
353 default:
355 }
356}
357/*---------------------------------------------------------------------------*/
358SENSORS_SENSOR(hdc_1000_sensor, "HDC1000", value, configure, status);
359/*---------------------------------------------------------------------------*/
360#endif /* BOARD_SENSORS_ENABLE */
361/*---------------------------------------------------------------------------*/
362/** @} */
Header file for the callback timer.
static bool i2c_arch_read(I2C_Handle i2c_handle, uint_least8_t slave_addr, void *rbuf, size_t rcount)
Perform a read-only I2C transaction.
Definition i2c-arch.h:144
bool i2c_arch_write_read(I2C_Handle i2c_handle, uint_least8_t slave_addr, void *wbuf, size_t wcount, void *rbuf, size_t rcount)
Setup and peform an I2C transaction.
Definition i2c-arch.c:53
static bool i2c_arch_write(I2C_Handle i2c_handle, uint_least8_t slave_addr, void *wbuf, size_t wcount)
Perform a write-only I2C transaction.
Definition i2c-arch.h:128
I2C_Handle i2c_arch_acquire(uint_least8_t index)
Open and lock the I2C Peripheral for use.
Definition i2c-arch.c:84
void i2c_arch_release(I2C_Handle i2c_handle)
Release the I2C Peripheral for other modules to use.
Definition i2c-arch.c:74
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition ctimer.c:138
static void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition ctimer.h:137
static int value(int type)
Returns a reading from the sensor.
static void notify_ready(void *not_used)
#define HDC_1000_SENSOR_STATUS_DISABLED
Not initialised.
static int status(int type)
Returns the status of the sensor.
static void start(void)
Start measurement.
static void convert(float *temp, float *hum)
Convert raw data to temperature and humidity.
#define HDC_1000_SENSOR_STATUS_READINGS_READY
Both readings ready.
#define HDC_1000_SENSOR_STATUS_TAKING_READINGS
Readings in progress.
static bool sensor_init(void)
Initialise the humidity sensor driver.
#define HDC_1000_SENSOR_STATUS_INITIALISED
Initialised but idle.
static int value(int type)
Returns a reading from the sensor.
static int configure(int type, int enable)
Configuration function for the HDC1000 sensor.
HDC_1000_SENSOR_STATUS
@ HDC_1000_SENSOR_STATUS_I2C_ERROR
I2C transaction failed.
Implementation of the I2C HAL driver for CC13xx/CC26xx.
Header file with definitions related to the sensors on the Sensortags.