RaspberrPi project source code
Guo Wenxue
2024-12-29 e30a4c8103e221201e5bfc1e3f9b19e7a86f68d4
commit | author | age
e30a4c 1 /*********************************************************************************
GW 2  *      Copyright:  (C) 2019 LingYun IoT System Studio
3  *                  All rights reserved.
4  *
5  *       Filename:  tsl2561.c
6  *    Description:  This file is the Lux sensor TSL2561 API functions on RaspberryPi,
7  *                  which connected to I2C-1
8  *
9  *        Version:  1.0.0(04/07/19)
10  *         Author:  Guo Wenxue <guowenxue@gmail.com>
11  *      ChangeLog:  1, Release initial version on "04/07/19 17:39:38"
12  *
13  ********************************************************************************/
14
15 #include <string.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <math.h>
20 #include <errno.h>
21 #include <time.h>
22
23 #include <sys/ioctl.h>
24 #include <linux/i2c.h>
25 #include <linux/i2c-dev.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29
30 #include "logger.h"
31 #include "util_proc.h"
32 #include "tsl2561.h"
33
34 int s_tsl_fd = -1;
35
36 static const int  regs_addr[REG_COUNT]={DATA0LOW, DATA0HIGH, DATA1LOW, DATA1HIGH};
37
38 int tsl2561_init(void)
39 {
40     if(s_tsl_fd > 0)
41         return 0;
42
43     if( (s_tsl_fd=open("/dev/i2c-1", O_RDWR)) < 0)
44     {
45         log_error("TSL2561 I2C device setup failure: %s\n", strerror(errno));
46         return -1;
47     }
48
49     log_debug("TSL2561 initialise ok, s_tsl_fd=%d\n", s_tsl_fd);
50     return s_tsl_fd;
51 }
52
53 void tsl2561_term(void)
54 {
55     close(s_tsl_fd);
56     s_tsl_fd = -1;
57     log_warn("Terminate TSL2561.\n");
58 }
59
60
61 #define ON          1
62 #define OFF         0
63
64 int tsl2561_power(int cmd)
65 {
66     struct i2c_msg               msg;
67     struct i2c_rdwr_ioctl_data   data;
68     unsigned char                buf[2];
69
70     msg.addr= TSL2561_I2C_ADDR;
71     msg.flags=0;  /* write */
72     msg.len= 1;
73     msg.buf= buf;
74
75     data.nmsgs= 1;
76     data.msgs= &msg;
77
78     msg.buf[0]=CONTROL_REG;
79     if( ioctl(s_tsl_fd, I2C_RDWR, &data) < 0 )
80     {
81         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
82         return -1;
83     }
84
85
86     if( cmd )
87         msg.buf[0]=POWER_UP;
88     else
89         msg.buf[0]=POWER_DOWN;
90
91     if( ioctl(s_tsl_fd, I2C_RDWR, &data) < 0 )
92     {
93         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
94         return -1;
95     }
96
97     return 0;
98 }
99
100 int tsl2561_readreg(unsigned char regaddr, unsigned char *regval)
101 {
102     struct i2c_msg               msg;
103     struct i2c_rdwr_ioctl_data   data;
104     unsigned char                buf[2];
105
106     msg.addr= TSL2561_I2C_ADDR;
107     msg.flags=0;  /* write */
108     msg.len= 1;
109     msg.buf= buf;
110     msg.buf[0] = regaddr;
111
112     data.nmsgs= 1;
113     data.msgs= &msg;
114
115     if( ioctl(s_tsl_fd, I2C_RDWR, &data) < 0 )
116     {
117         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
118         return -1;
119     }
120
121     memset(buf, 0, sizeof(buf));
122
123     msg.addr= TSL2561_I2C_ADDR;
124     msg.flags=I2C_M_RD;  /* read */
125     msg.len= 1;
126     msg.buf= buf;
127
128     data.nmsgs= 1;
129     data.msgs= &msg;
130
131     if( ioctl(s_tsl_fd, I2C_RDWR, &data) < 0 )
132     {
133         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
134         return -1;
135     }
136
137     *regval = msg.buf[0];
138     return 0;
139 }
140
141
142
143 float tsl2561_get_lux(void)
144 {
145     int                 i;
146     unsigned char       reg_data[REG_COUNT];
147
148     int                 chn0_data = 0;
149     int                 chn1_data = 0;
150
151     float               div = 0.0;
152     float               lux = 0.0;
153
154
155     tsl2561_power(ON);
156
157     msleep(410);  /* t(CONV) MAX 400ms */
158
159     /* Read register Channel0 and channel1 data from register */
160     for(i=0; i<REG_COUNT; i++)
161     {
162         tsl2561_readreg(regs_addr[i], &reg_data[i]);
163     }
164
165     chn0_data = reg_data[1]*256 + reg_data[0]; /* Channel0 = DATA0HIGH<<8 + DATA0LOW  */
166     chn1_data = reg_data[3]*256 + reg_data[2]; /* channel1 = DATA1HIGH<<8 +  DATA1LOW */
167
168     if( chn0_data<=0 || chn1_data<0 )
169     {
170         lux = 0.0;
171         goto OUT;
172     }
173
174     div = (float)chn1_data / (float)chn0_data;
175
176     if( div>0 && div<=0.5 )
177         lux = 0.304*chn0_data-0.062*chn0_data*pow(div,1.4);
178
179     else if( div>0.5 && div<=0.61 )
180         lux = 0.0224*chn0_data-0.031*chn1_data;
181
182     else if( div>0.61 && div<=0.8 )
183         lux = 0.0128*chn0_data-0.0153*chn1_data;
184
185     else if( div>0.8 && div<=1.3 )
186         lux = 0.00146*chn0_data-0.00112*chn1_data;
187
188     else if( div>1.3 )
189         lux = 0.0;
190
191     log_debug("TSLl2561 get lux: %.3f\n", lux);
192
193 OUT:
194     tsl2561_power(OFF);
195     return lux;
196 }
197
198