sht3x.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. #include <string.h>
  2. #define DBG_ENABLE
  3. #define DBG_SECTION_NAME "sht3x"
  4. #define DBG_LEVEL DBG_LOG
  5. #define DBG_COLOR
  6. #include <rtdbg.h>
  7. #include "sht3x.h"
  8. #ifdef PKG_USING_SHT3X
  9. #define CRC_POLY 0x31
  10. /**
  11. * This function write 2-byte cmd to SHT3x
  12. *
  13. * @param dev the pointer of device driver structure
  14. * @param cmd the 16bit command to be sent to SHT3x
  15. *
  16. * @return the cmd transfer status, RT_EOK reprensents setting successfully.
  17. */
  18. static rt_err_t write_cmd(sht3x_device_t dev, rt_uint16_t cmd)
  19. {
  20. struct rt_i2c_msg msgs;
  21. rt_uint8_t buf[2] ;
  22. buf[0] = cmd >> 8 ;
  23. buf[1] = cmd & 0xFF ;
  24. msgs.addr = dev->sht3x_addr;
  25. msgs.flags = RT_I2C_WR;
  26. msgs.buf = buf;
  27. msgs.len = 2;
  28. if (rt_i2c_transfer(dev->i2c, &msgs, 1) == 1)
  29. return RT_EOK;
  30. else
  31. return -RT_ERROR;
  32. }
  33. /**
  34. * This function read len bytes from dev and store the bytes in to buf
  35. *
  36. * @param dev the pointer of device driver structure
  37. * @param buf the pointer to buffer array
  38. * @param len the number of bytes to be read
  39. *
  40. * @return the i2c read status, RT_EOK represents success.
  41. */
  42. static rt_err_t read_bytes(sht3x_device_t dev, rt_uint8_t * buf, rt_uint8_t len)
  43. {
  44. if(rt_i2c_master_recv(dev->i2c, dev->sht3x_addr, RT_I2C_RD, buf, len) == len){
  45. return RT_EOK ;
  46. }else
  47. {
  48. return - RT_ERROR ;
  49. }
  50. }
  51. /**
  52. * This function calculate CRC value of bytes in buffer
  53. * CRC_POLY is predefined as 0x31
  54. *
  55. * @param buf the pointer to buffer array
  56. * @param len the length of buffer array
  57. *
  58. * @return calculated CRC value.
  59. */
  60. static rt_uint8_t crc8(rt_uint8_t * buf, rt_uint8_t len)
  61. {
  62. rt_uint8_t crc = 0xFF ;
  63. rt_uint8_t i, j ;
  64. for(j = len; j; j --){
  65. crc ^= *buf ++ ;
  66. for( i = 8; i; i --){
  67. crc = (crc & 0x80) ? (crc << 1) ^ CRC_POLY : (crc << 1) ;
  68. }
  69. }
  70. return crc ;
  71. }
  72. /**
  73. * This function read temperature and humidity by single shot mode
  74. * Attention:
  75. * - rt_thread_mdelay() is called to wait for SHT3x to be ready to read
  76. * - the temperature and humidity is stored in the device driver structure
  77. *
  78. * @param dev the pointer of device driver structure
  79. *
  80. * @return the status of read data from SHT3x, RT_EOK means success.
  81. */
  82. rt_err_t sht3x_read_singleshot(sht3x_device_t dev)
  83. {
  84. rt_uint8_t temp[6] ;
  85. rt_err_t result;
  86. RT_ASSERT(dev);
  87. result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
  88. if (result == RT_EOK)
  89. {
  90. if( write_cmd(dev, dev->cmd_readout) == RT_EOK)
  91. {
  92. // wait about 5 ms
  93. rt_thread_mdelay(5);
  94. if(read_bytes(dev, temp, 6) == RT_EOK){
  95. if(crc8(temp, 2) == temp[2]){
  96. dev->temperature = -45.0 + (temp[1] | temp[0] << 8) * 175.0 / (0xFFFF - 1) ; //sensor temperature convert to reality
  97. result = RT_EOK ;
  98. }else{
  99. result = -RT_ERROR ;
  100. }
  101. if(crc8(temp + 3, 2) == temp[5]){
  102. dev->humidity = (temp[4] | temp[3] << 8) * 0.0015259022 ; //sensor humidity convert to reality
  103. }else{
  104. result = -RT_ERROR ;
  105. }
  106. }else
  107. {
  108. result = -RT_ERROR ;
  109. }
  110. }
  111. else
  112. {
  113. result = -RT_ERROR ;
  114. }
  115. rt_mutex_release(dev->lock);
  116. }
  117. else
  118. {
  119. LOG_E("Taking mutex of SHT3x failed.");
  120. result = -RT_ERROR;
  121. }
  122. return result;
  123. }
  124. /**
  125. * This function resets all parameter with default
  126. *
  127. * @param dev the pointer of device driver structure
  128. *
  129. * @return the softreset status, RT_EOK reprensents setting successfully.
  130. */
  131. rt_err_t sht3x_softreset(sht3x_device_t dev)
  132. {
  133. RT_ASSERT(dev);
  134. if( write_cmd(dev, CMD_SOFT_RESET) == RT_EOK)
  135. {
  136. return RT_EOK;
  137. }else{
  138. return RT_ERROR ;
  139. }
  140. }
  141. /**
  142. * This function clear the status register in SHT3x
  143. *
  144. * @param dev the pointer of device driver structure
  145. *
  146. * @return the command transfer status, RT_EOK means success.
  147. */
  148. rt_err_t sht3x_clear_status(sht3x_device_t dev)
  149. {
  150. RT_ASSERT(dev);
  151. if( write_cmd(dev, CMD_CLEAR_STATUS) == RT_EOK)
  152. {
  153. return RT_EOK ;
  154. }else{
  155. return RT_ERROR ;
  156. }
  157. }
  158. /**
  159. * This function read the status register from SHT3x
  160. * Attention:
  161. * - the status word is stored in device driver structure
  162. *
  163. * @param dev the pointer of device driver structure
  164. *
  165. * @return the command transfer status, RT_EOK means success.
  166. */
  167. rt_err_t sht3x_read_status(sht3x_device_t dev)
  168. {
  169. rt_uint8_t buf[3];
  170. RT_ASSERT(dev);
  171. if( write_cmd(dev, CMD_READ_STATUS) == RT_EOK)
  172. {
  173. read_bytes(dev, buf, 3);
  174. if( crc8(buf, 2) == buf[2])
  175. {
  176. dev->status.status_word = ( buf[0] << 8 ) | buf[1];
  177. return RT_EOK ;
  178. }
  179. }
  180. return -RT_ERROR ;
  181. }
  182. /**
  183. * This function enable heater
  184. * @param dev the pointer of device driver structure
  185. *
  186. * @return the command transfer status, RT_EOK means success.
  187. */
  188. rt_err_t sht3x_enable_heater(sht3x_device_t dev)
  189. {
  190. RT_ASSERT(dev);
  191. if( write_cmd(dev, CMD_HEATER_ENABLE) == RT_EOK)
  192. {
  193. return RT_EOK ;
  194. }else
  195. {
  196. return -RT_ERROR ;
  197. }
  198. }
  199. /**
  200. * This function disable heater
  201. * @param dev the pointer of device driver structure
  202. *
  203. * @return the command transfer status, RT_EOK means success.
  204. */
  205. rt_err_t sht3x_disable_heater(sht3x_device_t dev)
  206. {
  207. RT_ASSERT(dev);
  208. if( write_cmd(dev, CMD_HEATER_DISABLE) == RT_EOK)
  209. {
  210. return RT_EOK ;
  211. }else
  212. {
  213. return -RT_ERROR ;
  214. }
  215. }
  216. /**
  217. * This function write accelerated response time command to SHT3x
  218. * @param dev the pointer of device driver structure
  219. *
  220. * @return the command transfer status, RT_EOK means success.
  221. */
  222. rt_err_t sht3x_acc_resp_time(sht3x_device_t dev)
  223. {
  224. RT_ASSERT(dev);
  225. if( write_cmd(dev, CMD_ART) == RT_EOK)
  226. {
  227. return RT_EOK ;
  228. }else
  229. {
  230. return -RT_ERROR ;
  231. }
  232. }
  233. /**
  234. * This function write break command to SHT3x to break out of continuous readout mode
  235. * @param dev the pointer of device driver structure
  236. *
  237. * @return the command transfer status, RT_EOK means success.
  238. */
  239. rt_err_t sht3x_break(sht3x_device_t dev)
  240. {
  241. RT_ASSERT(dev);
  242. if( write_cmd(dev, CMD_BREAK) == RT_EOK)
  243. {
  244. return RT_EOK ;
  245. }else
  246. {
  247. return -RT_ERROR ;
  248. }
  249. }
  250. /**
  251. * This function initializes sht3x registered device driver
  252. *
  253. * @param i2c_bus_name the name of i2c device used by SHT3x device
  254. * @param sht3x_addr the address of SHT3x device
  255. *
  256. * @return the pointer to sht3x device driver structure.
  257. */
  258. sht3x_device_t sht3x_init(const char *i2c_bus_name, rt_uint8_t sht3x_addr)
  259. {
  260. sht3x_device_t dev;
  261. RT_ASSERT(i2c_bus_name);
  262. dev = rt_calloc(1, sizeof(struct sht3x_device));
  263. if (dev == RT_NULL)
  264. {
  265. LOG_E("Can't allocate memory for sht3x device on '%s' ", i2c_bus_name);
  266. return RT_NULL;
  267. }
  268. if(sht3x_addr == SHT3X_ADDR_PD || sht3x_addr == SHT3X_ADDR_PU){
  269. dev->sht3x_addr = sht3x_addr ;
  270. }else{
  271. LOG_E("Illegal sht3x address:'%x'", sht3x_addr);
  272. rt_free(dev);
  273. return RT_NULL;
  274. }
  275. dev->i2c = rt_i2c_bus_device_find(i2c_bus_name);
  276. if (dev->i2c == RT_NULL)
  277. {
  278. LOG_E("Can't find sht3x device on '%s' ", i2c_bus_name);
  279. rt_free(dev);
  280. return RT_NULL;
  281. }
  282. dev->lock = rt_mutex_create("mutex_sht3x", RT_IPC_FLAG_FIFO);
  283. if (dev->lock == RT_NULL)
  284. {
  285. LOG_E("Can't create mutex for sht3x device on '%s' ", i2c_bus_name);
  286. rt_free(dev);
  287. return RT_NULL;
  288. }
  289. // I2C streching disabled, medium repeatability for default single shot readout
  290. dev->cmd_readout = CMD_MEAS_POLLING_M ;
  291. // clear the status register
  292. sht3x_clear_status(dev);
  293. return dev;
  294. }
  295. /**
  296. * This function releases memory and deletes mutex lock
  297. *
  298. * @param dev the pointer of device driver structure
  299. */
  300. void sht3x_deinit(sht3x_device_t dev)
  301. {
  302. RT_ASSERT(dev);
  303. rt_mutex_delete(dev->lock);
  304. rt_free(dev);
  305. }
  306. /**
  307. * This function is exported to MSH commands list
  308. * Usage example:
  309. * - sht3x probe i2c1 pu : initialize sht3x device on i2c1 bus with address pin pulled up(i2c address 0x45)
  310. * - sht3x probe i2c1: initialize sht3x device one i2c1 bus with address pin pulled down by default(i2c address 0x44)
  311. * - sht3x read: read and print temperature and humidity from previously initialized sht3x
  312. */
  313. void sht3x(int argc, char *argv[])
  314. {
  315. static sht3x_device_t dev = RT_NULL;
  316. rt_uint8_t sht_addr = SHT3X_ADDR_PD ;
  317. if (argc > 1)
  318. {
  319. if (!strcmp(argv[1], "probe"))
  320. {
  321. if (argc >= 3)
  322. {
  323. /* initialize the sensor when first probe */
  324. if (!dev || strcmp(dev->i2c->parent.parent.name, argv[2]))
  325. {
  326. /* deinit the old device */
  327. if(dev)
  328. {
  329. rt_kprintf("Deinit sht3x");
  330. sht3x_deinit(dev);
  331. }
  332. // no else needed here
  333. if( argc > 3)
  334. {
  335. if( !strcmp("pd", argv[3]))
  336. {
  337. sht_addr = SHT3X_ADDR_PD ;
  338. }
  339. else if( !strcmp("pu", argv[3]))
  340. {
  341. sht_addr = SHT3X_ADDR_PU ;
  342. }
  343. else
  344. {
  345. rt_kprintf("Illegal sht3x address, using 0x44 by default\n");
  346. sht_addr = SHT3X_ADDR_PD ; // pulled down by default: 0x44
  347. }
  348. }
  349. // no else needed here
  350. dev = sht3x_init(argv[2], sht_addr);
  351. if(!dev)
  352. {
  353. rt_kprintf("sht3x probe failed, check input args\n");
  354. }else
  355. {
  356. rt_kprintf("sht3x probed, addr:0x%x\n", sht_addr) ;
  357. }
  358. }
  359. }
  360. else
  361. {
  362. rt_kprintf("sht3x probe <i2c dev name> - probe sensor by given name\n");
  363. }
  364. }
  365. else if (!strcmp(argv[1], "read"))
  366. {
  367. if (dev)
  368. {
  369. /* read the sensor data */
  370. sht3x_read_singleshot(dev);
  371. rt_kprintf("sht3x humidity : %d.%d \n", (int)dev->humidity, (int)(dev->humidity * 10) % 10);
  372. rt_kprintf("sht3x temperature: %d.%d \n", (int)dev->temperature, (int)(dev->temperature * 10) % 10);
  373. }
  374. else
  375. {
  376. rt_kprintf("Please using 'sht3x probe <i2c dev name> <pu/pd>' first\n");
  377. }
  378. }
  379. else if (!strcmp(argv[1], "status"))
  380. {
  381. if(dev)
  382. {
  383. if(sht3x_read_status(dev) == RT_EOK)
  384. {
  385. rt_kprintf("sht3x status:\n");
  386. rt_kprintf("\tchecksum:\t%d\t- 0 means checksum correct\n", dev->status.bits.checksum_ok);
  387. rt_kprintf("\tcommand:\t%d\t- 0 means last cmd executed OK\n", dev->status.bits.command_ok);
  388. rt_kprintf("\treset deteced:\t%d\n", dev->status.bits.reset_detected);
  389. rt_kprintf("\talert pending:\t%d\n", dev->status.bits.alert_pending);
  390. rt_kprintf("\tT track alert:\t%d\n", dev->status.bits.T_tracking_alert);
  391. rt_kprintf("\tRH track alert:\t%d\n", dev->status.bits.RH_tracking_alert);
  392. rt_kprintf("\theater enabled:\t%d\n", dev->status.bits.heater);
  393. }else
  394. {
  395. rt_kprintf("sht3x status not read\n");
  396. }
  397. }else
  398. {
  399. rt_kprintf("Please using 'sht3x probe <i2c dev name> <pu/pd>' first\n");
  400. }
  401. }
  402. else if (!strcmp(argv[1], "reset"))
  403. {
  404. if(dev)
  405. {
  406. if(sht3x_softreset(dev) == RT_EOK)
  407. {
  408. rt_kprintf("sht3x reset cmd sent\n");
  409. }else
  410. {
  411. rt_kprintf("sht3x reset cmd not sent\n");
  412. }
  413. }else
  414. {
  415. rt_kprintf("Please using 'sht3x probe <i2c dev name> <pu/pd>' first\n");
  416. }
  417. }
  418. else if (!strcmp(argv[1], "heater"))
  419. {
  420. if(dev)
  421. {
  422. if( !strcmp(argv[2], "on"))
  423. {
  424. if(sht3x_enable_heater(dev) == RT_EOK)
  425. {
  426. rt_kprintf("sht3x heater cmd sent\n");
  427. }else
  428. {
  429. rt_kprintf("sht3x heater cmd not sent\n");
  430. }
  431. }else if( !strcmp(argv[2], "off"))
  432. {
  433. if(sht3x_disable_heater(dev) == RT_EOK)
  434. {
  435. rt_kprintf("sht3x heater cmd sent\n");
  436. }else
  437. {
  438. rt_kprintf("sht3x heater cmd not sent\n");
  439. }
  440. }
  441. else{
  442. rt_kprintf("Please input correct format:sht3x heater on/off\n");
  443. }
  444. }else
  445. {
  446. rt_kprintf("Please using 'sht3x probe <i2c dev name> <pu/pd>' first\n");
  447. }
  448. }
  449. else
  450. {
  451. rt_kprintf("Unknown command. Enter 'sht3x' for help\n");
  452. }
  453. }
  454. else
  455. {
  456. rt_kprintf("Usage:\n");
  457. rt_kprintf("\tsht3x probe <i2c dev name> <pu/pd> -- probe sensor by i2c dev name and pull config\n");
  458. rt_kprintf("\tsht3x read -- read sensor sht3x data\n");
  459. rt_kprintf("\tsht3x status -- status register of sht3x\n");
  460. rt_kprintf("\tsht3x reset -- send soft reset command to sht3x\n");
  461. rt_kprintf("\tsht3x heater <on/off> -- turn on/off heater of sht3x\n");
  462. }
  463. }
  464. MSH_CMD_EXPORT(sht3x, sht3x sensor);
  465. #endif /* PKG_USING_SHT3X */