sht21.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * Copyright (C) 2010 by Rittal GmbH & Co. KG,
  3. * Dawid Sadji <sadji.d@rittal.de> All rights reserved.
  4. * Ulrich Prinz <prinz.u@rittal.de> All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY EMBEDDED IT AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EMBEDDED IT
  23. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  26. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * For additional information see http://www.ethernut.de/
  32. *
  33. */
  34. /*
  35. * \file dev/sht21.c
  36. * \brief Driver for SHT2x temperatuer and humidity sensors from Sensirion.
  37. *
  38. * \verbatim
  39. * $Id$
  40. * \endverbatim
  41. */
  42. #include <compiler.h>
  43. #include <cfg/os.h>
  44. #include <sys/heap.h>
  45. #include <sys/timer.h>
  46. #include <sys/event.h>
  47. #include <dev/twif.h>
  48. #include <cfg/sht21.h>
  49. #include <dev/sht21.h>
  50. /* SHT21 packet size */
  51. #define SHT_READ_COUNT 3
  52. /* SHT21 CRC8 Polinomial */
  53. #define POLYNOMIAL 0x131
  54. /* SHT21 calculation factors */
  55. #define T1x100 -4685L
  56. #define T2x100 17572L
  57. #define H1x100 -600L
  58. #define H2x100 12500L
  59. #define SHT_POLL_TOUT 90
  60. #define SHT_POLL_CYCLE 5
  61. #ifndef SHT21_PRECISION
  62. #define SHT21_PRECISION SHT_RES_12_14
  63. #endif
  64. HANDLE sht_mutex;
  65. /*!
  66. * \brief Calculate 8-Bit checksum with given polynomial.
  67. *
  68. * This function calculates the checksum of a sensirion device
  69. * returned data and validates it against the last byte transmitted.
  70. * P(x) = x^8 + x^5 + x^4 + 1 = 100110001
  71. *
  72. * \para Data Pointer to data to be checked.
  73. * \para Size Size of data.
  74. *
  75. * \return -1 if CRC failed else 0
  76. */
  77. int ShtCrc(uint8_t *Data, uint8_t Size)
  78. {
  79. uint_fast8_t i = 0;
  80. uint_fast8_t bit = 0;
  81. uint_fast8_t checksum = 0;
  82. for (i = 0; i < Size; i++)
  83. {
  84. checksum ^= (Data[i]);
  85. for (bit = 8; bit > 0; --bit)
  86. {
  87. if (checksum & 0x80)
  88. checksum = (checksum << 1) ^ POLYNOMIAL;
  89. else
  90. checksum = (checksum << 1);
  91. }
  92. }
  93. if(checksum == Data[Size])
  94. return 0;
  95. else
  96. return -1;
  97. }
  98. /*!
  99. * \brief Read data from sensor device.
  100. *
  101. * This function reads the raw value of a SHT2x sensor device.
  102. * To get the real sensor value, the formulas given by the
  103. * datasheet have to be applied to this raw value.
  104. *
  105. * \param cmd can be SHT_GET_HUM or SHT_GET_TMP.
  106. * \param data Pointer to data value.
  107. *
  108. * \return -1 read failed else 0.
  109. */
  110. int ShtCommand(uint8_t cmd, uint16_t *data)
  111. {
  112. int rc = 0;
  113. uint8_t buf[4];
  114. #ifdef SHT_ACK_POLLING
  115. int tout = SHT_POLL_TOUT;
  116. #endif
  117. rc = NutEventWait(&sht_mutex, 500);
  118. if (rc) return rc;
  119. switch (cmd)
  120. {
  121. case SHT_SOFT_RESET:
  122. rc = TwMasterTransact( I2C_SLA_SHT21, &cmd, 1, NULL, 0, 10);
  123. NutSleep(15);
  124. break;
  125. case SHT_GET_TEMP:
  126. case SHT_GET_HUM:
  127. #ifdef SHT_ACK_POLLING
  128. /* Read SHT2x by ACK-polling. */
  129. rc = TwMasterTransact( I2C_SLA_SHT21, &cmd, 1, NULL, 0, 10);
  130. while (tout>0) {
  131. NutSleep(SHT_POLL_CYCLE);
  132. tout -= SHT_POLL_CYCLE;
  133. rc = TwMasterTransact(I2C_SLA_SHT21, NULL, 0, buf, SHT_READ_COUNT, 10);
  134. if (rc==SHT_READ_COUNT)
  135. break;
  136. }
  137. #else
  138. /* Read SHT2x by SHT in Master Hold mode. */
  139. rc = TwMasterTransact( I2C_SLA_SHT21, &cmd, 1, buf, SHT_READ_COUNT, SHT_POLL_TOUT);
  140. #endif
  141. if (rc == SHT_READ_COUNT) {
  142. rc = ShtCrc( buf, 2);
  143. *data = (buf[0]<<8)|buf[1];
  144. }
  145. else
  146. rc = -1;
  147. break;
  148. case SHT_GET_USER:
  149. rc = TwMasterRegRead(I2C_SLA_SHT21, cmd, 1, buf, 1, 100);
  150. if (rc==1) {
  151. *(uint8_t*)data = buf[0];
  152. }
  153. break;
  154. case SHT_SET_USER:
  155. buf[0] = cmd;
  156. buf[1] = (uint8_t)*data;
  157. rc = TwMasterTransact(I2C_SLA_SHT21, buf, 2, NULL, 0, 100);
  158. break;
  159. default:
  160. rc = -1;
  161. break;
  162. }
  163. /* Filter positive results from twi actions. */
  164. if (rc>0) rc = 0;
  165. /* Free the sensor access */
  166. NutEventPost(&sht_mutex);
  167. return rc;
  168. }
  169. /*!
  170. * \brief Return real sensor value.
  171. *
  172. * This function returns either the temperature or the humidity
  173. * value to a supplied int16_t pointer.
  174. * The value is decimal with 2 decimal digits:
  175. * val=2604 -> 26.04°C
  176. * val=2335 -> 23.35rH
  177. *
  178. * \param cmd Either SHT_GET_TEMP or SHT_GET_HUM.
  179. * \param val Pointer to store the value to.
  180. *
  181. * \return -1 if failed else 0.
  182. */
  183. int ShtRead( uint8_t cmd, int16_t *val)
  184. {
  185. int rc = -1;
  186. uint16_t th = 0;
  187. rc=ShtCommand( cmd, &th);
  188. if (rc==0) {
  189. th &= ~0x0003; /* filter status bits from value */
  190. if (cmd == SHT_GET_TEMP) {
  191. /* -46.85 + (175.72 * (St / 2^16)) */
  192. *val = (int16_t)(T1x100 + (T2x100 * (uint32_t)th / 65536L));
  193. rc = 0;
  194. }
  195. else if (cmd == SHT_GET_HUM) {
  196. /* -6 + (125 * (Srh / 2^16)) */
  197. *val = (int16_t)(H1x100 + (H2x100 * (uint32_t)th / 65536L));
  198. rc = 0;
  199. }
  200. }
  201. return rc;
  202. }
  203. /*!
  204. * \brief Register and initialize SHT2x sensor device.
  205. *
  206. * This function initializes the structures and I2C bus for
  207. * use with SHT2x sensor device. It checks communication too.
  208. *
  209. * \return -1 if init failed else 0.
  210. */
  211. int ShtInit(void)
  212. {
  213. int rc = 0;
  214. uint16_t dat;
  215. NutEventPost(&sht_mutex);
  216. rc = ShtCommand(SHT_SOFT_RESET, &dat);
  217. if (rc<0)
  218. return rc;
  219. /* Setup calculation precision */
  220. rc = ShtCommand( SHT_GET_USER, &dat);
  221. dat &= ~SHT_RES_MASK;
  222. dat |= SHT21_PRECISION;
  223. rc = ShtCommand( SHT_SET_USER, &dat);
  224. return rc;
  225. }