Contiki 3.x
tmp-007-sensor.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, 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 /**
32  * \addtogroup sensortag-cc26xx-tmp-sensor
33  * @{
34  *
35  * \file
36  * Driver for the Sensortag-CC26xx TI TMP007 infrared thermophile sensor
37  */
38 /*---------------------------------------------------------------------------*/
39 #include "contiki-conf.h"
40 #include "lib/sensors.h"
41 #include "tmp-007-sensor.h"
42 #include "sys/ctimer.h"
43 #include "board-i2c.h"
44 #include "sensor-common.h"
45 #include "ti-lib.h"
46 
47 #include <stdint.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <math.h>
51 /*---------------------------------------------------------------------------*/
52 #define DEBUG 0
53 #if DEBUG
54 #define PRINTF(...) printf(__VA_ARGS__)
55 #else
56 #define PRINTF(...)
57 #endif
58 /*---------------------------------------------------------------------------*/
59 /* Slave address */
60 #define SENSOR_I2C_ADDRESS 0x44
61 /*---------------------------------------------------------------------------*/
62 /* TMP007 register addresses */
63 #define TMP007_REG_ADDR_VOLTAGE 0x00
64 #define TMP007_REG_ADDR_LOCAL_TEMP 0x01
65 #define TMP007_REG_ADDR_CONFIG 0x02
66 #define TMP007_REG_ADDR_OBJ_TEMP 0x03
67 #define TMP007_REG_ADDR_STATUS 0x04
68 #define TMP007_REG_PROD_ID 0x1F
69 /*---------------------------------------------------------------------------*/
70 /* TMP007 register values */
71 #define TMP007_VAL_CONFIG_ON 0x1000 /* Sensor on state */
72 #define TMP007_VAL_CONFIG_OFF 0x0000 /* Sensor off state */
73 #define TMP007_VAL_CONFIG_RESET 0x8000
74 #define TMP007_VAL_PROD_ID 0x0078 /* Product ID */
75 /*---------------------------------------------------------------------------*/
76 /* Conversion ready (status register) bit values */
77 #define CONV_RDY_BIT 0x4000
78 /*---------------------------------------------------------------------------*/
79 /* Register length */
80 #define REGISTER_LENGTH 2
81 /*---------------------------------------------------------------------------*/
82 /* Sensor data size */
83 #define DATA_SIZE 4
84 /*---------------------------------------------------------------------------*/
85 /* Byte swap of 16-bit register value */
86 #define HI_UINT16(a) (((a) >> 8) & 0xFF)
87 #define LO_UINT16(a) ((a) & 0xFF)
88 
89 #define SWAP(v) ((LO_UINT16(v) << 8) | HI_UINT16(v))
90 /*---------------------------------------------------------------------------*/
91 #define SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS)
92 /*---------------------------------------------------------------------------*/
93 static uint8_t buf[DATA_SIZE];
94 static uint16_t val;
95 /*---------------------------------------------------------------------------*/
96 #define SENSOR_STATUS_DISABLED 0
97 #define SENSOR_STATUS_INITIALISED 1
98 #define SENSOR_STATUS_NOT_READY 2
99 #define SENSOR_STATUS_READY 3
100 
101 static int enabled = SENSOR_STATUS_DISABLED;
102 /*---------------------------------------------------------------------------*/
103 /* Wait SENSOR_STARTUP_DELAY clock ticks for the sensor to be ready - 275ms */
104 #define SENSOR_STARTUP_DELAY 36
105 
106 static struct ctimer startup_timer;
107 /*---------------------------------------------------------------------------*/
108 /* Latched values */
109 static int obj_temp_latched;
110 static int amb_temp_latched;
111 /*---------------------------------------------------------------------------*/
112 static void
113 notify_ready(void *not_used)
114 {
115  enabled = SENSOR_STATUS_READY;
116  sensors_changed(&tmp_007_sensor);
117 }
118 /*---------------------------------------------------------------------------*/
119 /**
120  * \brief Turn the sensor on/off
121  */
122 static bool
123 enable_sensor(bool enable)
124 {
125  bool success;
126 
127  SELECT();
128 
129  if(enable) {
130  val = TMP007_VAL_CONFIG_ON;
131  } else {
132  val = TMP007_VAL_CONFIG_OFF;
133  }
134  val = SWAP(val);
135 
136  success = sensor_common_write_reg(TMP007_REG_ADDR_CONFIG, (uint8_t *)&val,
137  REGISTER_LENGTH);
138 
139  return success;
140 }
141 /*---------------------------------------------------------------------------*/
142 /**
143  * \brief Read the sensor value registers
144  * \param raw_temp Temperature in 16 bit format
145  * \param raw_obj_temp object temperature in 16 bit format
146  * \return TRUE if valid data could be retrieved
147  */
148 static bool
149 read_data(uint16_t *raw_temp, uint16_t *raw_obj_temp)
150 {
151  bool success;
152 
153  SELECT();
154 
155  success = sensor_common_read_reg(TMP007_REG_ADDR_STATUS, (uint8_t *)&val,
156  REGISTER_LENGTH);
157 
158  if(success) {
159  val = SWAP(val);
160  success = val & CONV_RDY_BIT;
161  }
162 
163  if(success) {
164  success = sensor_common_read_reg(TMP007_REG_ADDR_LOCAL_TEMP, &buf[0],
165  REGISTER_LENGTH);
166  if(success) {
167  success = sensor_common_read_reg(TMP007_REG_ADDR_OBJ_TEMP, &buf[2],
168  REGISTER_LENGTH);
169  }
170  }
171 
172  if(!success) {
174  }
175 
176  /* Swap byte order */
177  *raw_temp = buf[0] << 8 | buf[1];
178  *raw_obj_temp = buf[2] << 8 | buf[3];
179 
180  return success;
181 }
182 /*---------------------------------------------------------------------------*/
183 /**
184  * \brief Convert raw data to values in degrees C
185  * \param raw_temp raw ambient temperature from sensor
186  * \param raw_obj_temp raw object temperature from sensor
187  * \param obj converted object temperature
188  * \param amb converted ambient temperature
189  */
190 static void
191 convert(uint16_t raw_temp, uint16_t raw_obj_temp, float *obj, float *amb)
192 {
193  const float SCALE_LSB = 0.03125;
194  float t;
195  int it;
196 
197  it = (int)((raw_obj_temp) >> 2);
198  t = ((float)(it)) * SCALE_LSB;
199  *obj = t;
200 
201  it = (int)((raw_temp) >> 2);
202  t = (float)it;
203  *amb = t * SCALE_LSB;
204 }
205 /*---------------------------------------------------------------------------*/
206 /**
207  * \brief Returns a reading from the sensor
208  * \param type TMP_007_SENSOR_TYPE_OBJECT or TMP_007_SENSOR_TYPE_AMBIENT
209  * \return Object or Ambient temperature in milli degrees C
210  */
211 static int
212 value(int type)
213 {
214  int rv;
215  uint16_t raw_temp;
216  uint16_t raw_obj_temp;
217  float obj_temp;
218  float amb_temp;
219 
220  if(enabled != SENSOR_STATUS_READY) {
221  PRINTF("Sensor disabled or starting up (%d)\n", enabled);
222  return CC26XX_SENSOR_READING_ERROR;
223  }
224 
225  if((type & TMP_007_SENSOR_TYPE_ALL) == 0) {
226  PRINTF("Invalid type\n");
227  return CC26XX_SENSOR_READING_ERROR;
228  }
229 
230  rv = CC26XX_SENSOR_READING_ERROR;
231 
232  if(type == TMP_007_SENSOR_TYPE_ALL) {
233  rv = read_data(&raw_temp, &raw_obj_temp);
234 
235  if(rv == 0) {
236  return CC26XX_SENSOR_READING_ERROR;
237  }
238 
239  convert(raw_temp, raw_obj_temp, &obj_temp, &amb_temp);
240  PRINTF("TMP: %04X %04X o=%d a=%d\n", raw_temp, raw_obj_temp,
241  (int)(obj_temp * 1000), (int)(amb_temp * 1000));
242 
243  obj_temp_latched = (int)(obj_temp * 1000);
244  amb_temp_latched = (int)(amb_temp * 1000);
245  rv = 1;
246  } else if(type == TMP_007_SENSOR_TYPE_OBJECT) {
247  rv = obj_temp_latched;
248  } else if(type == TMP_007_SENSOR_TYPE_AMBIENT) {
249  rv = amb_temp_latched;
250  }
251 
252  return rv;
253 }
254 /*---------------------------------------------------------------------------*/
255 /**
256  * \brief Configuration function for the TMP007 sensor.
257  *
258  * \param type Activate, enable or disable the sensor. See below
259  * \param enable
260  *
261  * When type == SENSORS_HW_INIT we turn on the hardware
262  * When type == SENSORS_ACTIVE and enable==1 we enable the sensor
263  * When type == SENSORS_ACTIVE and enable==0 we disable the sensor
264  */
265 static int
266 configure(int type, int enable)
267 {
268  switch(type) {
269  case SENSORS_HW_INIT:
270  ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_TMP_RDY);
271  ti_lib_ioc_io_port_pull_set(BOARD_IOID_TMP_RDY, IOC_IOPULL_UP);
272  ti_lib_ioc_io_hyst_set(BOARD_IOID_TMP_RDY, IOC_HYST_ENABLE);
273 
274  enable_sensor(false);
275  enabled = SENSOR_STATUS_INITIALISED;
276  break;
277  case SENSORS_ACTIVE:
278  /* Must be initialised first */
279  if(enabled == SENSOR_STATUS_DISABLED) {
280  return SENSOR_STATUS_DISABLED;
281  }
282  if(enable) {
283  enable_sensor(true);
284  ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL);
285  enabled = SENSOR_STATUS_NOT_READY;
286  } else {
287  ctimer_stop(&startup_timer);
288  enable_sensor(false);
289  enabled = SENSOR_STATUS_INITIALISED;
290  }
291  break;
292  default:
293  break;
294  }
295  return enabled;
296 }
297 /*---------------------------------------------------------------------------*/
298 /**
299  * \brief Returns the status of the sensor
300  * \param type SENSORS_ACTIVE or SENSORS_READY
301  * \return 1 if the sensor is enabled
302  */
303 static int
304 status(int type)
305 {
306  switch(type) {
307  case SENSORS_ACTIVE:
308  case SENSORS_READY:
309  return enabled;
310  break;
311  default:
312  break;
313  }
314  return SENSOR_STATUS_DISABLED;
315 }
316 /*---------------------------------------------------------------------------*/
317 SENSORS_SENSOR(tmp_007_sensor, "TMP007", value, configure, status);
318 /*---------------------------------------------------------------------------*/
319 /** @} */
Header file with macros which rename TI CC26xxware functions.
static void convert(uint16_t raw_temp, uint16_t raw_obj_temp, float *obj, float *amb)
Convert raw data to values in degrees C.
void sensor_common_set_error_data(uint8_t *buf, uint8_t len)
Fill a result buffer with dummy error data.
Definition: sensor-common.c:71
static int status(int type)
Returns the status of the sensor.
#define BOARD_IOID_TMP_RDY
TMP Sensor.
Definition: board.h:219
Header file for the Sensortag-CC26xx TI TMP007 infrared thermophile sensor.
Header file for the callback timer
#define NULL
The null pointer.
static int configure(int type, int enable)
Configuration function for the TMP007 sensor.
static int value(int type)
Returns a reading from the sensor.
static bool read_data(uint16_t *raw_temp, uint16_t *raw_obj_temp)
Read the sensor value registers.
Header file for the Sensortag-CC26xx Common sensor utilities.
Header file for the Sensortag-CC26xx I2C Driver.
bool sensor_common_read_reg(uint8_t addr, uint8_t *buf, uint8_t len)
Reads a sensor's register over I2C.
Definition: sensor-common.c:48
static bool enable_sensor(bool enable)
Turn the sensor on/off.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
bool sensor_common_write_reg(uint8_t addr, uint8_t *buf, uint8_t len)
Write to a sensor's register over I2C.
Definition: sensor-common.c:54
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149