|  |  |  | 
|---|
|  |  |  | * | 
|---|
|  |  |  | ********************************************************************************/ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #include <wiringPi.h> | 
|---|
|  |  |  | #include <wiringPiI2C.h> | 
|---|
|  |  |  | #include <string.h> | 
|---|
|  |  |  | #include <stdio.h> | 
|---|
|  |  |  | #include <stdlib.h> | 
|---|
|  |  |  | #include <unistd.h> | 
|---|
|  |  |  | #include <math.h> | 
|---|
|  |  |  | #include <errno.h> | 
|---|
|  |  |  | #include <time.h> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #include "tsl2561.h" | 
|---|
|  |  |  | #include <sys/ioctl.h> | 
|---|
|  |  |  | #include <linux/i2c.h> | 
|---|
|  |  |  | #include <linux/i2c-dev.h> | 
|---|
|  |  |  | #include <sys/types.h> | 
|---|
|  |  |  | #include <sys/stat.h> | 
|---|
|  |  |  | #include <fcntl.h> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #define TSL2561_I2C_ADDR                0x39 | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #define CONTROL_REG                     0x80 | 
|---|
|  |  |  | #define REG_COUNT                       4 | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #define POWER_UP                        0x03 | 
|---|
|  |  |  | #define POWER_DOWN                      0x00 | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /* Register Address  */ | 
|---|
|  |  |  | enum | 
|---|
|  |  |  | { | 
|---|
|  |  |  | /* Channel_0 = DATA0HIGH<<8 + DATA0LOW */ | 
|---|
|  |  |  | DATA0LOW = 0x8C, | 
|---|
|  |  |  | DATA0HIGH, | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /* Channel_1 = DATA1HIGH<<8 + DATA1LOW */ | 
|---|
|  |  |  | DATA1LOW, | 
|---|
|  |  |  | DATA1HIGH, | 
|---|
|  |  |  | }; | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int tsl_fd = -1; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | static const int  regs_addr[REG_COUNT]={DATA0LOW, DATA0HIGH, DATA1LOW, DATA1HIGH}; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #define msleep(x) usleep( 1000*(x) ) | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int tsl2561_init(void) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if(tsl_fd > 0) | 
|---|
|  |  |  | return 0; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | tsl_fd = wiringPiI2CSetup(TSL2561_I2C_ADDR); | 
|---|
|  |  |  | if(tsl_fd < 0) | 
|---|
|  |  |  | if( (tsl_fd=open("/dev/i2c-1", O_RDWR)) < 0) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | printf("TSL2561 I2C setup failure: %s\n", strerror(errno)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | else | 
|---|
|  |  |  | { | 
|---|
|  |  |  | printf("TSL2561 initialise ok, tsl_fd=%d\n", tsl_fd); | 
|---|
|  |  |  | printf("TSL2561 I2C device setup failure: %s\n", strerror(errno)); | 
|---|
|  |  |  | return -1; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | printf("TSL2561 initialise ok, tsl_fd=%d\n", tsl_fd); | 
|---|
|  |  |  | return tsl_fd; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #define ON          1 | 
|---|
|  |  |  | #define OFF         0 | 
|---|
|  |  |  |  | 
|---|
|  |  |  | void tsl2561_power(int cmd) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | struct i2c_msg               msg; | 
|---|
|  |  |  | struct i2c_rdwr_ioctl_data   data; | 
|---|
|  |  |  | unsigned char                buf[2]; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | msg.addr= TSL2561_I2C_ADDR; | 
|---|
|  |  |  | msg.flags=0;  /* write */ | 
|---|
|  |  |  | msg.len= 1; | 
|---|
|  |  |  | msg.buf= buf; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | data.nmsgs= 1; | 
|---|
|  |  |  | data.msgs= &msg; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | msg.buf[0]=CONTROL_REG; | 
|---|
|  |  |  | if( ioctl(tsl_fd, I2C_RDWR, &data) < 0 ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | printf("%s() ioctl failure: %s\n", __func__, strerror(errno)); | 
|---|
|  |  |  | return ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( cmd ) | 
|---|
|  |  |  | msg.buf[0]=POWER_UP; | 
|---|
|  |  |  | else | 
|---|
|  |  |  | msg.buf[0]=POWER_DOWN; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( ioctl(tsl_fd, I2C_RDWR, &data) < 0 ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | printf("%s() ioctl failure: %s\n", __func__, strerror(errno)); | 
|---|
|  |  |  | return ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int tsl2561_readreg(unsigned char regaddr, unsigned char *regval) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | struct i2c_msg               msg; | 
|---|
|  |  |  | struct i2c_rdwr_ioctl_data   data; | 
|---|
|  |  |  | unsigned char                buf[2]; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | msg.addr= TSL2561_I2C_ADDR; | 
|---|
|  |  |  | msg.flags=0;  /* write */ | 
|---|
|  |  |  | msg.len= 1; | 
|---|
|  |  |  | msg.buf= buf; | 
|---|
|  |  |  | msg.buf[0] = regaddr; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | data.nmsgs= 1; | 
|---|
|  |  |  | data.msgs= &msg; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( ioctl(tsl_fd, I2C_RDWR, &data) < 0 ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | printf("%s() ioctl failure: %s\n", __func__, strerror(errno)); | 
|---|
|  |  |  | return -1; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | memset(buf, 0, sizeof(buf)); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | msg.addr= TSL2561_I2C_ADDR; | 
|---|
|  |  |  | msg.flags=I2C_M_RD;  /* read */ | 
|---|
|  |  |  | msg.len= 1; | 
|---|
|  |  |  | msg.buf= buf; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | data.nmsgs= 1; | 
|---|
|  |  |  | data.msgs= &msg; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( ioctl(tsl_fd, I2C_RDWR, &data) < 0 ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | printf("%s() ioctl failure: %s\n", __func__, strerror(errno)); | 
|---|
|  |  |  | return -1; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | *regval = msg.buf[0]; | 
|---|
|  |  |  | return 0; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int tsl2561_get_lux(void) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | int                 i; | 
|---|
|  |  |  | int                 reg_data[REG_COUNT]; | 
|---|
|  |  |  | unsigned char       reg_data[REG_COUNT]; | 
|---|
|  |  |  | unsigned char       buf; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int                 chn0_data = 0; | 
|---|
|  |  |  | int                 chn1_data = 0; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | double              div = 0.0; | 
|---|
|  |  |  | double              lux = 0.0; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /* Power up TSL2561 */ | 
|---|
|  |  |  | wiringPiI2CWrite(tsl_fd, CONTROL_REG); | 
|---|
|  |  |  | wiringPiI2CWrite(tsl_fd, POWER_UP); | 
|---|
|  |  |  | float               div = 0.0; | 
|---|
|  |  |  | float               lux = 0.0; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | sleep(1); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | tsl2561_power(ON); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | msleep(410);  /* t(CONV) MAX 400ms */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /* Read register Channel0 and channel1 data from register */ | 
|---|
|  |  |  | for(i=0; i<REG_COUNT; i++) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | wiringPiI2CWrite(tsl_fd, regs_addr[i]); | 
|---|
|  |  |  | reg_data[i] = wiringPiI2CRead(tsl_fd); | 
|---|
|  |  |  | //printf("write and read register: 0x%0x->%d\n", regs_addr[i], reg_data[i]); | 
|---|
|  |  |  | tsl2561_readreg(regs_addr[i], ®_data[i]); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | chn0_data = reg_data[1]*256 + reg_data[0]; /* Channel0 = DATA0HIGH<<8 + DATA0LOW  */ | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( chn0_data<=0 || chn1_data<0 ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | //printf("TSL2561 get date chn0_data[%d] chn1_data[%d]\n", chn0_data, chn1_data); | 
|---|
|  |  |  | lux = 0.0; | 
|---|
|  |  |  | goto OUT; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | div = (double)chn1_data / (double)chn0_data; | 
|---|
|  |  |  | 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); | 
|---|
|  |  |  | 
|---|
|  |  |  | OUT: | 
|---|
|  |  |  | printf("TSLl2561 get lux: %.3f\n", lux); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | wiringPiI2CWrite(tsl_fd, CONTROL_REG); | 
|---|
|  |  |  | wiringPiI2CWrite(tsl_fd, POWER_DOWN); | 
|---|
|  |  |  | tsl2561_power(OFF); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | void print_datime(void) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | time_t         tmp; | 
|---|
|  |  |  | struct tm     *p; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | time(&tmp); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | p=localtime(&tmp); | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | printf("%d-%02d-%02d %02d:%02d:%02d\t", (p->tm_year+1900),(p->tm_mon+1), | 
|---|
|  |  |  | p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int main(int argc, char **argv) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | while(1) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | print_datime(); | 
|---|
|  |  |  | tsl2561_get_lux(); | 
|---|
|  |  |  | sleep(interval); | 
|---|
|  |  |  | } | 
|---|