From 55f465be474c54edbceb3c6013ae629e0e0323d8 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Wed, 31 Jul 2019 16:26:46 +0800 Subject: [PATCH] Add tsl2561 code, and test force fill-in light ok --- mqttd/etc/conf.h | 2 mqttd/hal/hal.c | 36 +++++- mqttd/hal/tsl2561.c | 112 ++++++++++++++++++++++ mqttd/etc/conf.c | 3 mqttd/hal/tsl2561.h | 41 ++++++++ mqttd/hal/hal.h | 7 + mqttd/etc/mqttd.conf | 3 mqttd/main.c | 45 ++++++++ 8 files changed, 238 insertions(+), 11 deletions(-) diff --git a/mqttd/etc/conf.c b/mqttd/etc/conf.c index 4afe90b..d9df566 100644 --- a/mqttd/etc/conf.c +++ b/mqttd/etc/conf.c @@ -179,6 +179,9 @@ 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); } diff --git a/mqttd/etc/conf.h b/mqttd/etc/conf.h index 8a9c871..574633b 100644 --- a/mqttd/etc/conf.h +++ b/mqttd/etc/conf.h @@ -63,9 +63,9 @@ /* 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; diff --git a/mqttd/etc/mqttd.conf b/mqttd/etc/mqttd.conf index 0436a3b..2675fbd 100644 --- a/mqttd/etc/mqttd.conf +++ b/mqttd/etc/mqttd.conf @@ -39,6 +39,9 @@ # 如果探测到人来了是否通过继电器控制灯泡, 0:不补光 1:补光 2:根据光强传感器的信息自动补光,如果光强传感器不在则补光 fillin_light=2 +# 继电器补光时长, 单位秒. 红外探测到人后电平为此时间大概是35秒左右 +light_intval=35 + [logger] diff --git a/mqttd/hal/hal.c b/mqttd/hal/hal.c index 4840944..527d6f9 100644 --- a/mqttd/hal/hal.c +++ b/mqttd/hal/hal.c @@ -42,15 +42,21 @@ 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; } @@ -98,16 +104,32 @@ 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) diff --git a/mqttd/hal/hal.h b/mqttd/hal/hal.h index 027a078..37e1510 100644 --- a/mqttd/hal/hal.h +++ b/mqttd/hal/hal.h @@ -21,6 +21,7 @@ #include "ds18b20.h" #include "sht20.h" +#include "tsl2561.h" #define OFF 0 #define ON 1 @@ -37,7 +38,11 @@ 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_ ----- */ diff --git a/mqttd/hal/tsl2561.c b/mqttd/hal/tsl2561.c new file mode 100644 index 0000000..c83501f --- /dev/null +++ b/mqttd/hal/tsl2561.c @@ -0,0 +1,112 @@ +/********************************************************************************* + * 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; +} + diff --git a/mqttd/hal/tsl2561.h b/mqttd/hal/tsl2561.h new file mode 100644 index 0000000..455495f --- /dev/null +++ b/mqttd/hal/tsl2561.h @@ -0,0 +1,41 @@ +/******************************************************************************** + * 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_ ----- */ + diff --git a/mqttd/main.c b/mqttd/main.c index be26876..dd643df 100644 --- a/mqttd/main.c +++ b/mqttd/main.c @@ -29,6 +29,8 @@ #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); @@ -49,6 +51,12 @@ 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) { @@ -61,6 +69,7 @@ int debug = 0; int opt; char *progname=NULL; + double lux = 0.0; struct option long_options[] = { {"conf", required_argument, NULL, 'c'}, @@ -121,6 +130,12 @@ 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; @@ -140,10 +155,37 @@ } 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"); } @@ -154,7 +196,6 @@ return 0; } /* ----- End of main() ----- */ - int check_set_program_running(int daemon) { -- Gitblit v1.9.1