RaspberrPi project source code
Guo Wenxue
6 days ago f7889e2ceddbc3e15ea4b5377d831f4432169f76
commit | author | age
e30a4c 1 /*********************************************************************************
GW 2  *      Copyright:  (C) 2018 LingYun IoT System Studio
3  *                  All rights reserved.
4  *
5  *       Filename:  sht20.c
6  *    Description:  This file is temperature and relative humidity sensor SHT20 code
7  *
8  *        Version:  1.0.0(2018/10/14)
9  *         Author:  Guo Wenxue <guowenxue@gmail.com>
10  *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
11  *
12  ********************************************************************************/
13
14 #include <stdio.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <sys/ioctl.h>
18 #include <linux/types.h>
19 #include <sys/stat.h>
20 #include <linux/i2c.h>
21 #include <linux/i2c-dev.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <string.h>
26 #include <stdint.h>
27 #include <time.h>
28 #include <errno.h>
29 #include <string.h>
30
31 #include "sht20.h"
32 #include "logger.h"
33 #include "util_proc.h"
34
35 static int s_sht2x_fd = -1;
36
37 void sht2x_term(void)
38 {
39     close(s_sht2x_fd);
40     s_sht2x_fd = -1;
41     log_warn("Terminate SHT2X\n");
42 }
43
44 static inline void dump_buf(const char *prompt, uint8_t *buf, int size)
45 {
46     int          i;
47
48     if( !buf )
49     {
50         return ;
51     }
52
53     if( prompt )
54     {
55         printf("%s ", prompt);
56     }
57
58     for(i=0; i<size; i++)
59     {
60         printf("%02x ", buf[i]);
61     }
62     printf("\n");
63
64     return ;
65 }
66
67 #ifdef I2C_API_RDWR  /* Use I2C userspace driver read/write API */
68
69 int sht2x_softreset(int fd)
70 {
71     uint8_t           buf[4];
72
73     if( fd<0 )
74     {
75         log_error("Invalid input arguments\n");
76         return -1;
77     }
78
79     /* software reset SHT2x */
80     memset(buf, 0, sizeof(buf));
81
82     buf[0] = SOFTRESET;
83     write(fd, buf, 1);
84
85     msleep(50);
86
87     return 0;
88 }
89
90 int sht2x_init(void)
91 {
92
93     if( (s_sht2x_fd=open("/dev/i2c-1", O_RDWR)) < 0)
94     {
95         log_error("i2c device open failed: %s\n", strerror(errno));
96         return -1;
97     }
98
99     /* set I2C mode and SHT2x slave address */
100     ioctl(s_sht2x_fd, I2C_TENBIT, 0);    /* Not 10-bit but 7-bit mode */
101     ioctl(s_sht2x_fd, I2C_SLAVE, 0x40); /* set SHT2x slava address 0x40*/
102
103     if( sht2x_softreset(s_sht2x_fd) < 0 )
104     {
105         log_error("SHT2x softreset failure\n");
106         sht2x_term();
107         return -2;
108     }
109
110     log_debug("SHT2X initialise ok, s_sht2x_fd=%d\n", s_sht2x_fd);
111     return s_sht2x_fd;
112 }
113
114 int sht2x_get_temp_humidity(float *temp, float *rh)
115 {
116     uint8_t           buf[4];
117
118     if( !temp || !rh )
119     {
120         log_error("Invalid input arguments\n");
121         return -1;
122     }
123
124     if( s_sht2x_fd < 0 )
125     {
126         if( sht2x_init() < 0)
127         {
128             log_error("SHT2x initialise failure\n");
129             return -2;
130         }
131     }
132
133     /* send trigger temperature measure command and read the data */
134     memset(buf, 0, sizeof(buf));
135     buf[0]=TRIGGER_TEMPERATURE_NO_HOLD;
136     write(s_sht2x_fd, buf, 1);
137
138     msleep(85); /* datasheet: typ=66, max=85 */
139
140     memset(buf, 0, sizeof(buf));
141     read(s_sht2x_fd, buf, 3);
142     //dump_buf("Temperature sample data: ", buf, 3);
143     *temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
144
145     /* send trigger humidity measure command and read the data */
146     memset(buf, 0, sizeof(buf));
147     buf[0] = TRIGGER_HUMIDITY_NO_HOLD;
148     write(s_sht2x_fd, buf, 1);
149
150     msleep(29); /* datasheet: typ=22, max=29 */
151     memset(buf, 0, sizeof(buf));
152
153     read(s_sht2x_fd, buf, 3);
154     //dump_buf("Relative humidity sample data: ", buf, 3);
155     *rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
156
157     return 0;
158 }
159
160 int sht2x_get_serialnumber(uint8_t *serialnumber, int size)
161 {
162     uint8_t           buf[4];
163
164     if( !serialnumber || size!=8 )
165     {
166         log_error("Invalid input arguments\n");
167         return -1;
168     }
169
170     if( s_sht2x_fd < 0 )
171     {
172         if( sht2x_init() < 0)
173         {
174             log_error("SHT2x initialise failure\n");
175             return -2;
176         }
177     }
178
179     /* Read SerialNumber from Location 1 */
180     memset(buf, 0, sizeof(buf));
181     buf[0] = 0xfa;  /* command for readout on-chip memory */
182     buf[1] = 0x0f;  /* on-chip memory address */
183     write(s_sht2x_fd, buf, 2);
184
185     memset(buf, 0, sizeof(buf));
186     read(s_sht2x_fd, buf, 4);
187
188     serialnumber[5]=buf[0]; /* Read SNB_3 */
189     serialnumber[4]=buf[1]; /* Read SNB_2 */
190     serialnumber[3]=buf[2]; /* Read SNB_1 */
191     serialnumber[2]=buf[3]; /* Read SNB_0 */
192
193     /* Read SerialNumber from Location 2 */
194     memset(buf, 0, sizeof(buf) );
195     buf[0]=0xfc;  /* command for readout on-chip memory */
196     buf[1]=0xc9;  /* on-chip memory address */
197     write(s_sht2x_fd, buf, 2);
198
199     memset(buf, 0, sizeof(buf) );
200     read(s_sht2x_fd, buf, 4);
201
202     serialnumber[1]=buf[0]; /* Read SNC_1 */
203     serialnumber[0]=buf[1]; /* Read SNC_0 */
204     serialnumber[7]=buf[2]; /* Read SNA_1 */
205     serialnumber[6]=buf[3]; /* Read SNA_0 */
206
207     //dump_buf("SHT2x Serial number: ", serialnumber, 8);
208
209     return 0;
210 }
211
212 #elif (defined I2C_API_IOCTL)  /* Use I2C userspace driver read/write API */
213
214 int sht2x_softreset(int fd)
215 {
216     struct i2c_msg               msg;
217     struct i2c_rdwr_ioctl_data   sht2x_data;
218     uint8_t                      buf[2];
219
220     if( fd<0 )
221     {
222         log_error("Invalid input arguments\n");
223         return -1;
224     }
225
226     msg.addr= 0x40;
227     msg.flags=0; //write
228     msg.len= 1;
229     msg.buf= buf;
230     msg.buf[0]=SOFTRESET;
231
232     sht2x_data.nmsgs= 1;
233     sht2x_data.msgs= &msg;
234
235     if( ioctl(fd, I2C_RDWR, &sht2x_data) < 0 )
236     {
237         log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
238         sht2x_term();
239         return -2;
240     }
241
242     msleep(50);
243
244     return 0;
245 }
246
247
248 int sht2x_init(void)
249 {
250     if( (s_sht2x_fd=open("/dev/i2c-1", O_RDWR)) < 0)
251     {
252         log_error("i2c device open failed: %s\n", strerror(errno));
253         return -1;
254     }
255
256     if( sht2x_softreset(s_sht2x_fd) < 0 )
257     {
258         log_error("SHT2x softreset failure\n");
259         sht2x_term();
260         return -2;
261     }
262
263     log_debug("SHT2X initialise ok, s_sht2x_fd=%d\n", s_sht2x_fd);
264     return 0;
265 }
266
267 int sht2x_get_serialnumber(uint8_t *serialnumber, int size)
268 {
269     struct i2c_msg               msgs[2];
270     struct i2c_rdwr_ioctl_data   sht2x_data;
271     uint8_t                      sbuf[2];
272     uint8_t                      rbuf[4];
273
274     if( !serialnumber || size!=8 )
275     {
276         log_error("Invalid input arguments\n");
277         return -1;
278     }
279
280     if( s_sht2x_fd < 0 )
281     {
282         if( sht2x_init() < 0)
283         {
284             log_error("SHT2x initialise failure\n");
285             return -2;
286         }
287     }
288
289     /*+------------------------------------------+
290      *|     Read SerialNumber from Location 1    |
291      *+------------------------------------------+*/
292
293     msgs[0].addr= 0x40;
294     msgs[0].flags=0; //write
295     msgs[0].len= 2;
296     msgs[0].buf= sbuf;
297     msgs[0].buf[0]=0xfa;  /* command for readout on-chip memory */
298     msgs[0].buf[1]=0x0f;  /* on-chip memory address */
299
300     msgs[1].addr=0x40;
301     msgs[1].flags=I2C_M_RD; //write
302     msgs[1].len= 4;
303     msgs[1].buf= rbuf;
304
305     sht2x_data.nmsgs= 2;
306     sht2x_data.msgs= msgs;
307
308     if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
309     {
310         log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
311         sht2x_term();
312         return -2;
313     }
314
315     serialnumber[5]=rbuf[0]; /* Read SNB_3 */
316     serialnumber[4]=rbuf[1]; /* Read SNB_2 */
317     serialnumber[3]=rbuf[2]; /* Read SNB_1 */
318     serialnumber[2]=rbuf[3]; /* Read SNB_0 */
319
320
321     /*+------------------------------------------+
322      *|     Read SerialNumber from Location 2    |
323      *+------------------------------------------+*/
324
325     msgs[0].addr= 0x40;
326     msgs[0].flags=0; //write
327     msgs[0].len= 2;
328     msgs[0].buf= sbuf;
329     msgs[0].buf[0]=0xfc;  /* command for readout on-chip memory */
330     msgs[0].buf[1]=0xc9;  /* on-chip memory address */
331
332     msgs[1].addr=0x40;
333     msgs[1].flags=I2C_M_RD; //write
334     msgs[1].len= 4;
335     msgs[1].buf= rbuf;
336
337     sht2x_data.nmsgs= 2;
338     sht2x_data.msgs= msgs;
339
340     if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
341     {
342         log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
343         sht2x_term();
344         return -2;
345     }
346
347     serialnumber[1]=rbuf[0]; /* Read SNC_1 */
348     serialnumber[0]=rbuf[1]; /* Read SNC_0 */
349     serialnumber[7]=rbuf[2]; /* Read SNA_1 */
350     serialnumber[6]=rbuf[3]; /* Read SNA_0 */
351
352     //dump_buf("SHT2x Serial number: ", serialnumber, 8);
353
354     return 0;
355 }
356
357
358 int sht2x_get_temp_humidity(float *temp, float *rh)
359 {
360     struct i2c_msg               msg;
361     struct i2c_rdwr_ioctl_data   sht2x_data;
362     uint8_t                      buf[4];
363
364     if( !temp || !rh )
365     {
366         log_error("Invalid input arguments\n");
367         return -1;
368     }
369
370     if( s_sht2x_fd < 0 )
371     {
372         if( sht2x_init() < 0)
373         {
374             log_error("SHT2x initialise failure\n");
375             return -2;
376         }
377     }
378
379     /*+------------------------------------------+
380      *|       measure and get temperature        |
381      *+------------------------------------------+*/
382
383     msg.addr= 0x40;
384     msg.flags=0; //write
385     msg.len= 1;
386     msg.buf= buf;
387     msg.buf[0]=TRIGGER_TEMPERATURE_NO_HOLD;  /* trigger temperature without hold I2C bus */
388
389     sht2x_data.nmsgs= 1;
390     sht2x_data.msgs= &msg;
391
392     if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
393     {
394         log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
395         sht2x_term();
396         return -2;
397     }
398
399     msleep(85);
400
401     memset(buf, 0, sizeof(buf));
402     msg.addr=0x40;
403     msg.flags=I2C_M_RD; //write
404     msg.len= 3;
405     msg.buf= buf;
406
407     sht2x_data.nmsgs= 1;
408     sht2x_data.msgs= &msg;
409
410     if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
411     {
412         log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
413         sht2x_term();
414         return -2;
415     }
416
417     //dump_buf("Temperature sample data: ", buf, 3);
418     *temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
419
420
421     /*+------------------------------------------+
422      *|    measure and get relative humidity     |
423      *+------------------------------------------+*/
424
425     msg.addr= 0x40;
426     msg.flags=0; //write
427     msg.len= 1;
428     msg.buf= buf;
429     msg.buf[0]=TRIGGER_HUMIDITY_NO_HOLD;  /* trigger humidity without hold I2C bus */
430
431     sht2x_data.nmsgs= 1;
432     sht2x_data.msgs= &msg;
433
434     if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
435     {
436         log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
437         sht2x_term();
438         return -2;
439     }
440
441     msleep(29);
442
443     memset(buf, 0, sizeof(buf));
444     msg.addr=0x40;
445     msg.flags=I2C_M_RD; //write
446     msg.len= 3;
447     msg.buf= buf;
448
449     sht2x_data.nmsgs= 1;
450     sht2x_data.msgs= &msg;
451
452     if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
453     {
454         log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
455         sht2x_term();
456         return -2;
457     }
458
459     //dump_buf("Relative humidity sample data: ", buf, 3);
460     *rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
461
462     return 0;
463 }
464
465 #endif
466