Contiki-NG
sht21.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, OpenMote Technologies, S.L.
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 Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 /*---------------------------------------------------------------------------*/
33 /**
34  * \addtogroup openmote-sht21-sensor
35  * @{
36  *
37  * \file
38  * Driver for the SHT21 temperature and relative humidity sensor
39  *
40  * \author
41  * Pere Tuset <peretuset@openmote.com>
42  */
43 /*---------------------------------------------------------------------------*/
44 #include "dev/i2c.h"
45 #include "dev/sht21.h"
46 #include "lib/sensors.h"
47 /*---------------------------------------------------------------------------*/
48 #define DEBUG 0
49 #if DEBUG
50 #define PRINTF(...) printf(__VA_ARGS__)
51 #else
52 #define PRINTF(...)
53 #endif
54 /*---------------------------------------------------------------------------*/
55 /**
56  * \name SHT21 address
57  */
58 #define SHT21_ADDRESS (0x40)
59 /** @} */
60 /*---------------------------------------------------------------------------*/
61 /**
62  * \name SHT21 register addresses and values
63  * @{
64  */
65 #define SHT21_USER_REG_READ (0xE7)
66 #define SHT21_USER_REG_WRITE (0xE6)
67 #define SHT21_USER_REG_RESERVED_BITS (0x38)
68 
69 #define SHT21_TEMPERATURE_HM_CMD (0xE3)
70 #define SHT21_HUMIDITY_HM_CMD (0xE5)
71 #define SHT21_TEMPERATURE_NHM_CMD (0xF3)
72 #define SHT21_HUMIDITY_NHM_CMD (0xF5)
73 #define SHT21_RESET_CMD (0xFE)
74 
75 #define SHT21_STATUS_MASK (0xFC)
76 
77 #define SHT21_RESOLUTION_12b_14b ((0 << 7) | (0 << 0))
78 #define SHT21_RESOLUTION_8b_12b ((0 << 7) | (1 << 0))
79 #define SHT21_RESOLUTION_10b_13b ((1 << 7) | (0 << 0))
80 #define SHT21_RESOLUTION_11b_11b ((1 << 7) | (1 << 0))
81 #define SHT21_BATTERY_ABOVE_2V25 (0 << 6)
82 #define SHT21_BATTERY_BELOW_2V25 (1 << 6)
83 #define SHT21_ONCHIP_HEATER_ENABLE (1 << 2)
84 #define SHT21_ONCHIP_HEATER_DISABLE (0 << 2)
85 #define SHT21_OTP_RELOAD_ENABLE (0 << 1)
86 #define SHT21_OTP_RELOAD_DISABLE (1 << 1)
87 /** @} */
88 /*---------------------------------------------------------------------------*/
89 /**
90  * \name SHT21 configuration values
91  * @{
92  */
93 #define SHT21_DEFAULT_CONFIG (SHT21_RESOLUTION_12b_14b | \
94  SHT21_ONCHIP_HEATER_DISABLE | \
95  SHT21_BATTERY_ABOVE_2V25 | \
96  SHT21_OTP_RELOAD_DISABLE)
97 
98 #define SHT21_USER_CONFIG (SHT21_RESOLUTION_12b_14b | \
99  SHT21_ONCHIP_HEATER_DISABLE | \
100  SHT21_BATTERY_ABOVE_2V25 | \
101  SHT21_OTP_RELOAD_DISABLE)
102 /** @} */
103 /*---------------------------------------------------------------------------*/
104 static uint8_t enabled;
105 /*---------------------------------------------------------------------------*/
106 static void
107 sht21_init(void)
108 {
109  uint8_t config[2];
110 
111  /* Setup the configuration vector, the first position holds address */
112  /* and the second position holds the actual configuration */
113  config[0] = SHT21_USER_REG_WRITE;
114  config[1] = 0;
115 
116  /* Read the current configuration according to the datasheet (pag. 9, fig. 18) */
117  i2c_single_send(SHT21_ADDRESS, SHT21_USER_REG_READ);
118  i2c_single_receive(SHT21_ADDRESS, &config[1]);
119 
120  /* Clean all the configuration bits except those reserved */
121  config[1] &= SHT21_USER_REG_RESERVED_BITS;
122 
123  /* Set the configuration bits without changing those reserved */
124  config[1] |= SHT21_USER_CONFIG;
125 
126  i2c_burst_send(SHT21_ADDRESS, config, sizeof(config));
127 }
128 /*---------------------------------------------------------------------------*/
129 static void
130 sht21_reset(void)
131 {
132  /* Send a soft-reset command according to the datasheet (pag. 9, fig. 17) */
133  i2c_single_send(SHT21_ADDRESS, SHT21_RESET_CMD);
134 }
135 /*---------------------------------------------------------------------------*/
136 static uint8_t
137 sht21_is_present(void)
138 {
139  uint8_t status;
140  uint8_t is_present;
141 
142  /* Read the current configuration according to the datasheet (pag. 9, fig. 18) */
143  i2c_single_send(SHT21_ADDRESS, SHT21_USER_REG_READ);
144  status = i2c_single_receive(SHT21_ADDRESS, &is_present);
145  if(status != I2C_MASTER_ERR_NONE) {
146  return 0;
147  }
148 
149  /* Clear the reserved bits according to the datasheet (pag. 9, tab. 8) */
150  is_present &= ~SHT21_USER_REG_RESERVED_BITS;
151 
152  return (is_present == SHT21_USER_CONFIG) || (is_present == SHT21_DEFAULT_CONFIG);
153 }
154 /*---------------------------------------------------------------------------*/
155 static uint32_t
156 sht21_read_temperature(void)
157 {
158  uint8_t sht21_temperature[2];
159  uint16_t temperature;
160 
161  /* Read the current temperature according to the datasheet (pag. 8, fig. 15) */
162  i2c_single_send(SHT21_ADDRESS, SHT21_TEMPERATURE_HM_CMD);
163  i2c_burst_receive(SHT21_ADDRESS, sht21_temperature, sizeof(sht21_temperature));
164 
165  temperature = (sht21_temperature[0] << 8) | ((sht21_temperature[1] & SHT21_STATUS_MASK));
166 
167  return temperature;
168 }
169 /*---------------------------------------------------------------------------*/
170 static int16_t
171 sht21_convert_temperature(uint32_t temperature)
172 {
173  int16_t result;
174 
175  temperature *= 17572;
176  temperature = temperature >> 16;
177  result = (int16_t)temperature - 4685;
178 
179  return result;
180 }
181 /*---------------------------------------------------------------------------*/
182 static uint32_t
183 sht21_read_humidity(void)
184 {
185  uint8_t sht21_humidity[2];
186  uint16_t humidity;
187 
188  /* Read the current humidity according to the datasheet (pag. 8, fig. 15) */
189  i2c_single_send(SHT21_ADDRESS, SHT21_HUMIDITY_HM_CMD);
190  i2c_burst_receive(SHT21_ADDRESS, sht21_humidity, sizeof(sht21_humidity));
191 
192  humidity = (sht21_humidity[0] << 8) | ((sht21_humidity[1] & SHT21_STATUS_MASK));
193 
194  return humidity;
195 }
196 /*---------------------------------------------------------------------------*/
197 static int16_t
198 sht21_convert_humidity(uint32_t humidity)
199 {
200  int16_t result;
201 
202  humidity *= 12500;
203  humidity = humidity >> 16;
204  result = (int16_t)humidity - 600;
205  result = (result > 10000) ? 10000 : result;
206 
207  return result;
208 }
209 /*---------------------------------------------------------------------------*/
210 static int
211 status(int type)
212 {
213  switch(type) {
214  case SENSORS_ACTIVE:
215  case SENSORS_READY:
216  return enabled;
217  }
218  return 0;
219 }
220 /*---------------------------------------------------------------------------*/
221 static int
222 value(int type)
223 {
224  uint32_t value;
225 
226  if(!enabled) {
227  PRINTF("SHT21: sensor not started\n");
228  return SHT21_ERROR;
229  }
230 
231  if(type == SHT21_READ_RAW_TEMP) {
232  return sht21_read_temperature();
233  } else if(type == SHT21_READ_RAW_RHUM) {
234  return sht21_read_humidity();
235  } else if(type == SHT21_READ_TEMP) {
236  value = sht21_read_temperature();
237  return sht21_convert_temperature(value);
238  } else if(type == SHT21_READ_RHUM) {
239  value = sht21_read_humidity();
240  return sht21_convert_humidity(value);
241  } else {
242  PRINTF("SHT21: invalid value requested\n");
243  return SHT21_ERROR;
244  }
245 }
246 /*---------------------------------------------------------------------------*/
247 static int
248 configure(int type, int value)
249 {
250  if(type == SHT21_ACTIVATE) {
251  if(!sht21_is_present()) {
252  PRINTF("SHT21: is not present\n");
253  return SHT21_ERROR;
254  } else {
255  sht21_init();
256  enabled = 1;
257  return SHT21_SUCCESS;
258  }
259  }
260 
261  if(type == SHT21_RESET && enabled) {
262  sht21_reset();
263  return SHT21_SUCCESS;
264  } else {
265  PRINTF("SHT21: is not enabled\n");
266  return SHT21_ERROR;
267  }
268 
269  return SHT21_ERROR;
270 }
271 /*---------------------------------------------------------------------------*/
272 SENSORS_SENSOR(sht21, SHT21_SENSOR, value, configure, status);
273 /*---------------------------------------------------------------------------*/
274 /** @} */
uint8_t i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to send multiple bytes to a slave.
Definition: i2c.c:188
uint8_t i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to receive multiple bytes from a slave.
Definition: i2c.c:218
static int config(int type, int c, nrf_drv_gpiote_pin_t pin)
Configuration function for the button sensor for all buttons.
Header file for the SHT21 temperature and humidity sensor driver.
uint8_t i2c_single_receive(uint8_t slave_addr, uint8_t *data)
Perform all operations to receive a byte from a slave.
Definition: i2c.c:172
uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data)
Perform all operations to send a byte to a slave.
Definition: i2c.c:159