基于millis()的延时继电器求助:添加非阻塞1分钟延时
Arduino非阻塞延时实现:继电器延时关闭方案
要解决你的需求,我们用Arduino的millis()函数实现非阻塞计时——这是替代delay()避免程序卡死的标准做法。核心思路是记录延时启动的时间戳,每次循环检查是否达到设定时长,同时在重新检测到运动时立即终止计时流程。
修改后的完整代码
// 补全原代码中未定义的RED引脚,可根据实际硬件调整引脚号 int RED = 19; int Green = 18; int Relay = 12; int Input = 4; int state = LOW; int val = 0; // 非阻塞延时相关变量 unsigned long relayOffDelayStart = 0; // 记录延时开始的时间戳 const unsigned long RELAY_OFF_DELAY = 60000; // 1分钟延时,单位:毫秒 bool waitingToTurnOffRelay = false; // 标记是否处于等待关闭继电器的状态 void setup() { pinMode(RED, OUTPUT); pinMode(Green, OUTPUT); pinMode(Relay, OUTPUT); pinMode(Input, INPUT_PULLUP); Serial.begin(9600); } void loop(){ val = digitalRead(Input); if (val == HIGH) { // 检测到运动:立即恢复继电器和LED状态,终止延时流程 digitalWrite(RED, LOW); digitalWrite(Green, HIGH); digitalWrite(Relay, HIGH); // 重置延时标记,取消之前的关闭倒计时 waitingToTurnOffRelay = false; if (state == LOW) { Serial.println("Motion detected!"); state = HIGH; } // 原代码的防抖短延时,若要完全无阻塞可替换为millis防抖逻辑 delay(100); } else { // 未检测到运动:先切换LED状态 digitalWrite(RED, HIGH); digitalWrite(Green, LOW); if (state == HIGH) { // 刚从运动状态切换到无运动,启动关闭继电器的计时 Serial.println("Motion stopped!"); state = LOW; relayOffDelayStart = millis(); // 记录当前时间戳 waitingToTurnOffRelay = true; // 标记进入等待状态 } // 检查是否满足延时关闭条件 if (waitingToTurnOffRelay && (millis() - relayOffDelayStart >= RELAY_OFF_DELAY)) { digitalWrite(Relay, LOW); // 延时1分钟后关闭继电器 waitingToTurnOffRelay = false; // 结束等待状态 delay(20); // 原代码的短延时,不影响整体非阻塞逻辑 } // 原代码的delay(700)若为防抖用途,建议替换为millis实现非阻塞防抖 // delay(700); } }
关键逻辑说明
- 非阻塞计时:通过
millis()获取当前系统运行时间,对比延时起始时间戳判断是否达到1分钟,整个过程不会暂停程序,其他代码可正常执行。 - 延时终止:再次检测到运动时,直接将
waitingToTurnOffRelay设为false,终止关闭继电器的计时流程。 - 状态切换处理:仅当从运动状态切换到无运动状态时才启动计时,避免重复触发延时。
内容的提问来源于stack exchange,提问作者ali arif
相关产品推荐
相关产品推荐

