Add tsl2561 code, and test force fill-in light ok
6 files modified
2 files added
| | |
| | | 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) |
| | | { |