Arduino中如何获取按钮未按下时长?超30秒触发事件
Arduino 检测按钮未按下时长并触发事件的解决方案
核心思路
利用Arduino的millis()函数获取系统运行的毫秒数,记录按钮进入未按下状态的起始时间点,每次循环计算当前时间与该起始点的差值。当差值超过30000毫秒(30秒)时,执行预设的指定事件。同时加入按钮防抖逻辑,避免机械抖动导致的误判,还要防止事件重复触发。
完整代码示例
// 定义按钮引脚 const int buttonPin = 2; // 记录按钮未按下状态的起始时间 unsigned long lastActiveTime = 0; // 触发阈值:30秒 = 30000毫秒 const unsigned long timeoutThreshold = 30000; // 按钮状态变量 int currentBtnState; int lastBtnState = HIGH; // 防抖延时(过滤机械抖动,建议10-50ms) const unsigned long debounceDelay = 30; // 事件触发标记,避免重复执行 bool eventFired = false; void setup() { pinMode(buttonPin, INPUT_PULLUP); // 使用内部上拉电阻,未按下时为HIGH Serial.begin(9600); // 初始化起始时间为当前系统时间 lastActiveTime = millis(); } void loop() { // 读取按钮状态并做防抖处理 int rawReading = digitalRead(buttonPin); if (rawReading != lastBtnState) { lastActiveTime = millis(); } if (millis() - lastActiveTime > debounceDelay) { currentBtnState = rawReading; } lastBtnState = rawReading; // 核心逻辑判断 if (currentBtnState == LOW) { // 按钮被按下,重置计时和事件标记 lastActiveTime = millis(); eventFired = false; Serial.println("按钮已按下,重置超时计时"); } else { // 按钮未按下,计算已持续时长 unsigned long elapsed = millis() - lastActiveTime; if (elapsed > timeoutThreshold && !eventFired) { // 超时且未触发过事件,执行指定操作 executeTargetEvent(); eventFired = true; } } // 这里可以添加其他并行任务代码,不会被阻塞 } // 自定义的指定事件函数,按需修改逻辑 void executeTargetEvent() { Serial.println("按钮未按下超过30秒,执行指定事件"); // 示例操作:点亮LED/发送指令等 // digitalWrite(ledPin, HIGH); // mySerial.println("TIMEOUT"); }
关键细节解释
- INPUT_PULLUP配置:按钮引脚设为
INPUT_PULLUP后,未按下时引脚默认是高电平,按下时接地变为低电平,无需额外外接下拉电阻,简化硬件电路。 - 防抖处理:按钮机械结构会导致按下/松开时出现短暂电平波动,通过
debounceDelay过滤这段抖动时间,确保状态判断准确。 - 防重复触发:
eventFired标记确保超时事件只会触发一次,直到按钮被按下重置标记,避免循环中反复执行事件。 - 非阻塞计时:使用
millis()而非delay(),程序可以在计时的同时处理其他任务,保证Arduino的多任务能力。
内容的提问来源于stack exchange,提问作者Priyansh Maheshwari
相关产品推荐
相关产品推荐

