RaspberrPi project source code
guowenxue
2024-03-14 b3dc672c57aa5374fcd1ba1da5321d6c63d68e0f
commit | author | age
d6b4a7 1 /*********************************************************************************
G 2  *      Copyright:  (C) 2023 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(10/08/23)
9  *         Author:  Guo Wenxue <guowenxue@gmail.com>
10  *      ChangeLog:  1, Release initial version on "10/08/23 17:52:00"
11  *
12  * Pin connection:
13  *               STH20 Module            Raspberry Pi Board
14  *                   VCC      <----->      #Pin1(3.3V)
15  *                   SDA1     <----->      #Pin3(SDA, BCM GPIO2)
16  *                   SCL1     <----->      #Pin5(SCL, BCM GPIO3)
17  *                   GND      <----->      GND
18  *
19  * /boot/config.txt:
20  *                  dtoverlay=i2c1,pins_2_3
21  *
22  ********************************************************************************/
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <libgen.h>
31 #include <getopt.h>
32 #include <time.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <sys/ioctl.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <linux/types.h>
39 #include <linux/i2c.h>
40 #include <linux/i2c-dev.h>
41
42 #include "logger.h"
43 #include "util_proc.h"
44 #include "sht20.h"
45
46 int i2c_write(int fd, uint8_t slave_addr, uint8_t *data, int len);
47 int i2c_read(int fd, uint8_t slave_addr, uint8_t *buf, int size);
48 int sht20_checksum(uint8_t *data, int len, int8_t checksum);
49
50 int sht2x_get_temp_humidity(float *temp, float *rh)
51 {
52     int             fd;
53     int             rv = 0;
54     char           *dev = SHT20_I2CDEV;
55     uint8_t         buf[4];
56
57     if( !temp || !rh )
58     {
59         log_error("Invalid input arguments\n");
60         return -1;
61     }
62
63     /*+--------------------------------+
64      *|     open /dev/i2c-x device     |
65      *+--------------------------------+*/
66     if( (fd=open(dev, O_RDWR)) < 0)
67     {
68         log_error("i2c device '%s' open failed: %s\n", dev, strerror(errno));
69         return -2;
70     }
71
72     /*+--------------------------------+
73      *|   software reset SHT20 sensor  |
74      *+--------------------------------+*/
75
76     buf[0] = 0xFE;
77     i2c_write(fd, SHT20_I2CADDR, buf, 1);
78
79     msleep(50);
80
81
82     /*+--------------------------------+
83      *|   trigger temperature measure  |
84      *+--------------------------------+*/
85
86     buf[0] = 0xF3;
87     i2c_write(fd, SHT20_I2CADDR, buf, 1);
88
89     msleep(85); /* datasheet: typ=66, max=85 */
90
91     memset(buf, 0, sizeof(buf));
92     i2c_read(fd, SHT20_I2CADDR, buf, 3);
93     log_dump(LOG_LEVEL_DEBUG, "Temperature sample data: ", buf, 3);
94
95     if( !sht20_checksum(buf, 2, buf[2]) )
96     {
97         rv = -3;
98         log_error("Temperature sample data CRC checksum failure.\n");
99         goto cleanup;
100     }
101
102     *temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
103
104
105     /*+--------------------------------+
106      *|    trigger humidity measure    |
107      *+--------------------------------+*/
108
109     buf[0] = 0xF5;
110     i2c_write(fd, SHT20_I2CADDR, buf, 1);
111
112     msleep(29); /* datasheet: typ=22, max=29 */
113
114     memset(buf, 0, sizeof(buf));
115     i2c_read(fd, SHT20_I2CADDR, buf, 3);
116     log_dump(LOG_LEVEL_DEBUG, "Relative humidity sample data: ", buf, 3);
117
118     if( !sht20_checksum(buf, 2, buf[2]) )
119     {
120         rv = -4;
121         log_error("Relative humidity sample data CRC checksum failure.\n");
122         goto cleanup;
123     }
124
125     *rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
126
127     /*+--------------------------------+
128      *|    print the measure result    |
129      *+--------------------------------+*/
130
131     log_debug("Temperature=%lf 'C relative humidity=%lf%%\n", *temp, *rh);
132
133 cleanup:
134     close(fd);
135     return rv;
136 }
137
138 int sht20_checksum(uint8_t *data, int len, int8_t checksum)
139 {
140     int8_t crc = 0;
141     int8_t bit;
142     int8_t byteCtr;
143
144     //calculates 8-Bit checksum with given polynomial: x^8 + x^5 + x^4 + 1
145     for (byteCtr = 0; byteCtr < len; ++byteCtr)
146     {
147         crc ^= (data[byteCtr]);
148         for ( bit = 8; bit > 0; --bit)
149         {
150             /* x^8 + x^5 + x^4 + 1 = 0001 0011 0001 = 0x131 */
151             if (crc & 0x80) crc = (crc << 1) ^ 0x131;
152             else crc = (crc << 1);
153         }
154     }
155
156     if (crc != checksum)
157         return 0;
158     else
159         return 1;
160 }
161
162 int i2c_write(int fd, uint8_t slave_addr, uint8_t *data, int len)
163 {
164     struct i2c_rdwr_ioctl_data i2cdata;
165     int rv = 0;
166
167     if( !data || len<= 0)
168     {
169         log_error("%s() invalid input arguments!\n", __func__);
170         return -1;
171     }
172
173     i2cdata.nmsgs = 1;
174     i2cdata.msgs = malloc( sizeof(struct i2c_msg)*i2cdata.nmsgs );
175     if ( !i2cdata.msgs )
176     {
177         log_error("%s() msgs malloc failed!\n", __func__);
178         return -2;
179     }
180
181     i2cdata.msgs[0].addr = slave_addr;
182     i2cdata.msgs[0].flags = 0; //write
183     i2cdata.msgs[0].len = len;
184     i2cdata.msgs[0].buf = malloc(len);
185     if( !i2cdata.msgs[0].buf )
186     {
187         log_error("%s() msgs malloc failed!\n", __func__);
188         rv = -3;
189         goto cleanup;
190     }
191     memcpy(i2cdata.msgs[0].buf, data, len);
192
193
194     if( ioctl(fd, I2C_RDWR, &i2cdata)<0 )
195     {
196         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
197         rv = -4;
198         goto cleanup;
199     }
200
201 cleanup:
202     if( i2cdata.msgs[0].buf )
203         free(i2cdata.msgs[0].buf);
204
205     if( i2cdata.msgs )
206         free(i2cdata.msgs);
207
208     return rv;
209 }
210
211 int i2c_read(int fd, uint8_t slave_addr, uint8_t *buf, int size)
212 {
213     struct i2c_rdwr_ioctl_data i2cdata;
214     int rv = 0;
215
216     if( !buf || size<= 0)
217     {
218         log_error("%s() invalid input arguments!\n", __func__);
219         return -1;
220     }
221
222     i2cdata.nmsgs = 1;
223     i2cdata.msgs = malloc( sizeof(struct i2c_msg)*i2cdata.nmsgs );
224     if ( !i2cdata.msgs )
225     {
226         log_error("%s() msgs malloc failed!\n", __func__);
227         return -2;
228     }
229
230     i2cdata.msgs[0].addr = slave_addr;
231     i2cdata.msgs[0].flags = I2C_M_RD; //read
232     i2cdata.msgs[0].len = size;
233     i2cdata.msgs[0].buf = buf;
234     memset(buf, 0, size);
235
236     if( ioctl(fd, I2C_RDWR, &i2cdata)<0 )
237     {
238         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
239         rv = -4;
240     }
241
242     free( i2cdata.msgs );
243     return rv;
244 }