esp8266 人体感应
esp8266 人体感应
最近在淘宝买了一个人体感应模块,用来做人体感应,感应到有人活动的时候,串口输出,更高级的可以发送邮件,微信等。
人体感应模块介绍
淘宝买的是HC-SR312微型人体感应模块,是基于被动式人体红外线技术的数字智能自动控制产品 灵敏度高,可靠性强,广泛应用于各类自动感应电器设备。

功能特点
可重复触发方式:即感应输出高电平后,在延时时间段内,如果有人体在其感应范围活动,其输出将一直保持高电平,直到人离开后延时,才变为低电平(即:感应模块检测到人体的每一次活动后会自动顺延一个延时时间段,并且以最后一次活动的时间为延时时间的起始点)。
看手册这个延迟时间是2s。
esp8266 和人体感应模块连接图
人体感应模块数据口输出连接到GPIO12 D6口
nodemcu IO 电路图

最简单的代码
int PIR_sensor = 12; //PIR OUTPUT端口 D6 GPIO12int LED = 2; //LED端口 D4 GPIO2int val = 0; void setup(){ pinMode(PIR_sensor INPUT); //设置PIR端口为输入模式 pinMode(LED OUTPUT); //设置LED端口为输出模式 Serial.begin(9600); //设置串口波特率为9600} void loop(){ val = digitalRead(PIR_sensor); //读取PIR端口值,只有0或者1 delay(2000); //延迟2s if (val == HIGH)// 如果读取到的高电平值,表示感应到人, { digitalWrite(LED HIGH); Serial.println("detect human!!!!"); } else { digitalWrite(LED LOW); //等于0 表示没有感应到人 }}
上面的代码虽然能正常工作,但是检测不是非常精确,而且可以看出来是阻塞的,如果想加什么功能,每次都要sleep 2s。那有没更好的办法呢?自然很容易想到定时器和中断来实现。
定时器和中断实现
#define timeSeconds 2// PIR OUTPUT端口 D6 GPIO12 LED端口 D4 GPIO2const int LED = 2;const int PIR_sensor = 12;// 获取当前时间unsigned long now = millis();// 上一次触发中断的时间unsigned long lastTrigger = 0;// 是否开启计时器的标志boolean startTimer = false;// 定时时间周期 2sunsigned long detectDuration = 1000 * timeSeconds;// 检测人体感应的中断触发函数,将LED置为高电平,且给开启计时器的标志startTimer置为true 表示开始计时,给lastTrigger赋值触发中断的时间ICACHE_RAM_ATTR void detectHuman() { Serial.println("Human Detected!!!"); digitalWrite(LED HIGH); startTimer = true; lastTrigger = millis();}void setup() { Serial.begin(9600); // 将人体感应数据口连接的IO口设置为输入上拉模式,使引脚即使在未连接外部组件的时候也能保持确定的逻辑电平。 pinMode(PIR_sensor INPUT_PULLUP); // 将人体感应数据口连接的IO口设置为中断模式 赋值中断函数和将中断模式设置为RISING(当引脚由低电平变为高电平时,触发中断) attachInterrupt(digitalPinToInterrupt(PIR_sensor) detectHuman RISING); pinMode(LED OUTPUT); digitalWrite(LED LOW);}void loop() { // 获取当前时间 now = millis(); // 如果已经开始了计时,且当前时间减去上一次触发中断时间大于人体感应模块检测的时间周期 2s,将LED电平置为低,且将计时器标志置为false,等待下一次中断 if(startTimer && (now - lastTrigger > detectDuration)) { Serial.println("Human detected stopped..."); digitalWrite(LED LOW); startTimer = false; }}
上面的代码利用中断,大大地提高了人体检测模块的检测效率和准确性。并用软件实现了2s的软定时器,定时将LED端口置为低电平,好观察效果。