You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将按钮集成到舵机定时控制循环中按钮失效问题求助

问题根因

  • 核心问题是使用了delay()阻塞函数:代码在执行delay(18000)和delay(6000)的过程中,程序完全暂停运行,不会读取按钮状态,所以按钮触发逻辑根本没有机会执行,自然无响应。
  • 按钮逻辑不符合需求:当前代码写的是按钮按下时切换舵机角度,不是你需要的「按住转180°、松开回0°」的效果。
  • 定时时长不符合需求:你需要的24小时间隔对应毫秒值为24*60*60*1000 = 86400000,当前代码写的18000仅为18秒。

解决方案

改用非阻塞的millis()计时替代delay(),程序空闲时持续检测按钮状态,同时满足定时触发和按钮触发两个需求,修正后代码如下:

#include <Servo.h>
Servo myservo;
const int BUTTON_PIN = 8;
const int SERVO_PIN  = 9;

// 定时相关参数
const unsigned long OPEN_INTERVAL = 24UL * 60 * 60 * 1000; // 24小时间隔,单位毫秒
const unsigned long OPEN_DURATION = 6000; // 开门持续6秒
unsigned long lastOpenTime = 0;
bool isTimingOpen = false;

void setup(){
  myservo.attach(SERVO_PIN);
  Serial.begin(9600); 
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  myservo.write(0);
} 
  
void loop(){
  unsigned long currentMillis = millis();

  // 优先检测按钮状态
  int buttonState = digitalRead(BUTTON_PIN);
  if(buttonState == LOW){ // 按钮按下(INPUT_PULLUP模式下按下为低电平)
    myservo.write(180);
    // 按下按钮时重置定时计时,避免刚松开就触发定时开门
    lastOpenTime = currentMillis;
    isTimingOpen = false;
  }else{
    // 按钮松开时,执行定时逻辑
    if(!isTimingOpen){
      // 到了开门时间
      if(currentMillis - lastOpenTime >= OPEN_INTERVAL){
        myservo.write(180);
        isTimingOpen = true;
        lastOpenTime = currentMillis;
      }else{
        myservo.write(0);
      }
    }else{
      // 开门时间到了6秒,关门
      if(currentMillis - lastOpenTime >= OPEN_DURATION){
        myservo.write(0);
        isTimingOpen = false;
        lastOpenTime = currentMillis;
      }
    }
  }
}

代码说明

  • 用millis()记录时间戳计算时间差,全程无阻塞,程序每轮循环都会检测按钮状态,按钮响应无延迟。
  • 按钮优先级高于定时,按住按钮立即开门,松开立即回到关门状态,同时会重置定时计时,避免和定时逻辑冲突。
  • 定时参数可以按需修改,默认24小时间隔开门6秒符合你的需求。

内容的提问来源于stack exchange,提问作者Matthew Kerry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 20:09:03