RaspberrPi project source code
guowenxue
2 days ago d03f549fa5327ff2e138547e702877cb12a82189
update TSL2561 source code to fix bug
6 files modified
257 ■■■■■ changed files
project/lightd/etc/lightd.conf 12 ●●●●● patch | view | raw | blame | history
project/lightd/hal/tsl2561.c 65 ●●●●● patch | view | raw | blame | history
project/lightd/hal/tsl2561.h 2 ●●● patch | view | raw | blame | history
project/modules/tsl2561.c 67 ●●●●● patch | view | raw | blame | history
project/modules/tsl2561.h 2 ●●● patch | view | raw | blame | history
utils/tsl2561.c 109 ●●●●● patch | view | raw | blame | history
project/lightd/etc/lightd.conf
@@ -11,20 +11,16 @@
tsl2561=1
# TSL2561 光强传感器光强阈值
lux_threshold=0.10
lux_threshold=0.005
# 红外传感器(有人时输出高电平), 格式: {名称:BCM编码:控制电平}
# Indoor(#16)<->(black/gray)    Hallway(#12)<->(yellow/red)
# 测试延时: while true; do gpioget gpiochip0 18; sleep 1; done
gpio_inpin={infrared_indoor:23:1},{infrared_hallway:18:1}
gpio_inpin={infrared_indoor:24:1},{infrared_hallway:23:1}
# 继电器GPIO输出控制,     格式: {名称:BCM编码:控制电平}
#            Relay(1) <-> #35     Relay(2) <-> #37
gpio_outpin={light_indoor:19:1},{light_hallway:26:1}
gpio_outpin={light_indoor:26:1},{light_hallway:19:1}
# 红外探测到人后,继电器控制灯亮的时长
light_intval=15
[logger]
@@ -65,7 +61,7 @@
pubQos=0
# Publisher上报传感器数据的周期,单位是秒
interval=60
interval=300
[subsciber]
project/lightd/hal/tsl2561.c
@@ -147,11 +147,11 @@
    int                 i, fd;
    int                 rv = 0;
    char               *dev = TSL2561_I2CDEV;
    float               div = 0.0;
    unsigned char       reg_data[REG_COUNT];
    int                 chn0_data = 0;
    int                 chn1_data = 0;
    int                 ch0_data = 0;
    int                 ch1_data = 0;
    float               ratio = 0.0;
    if( !lux )
    {
@@ -174,39 +174,52 @@
    {
        rv = tsl2561_readreg(fd, regs_addr[i], &reg_data[i]);
        if( rv < 0)
            goto failed;
        {
            log_error("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 )
    {
        rv = -2;
    /* 根据datasheet,饱和时光照强度很大 */
    if (ch0_data == 0xFFFF || ch1_data == 0xFFFF) {
        *lux = 50000.0;
        goto cleanup;
    }
    div = (float)chn1_data / (float)chn0_data;
    if( div>0 && div<=0.5 )
        *lux = 0.304*chn0_data-0.062*chn0_data*pow(div,1.4);
    else if( div>0.5 && div<=0.61 )
        *lux = 0.0224*chn0_data-0.031*chn1_data;
    else if( div>0.61 && div<=0.8 )
        *lux = 0.0128*chn0_data-0.0153*chn1_data;
    else if( div>0.8 && div<=1.3 )
        *lux = 0.00146*chn0_data-0.00112*chn1_data;
    else if( div>1.3 )
    if (ch0_data == 0) { /* 无光照 */
        *lux = 0.0;
        goto cleanup;
    }
    ratio = (float)ch1_data / (float)ch0_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;
    }
    if (*lux < 0) { /* 确保结果非负 */
        *lux = 0.0;
    }
cleanup:
    tsl2561_power(fd, OFF);
failed:
    close(fd);
    return rv;
}
project/lightd/hal/tsl2561.h
@@ -24,7 +24,7 @@
#ifndef  _TSL2561_H_
#define  _TSL2561_H_
#define TSL2561_I2CDEV                 "/dev/i2c-0"
#define TSL2561_I2CDEV                 "/dev/i2c-1"
#define TSL2561_I2CADDR                 0x39
extern int tsl2561_get_lux(float *lux);
project/modules/tsl2561.c
@@ -37,8 +37,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include "utils.h"
#include "logger.h"
#include "utils.h"
#include "tsl2561.h"
@@ -147,11 +147,11 @@
    int                 i, fd;
    int                 rv = 0;
    char               *dev = TSL2561_I2CDEV;
    float               div = 0.0;
    unsigned char       reg_data[REG_COUNT];
    int                 chn0_data = 0;
    int                 chn1_data = 0;
    int                 ch0_data = 0;
    int                 ch1_data = 0;
    float               ratio = 0.0;
    if( !lux )
    {
@@ -174,39 +174,52 @@
    {
        rv = tsl2561_readreg(fd, regs_addr[i], &reg_data[i]);
        if( rv < 0)
            goto failed;
        {
            log_error("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 )
    {
        rv = -2;
    /* 根据datasheet,饱和时光照强度很大 */
    if (ch0_data == 0xFFFF || ch1_data == 0xFFFF) {
        *lux = 50000.0;
        goto cleanup;
    }
    div = (float)chn1_data / (float)chn0_data;
    if( div>0 && div<=0.5 )
        *lux = 0.304*chn0_data-0.062*chn0_data*pow(div,1.4);
    else if( div>0.5 && div<=0.61 )
        *lux = 0.0224*chn0_data-0.031*chn1_data;
    else if( div>0.61 && div<=0.8 )
        *lux = 0.0128*chn0_data-0.0153*chn1_data;
    else if( div>0.8 && div<=1.3 )
        *lux = 0.00146*chn0_data-0.00112*chn1_data;
    else if( div>1.3 )
    if (ch0_data == 0) { /* 无光照 */
        *lux = 0.0;
        goto cleanup;
    }
    ratio = (float)ch1_data / (float)ch0_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;
    }
    if (*lux < 0) { /* 确保结果非负 */
        *lux = 0.0;
    }
cleanup:
    tsl2561_power(fd, OFF);
failed:
    close(fd);
    return rv;
}
project/modules/tsl2561.h
@@ -24,7 +24,7 @@
#ifndef  _TSL2561_H_
#define  _TSL2561_H_
#define TSL2561_I2CDEV                 "/dev/i2c-0"
#define TSL2561_I2CDEV                 "/dev/i2c-1"
#define TSL2561_I2CADDR                 0x39
extern int tsl2561_get_lux(float *lux);
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], &reg_data[i]);
        rv = tsl2561_readreg(fd, regs_addr[i], &reg_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)