Add tsl2561 code, and test force fill-in light ok
	
		
		2 files added
	
		
		6 files modified
	
	
 
	
	
	
	
	
	
	
	
|  |  |  | 
|---|
|  |  |  | log_warn("WARNNING: LUX sensor hardware not enable and change fill-in light mode to ON\n"); | 
|---|
|  |  |  | ctx->hwconf.fillin_light = FILLIN_LIGHT_ON; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | ctx->hwconf.light_intval = iniparser_getint(ini, "hardware:light_intval", 20); | 
|---|
|  |  |  | log_nrml("Parser inbreak fill-in light interval time [%d]\n", ctx->hwconf.light_intval); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /* Infrared detect inbreank  */ | 
|---|
|  |  |  | unsigned char  infrared_pin; /* enable or disable inbreak detected */ | 
|---|
|  |  |  | void (*ifrd_handler)(void);  /* infrared detected interrupt handler */ | 
|---|
|  |  |  | unsigned char  inbreak_beep; /* enable or diable beep when detect inbreak */ | 
|---|
|  |  |  | unsigned char  fillin_light; /* fill-in light when detect inbrank or not */ | 
|---|
|  |  |  | unsigned char  light_intval; /* fill-in light interval time, unit second  */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } hwconf_t; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | # 如果探测到人来了是否通过继电器控制灯泡, 0:不补光 1:补光 2:根据光强传感器的信息自动补光,如果光强传感器不在则补光 | 
|---|
|  |  |  | fillin_light=2 | 
|---|
|  |  |  |  | 
|---|
|  |  |  | # 继电器补光时长, 单位秒. 红外探测到人后电平为此时间大概是35秒左右 | 
|---|
|  |  |  | light_intval=35 | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | [logger] | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | if( hwconf->beep_pin ) | 
|---|
|  |  |  | init_beep(hwconf->beep_pin); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( hwconf->infrared_pin && hwconf->ifrd_handler ) | 
|---|
|  |  |  | init_infrared(hwconf->infrared_pin, INT_EDGE_RISING, hwconf->ifrd_handler); | 
|---|
|  |  |  | if( hwconf->infrared_pin ) | 
|---|
|  |  |  | init_infrared(hwconf->infrared_pin); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( hwconf->sht2x && sht2x_init() < 0 ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | log_err("Initialise SHT20 failure\n"); | 
|---|
|  |  |  | log_err("Initialise SHT20 T&H sensor failure\n"); | 
|---|
|  |  |  | return -1; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( hwconf->lux && tsl2561_init() < 0 ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | log_err("Initialise TSL2561 Lux sensor failure\n"); | 
|---|
|  |  |  | return -1; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return 0; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | void init_beep(int pin) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | beep_pin = pin; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /* TBD */ | 
|---|
|  |  |  | //pinMode(relay_pin, OUTPUT); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | void init_infrared(int pin, int irq_type, void (*handler)(void)) | 
|---|
|  |  |  | void turn_beep(int times) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | /* TBD */ | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /* wiringPi IRQ handler use a thread and can not pass argument, so we don't use interrupt */ | 
|---|
|  |  |  | void init_infrared(int pin) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | infrared_pin = pin; | 
|---|
|  |  |  | pinMode(pin, INPUT); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | delay(100); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | wiringPiISR(pin, irq_type, handler); | 
|---|
|  |  |  | /*  jitter_time: cancel jitter interval time | 
|---|
|  |  |  | * Return value: 1(HIGH): Sombody detected  0(LOW): Nobody detected */ | 
|---|
|  |  |  | int infrared_detect(int jitter_time) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if( digitalRead(infrared_pin) ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | msleep(jitter_time); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return digitalRead(infrared_pin); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | void turn_relay(int cmd) | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #include "ds18b20.h" | 
|---|
|  |  |  | #include "sht20.h" | 
|---|
|  |  |  | #include "tsl2561.h" | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #define OFF   0 | 
|---|
|  |  |  | #define ON    1 | 
|---|
|  |  |  | 
|---|
|  |  |  | extern int hal_init(hwconf_t *conf); | 
|---|
|  |  |  | extern void turn_relay(int cmd); | 
|---|
|  |  |  | extern int turn_led(int which, int cmd); | 
|---|
|  |  |  | extern void init_infrared(int pin, int irq_type, void (*handler)(void)); | 
|---|
|  |  |  | extern void init_infrared(int pin); | 
|---|
|  |  |  | extern void turn_beep(int times); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /*  jitter_time: cancel jitter interval time | 
|---|
|  |  |  | * Return value: 1(HIGH): Sombody detected  0(LOW): Nobody detected */ | 
|---|
|  |  |  | extern int infrared_detect(int jitter_time); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #endif   /* ----- #ifndef _HAL_H_  ----- */ | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | /********************************************************************************* | 
|---|
|  |  |  | *      Copyright:  (C) 2019 LingYun IoT System Studio | 
|---|
|  |  |  | *                  All rights reserved. | 
|---|
|  |  |  | * | 
|---|
|  |  |  | *       Filename:  tsl2561.c | 
|---|
|  |  |  | *    Description:  This file is the Lux sensor TSL2561 API functions on RaspberryPi, | 
|---|
|  |  |  | *                  which connected to I2C-1 | 
|---|
|  |  |  | * | 
|---|
|  |  |  | *        Version:  1.0.0(04/07/19) | 
|---|
|  |  |  | *         Author:  Guo Wenxue <guowenxue@gmail.com> | 
|---|
|  |  |  | *      ChangeLog:  1, Release initial version on "04/07/19 17:39:38" | 
|---|
|  |  |  | * | 
|---|
|  |  |  | ********************************************************************************/ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #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" | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int tsl_fd = -1; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | static const int  regs_addr[REG_COUNT]={DATA0LOW, DATA0HIGH, DATA1LOW, DATA1HIGH}; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int tsl2561_init(void) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if(tsl_fd > 0) | 
|---|
|  |  |  | return 0; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | tsl_fd = wiringPiI2CSetup(TSL2561_I2C_ADDR); | 
|---|
|  |  |  | if(tsl_fd < 0) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | printf("TSL2561 I2C setup failure: %s\n", strerror(errno)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | else | 
|---|
|  |  |  | { | 
|---|
|  |  |  | printf("TSL2561 initialise ok, tsl_fd=%d\n", tsl_fd); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return tsl_fd; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | double tsl2561_get_lux(void) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | int                 i; | 
|---|
|  |  |  | int                 reg_data[REG_COUNT]; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 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); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | delay(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]); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 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 */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 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; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 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 ) | 
|---|
|  |  |  | lux = 0.0; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | OUT: | 
|---|
|  |  |  | printf("TSLl2561 get lux: %.3f\n", lux); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | wiringPiI2CWrite(tsl_fd, CONTROL_REG); | 
|---|
|  |  |  | wiringPiI2CWrite(tsl_fd, POWER_DOWN); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return lux; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | /******************************************************************************** | 
|---|
|  |  |  | *      Copyright:  (C) 2019 LingYun IoT System Studio | 
|---|
|  |  |  | *                  All rights reserved. | 
|---|
|  |  |  | * | 
|---|
|  |  |  | *       Filename:  tsl2561.h | 
|---|
|  |  |  | *    Description:  This head file is the Lux sensor TSL2561 API functions on RaspberryPi | 
|---|
|  |  |  | * | 
|---|
|  |  |  | *        Version:  1.0.0(04/07/19) | 
|---|
|  |  |  | *         Author:  Guo Wenxue <guowenxue@gmail.com> | 
|---|
|  |  |  | *      ChangeLog:  1, Release initial version on "04/07/19 17:42:35" | 
|---|
|  |  |  | * | 
|---|
|  |  |  | ********************************************************************************/ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #ifndef  _TSL2561_H_ | 
|---|
|  |  |  | #define  _TSL2561_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, | 
|---|
|  |  |  | }; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | extern int tsl2561_init(void); | 
|---|
|  |  |  | extern double tsl2561_get_lux(void); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | #endif   /* ----- #ifndef _TSL2561_H_  ----- */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | #define PROG_VERSION               "v1.0.0" | 
|---|
|  |  |  | #define DAEMON_PIDFILE             "/tmp/.mqtt.pid" | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int g_relay_flag = 0;  /* relay already turn on and wait to off  */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int check_set_program_running(int daemon); | 
|---|
|  |  |  | void *mqtt_sub_worker(void *args); | 
|---|
|  |  |  | void *mqtt_pub_worker(void *args); | 
|---|
|  |  |  | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | void turn_light_off(int signum) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | log_nrml("fill-in light timeout and turn light off now\n"); | 
|---|
|  |  |  | turn_relay(OFF); | 
|---|
|  |  |  | g_relay_flag = 0; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int main (int argc, char **argv) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | 
|---|
|  |  |  | int                debug = 0; | 
|---|
|  |  |  | int                opt; | 
|---|
|  |  |  | char              *progname=NULL; | 
|---|
|  |  |  | double             lux = 0.0; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | struct option long_options[] = { | 
|---|
|  |  |  | {"conf", required_argument, NULL, 'c'}, | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | install_proc_signal(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( ctx.hwconf.fillin_light ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | log_nrml("Install inbreak detected fill-in light off signal\n"); | 
|---|
|  |  |  | signal(SIGALRM, turn_light_off); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( check_set_program_running(daemon) < 0 ) | 
|---|
|  |  |  | goto OUT; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | log_nrml("Start MQTT publisher worker thread ok\n"); | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | while( ! g_signal.stop ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | msleep(1000); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( ctx.hwconf.infrared_pin ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | //log_nrml("infrared dected human incoming\n"); | 
|---|
|  |  |  | if( !g_relay_flag && infrared_detect(1500) ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | log_nrml("Someone incoming detected by infrared\n"); | 
|---|
|  |  |  | if( ctx.hwconf.inbreak_beep ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | turn_beep(ctx.hwconf.beep_times); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if( ctx.hwconf.fillin_light==FILLIN_LIGHT_ON && !g_relay_flag ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | log_nrml("Force fill-in light on and will be off in [%d] seconds\n", ctx.hwconf.light_intval); | 
|---|
|  |  |  | turn_relay(ON); | 
|---|
|  |  |  | g_relay_flag = 1; | 
|---|
|  |  |  | alarm(ctx.hwconf.light_intval); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | else if( ctx.hwconf.fillin_light==FILLIN_LIGHT_AUTO && ctx.hwconf.lux ) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | lux = tsl2561_get_lux(); | 
|---|
|  |  |  | log_nrml("TSL2516 lux sensor detect illumination intensity %.3f lux\n", lux); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //log_nrml("Main control thread continue running\n"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return 0; | 
|---|
|  |  |  | } /* ----- End of main() ----- */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int check_set_program_running(int daemon) | 
|---|
|  |  |  | { | 
|---|