From d03f549fa5327ff2e138547e702877cb12a82189 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Sat, 22 Nov 2025 20:24:56 +0800
Subject: [PATCH] update TSL2561 source code to fix bug
---
utils/tsl2561.c | 109 ++++++++++++++++++++++++++++++++----------------------
1 files changed, 64 insertions(+), 45 deletions(-)
diff --git a/utils/tsl2561.c b/utils/tsl2561.c
index 20bd0c2..d21dc32 100644
--- a/utils/tsl2561.c
+++ b/utils/tsl2561.c
@@ -63,7 +63,7 @@
static const int regs_addr[REG_COUNT]={DATA0LOW, DATA0HIGH, DATA1LOW, DATA1HIGH};
-float tsl2561_get_lux(int fd);
+int tsl2561_get_lux(char *dev, float *lux);
static inline void print_datime(void);
static inline void banner(const char *progname)
@@ -89,7 +89,7 @@
int main(int argc, char **argv)
{
- int fd, rv;
+ int rv;
float lux;
char *dev = "/dev/i2c-0";
char *progname=NULL;
@@ -125,26 +125,17 @@
}
}
- /*+--------------------------------+
- *| open /dev/i2c-x device |
- *+--------------------------------+*/
- if( (fd=open(dev, O_RDWR)) < 0)
- {
- printf("i2c device '%s' open failed: %s\n", dev, strerror(errno));
- return -1;
- }
-
while(1)
{
- lux = tsl2561_get_lux(fd);
-
- print_datime();
- printf("TSLl2561 get lux: %.3f\n", lux);
+ if( !tsl2561_get_lux(dev, &lux) )
+ {
+ print_datime();
+ printf("TSLl2561 get lux: %.3f\n", lux);
+ }
sleep(1);
}
- close(fd);
return 0;
}
@@ -260,17 +251,27 @@
return 0;
}
-float tsl2561_get_lux(int fd)
+int tsl2561_get_lux(char *dev, float *lux)
{
- int i;
+ int i, fd;
+ int rv = 0;
+
unsigned char reg_data[REG_COUNT];
- unsigned char buf;
+ int ch0_data = 0;
+ int ch1_data = 0;
+ float ratio = 0.0;
- int chn0_data = 0;
- int chn1_data = 0;
+ if( !lux )
+ {
+ printf("Invalid input arguments\n");
+ return -1;
+ }
- float div = 0.0;
- float lux = 0.0;
+ if( (fd=open(dev, O_RDWR)) < 0)
+ {
+ printf("i2c device '%s' open failed: %s\n", dev, strerror(errno));
+ return -2;
+ }
tsl2561_power(fd, ON);
@@ -279,38 +280,56 @@
/* Read register Channel0 and channel1 data from register */
for(i=0; i<REG_COUNT; i++)
{
- tsl2561_readreg(fd, regs_addr[i], ®_data[i]);
+ rv = tsl2561_readreg(fd, regs_addr[i], ®_data[i]);
+ if( rv < 0)
+ {
+ printf("TSL2561 read register failed\n");
+ goto cleanup;
+ }
}
- chn0_data = reg_data[1]*256 + reg_data[0]; /* Channel0 = DATA0HIGH<<8 + DATA0LOW */
- chn1_data = reg_data[3]*256 + reg_data[2]; /* channel1 = DATA1HIGH<<8 + DATA1LOW */
+ rv = 0;
+ ch0_data = (reg_data[1]<<8) + reg_data[0]; /* 通道0:可见光+红外 */
+ ch1_data = (reg_data[3]<<8) + reg_data[2]; /* 通道1:仅红外 */
- if( chn0_data<=0 || chn1_data<0 )
- {
- lux = 0.0;
- goto OUT;
+
+ /* 根据datasheet,饱和时光照强度很大 */
+ if (ch0_data == 0xFFFF || ch1_data == 0xFFFF) {
+ *lux = 50000.0;
+ goto cleanup;
}
- div = (float)chn1_data / (float)chn0_data;
+ if (ch0_data == 0) { /* 无光照 */
+ *lux = 0.0;
+ goto cleanup;
+ }
- if( div>0 && div<=0.5 )
- lux = 0.304*chn0_data-0.062*chn0_data*pow(div,1.4);
+ ratio = (float)ch1_data / (float)ch0_data;
- else if( div>0.5 && div<=0.61 )
- lux = 0.0224*chn0_data-0.031*chn1_data;
+ if (ratio >= 0 && ratio <= 0.50) {
+ *lux = 0.0304f * ch0_data - 0.062f * ch0_data * powf(ratio, 1.4f);
+ }
+ else if (ratio <= 0.61) {
+ *lux = 0.0224f * ch0_data - 0.031f * ch1_data;
+ }
+ else if (ratio <= 0.80) {
+ *lux = 0.0128f * ch0_data - 0.0153f * ch1_data;
+ }
+ else if (ratio <= 1.30) {
+ *lux = 0.00146f * ch0_data - 0.00112f * ch1_data;
+ }
+ else { /* 超出有效范围 */
+ *lux = 0.0;
+ }
- else if( div>0.61 && div<=0.8 )
- lux = 0.0128*chn0_data-0.0153*chn1_data;
+ if (*lux < 0) { /* 确保结果非负 */
+ *lux = 0.0;
+ }
- else if( div>0.8 && div<=1.3 )
- lux = 0.00146*chn0_data-0.00112*chn1_data;
-
- else if( div>1.3 )
- lux = 0.0;
-
-OUT:
+cleanup:
tsl2561_power(fd, OFF);
- return lux;
+ close(fd);
+ return rv;
}
static inline void dump_buf(const char *prompt, char *buf, int size)
--
Gitblit v1.9.1