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

Arduino如何实现按一次按键舵机动作、再按一次舵机复位

问题根因

原代码是按住生效的电平判断逻辑:循环里实时读取按键电平,检测到按键按下(低电平)就控制舵机转到180度,检测到按键松开(高电平)就立刻转回0度,没有做按键状态锁存、边沿检测和消抖处理,自然无法实现按一次切换、再按一次回位的效果。

修复思路

要实现预期的按键切换效果,需要补充三个核心逻辑:

  • 增加机械按键消抖处理,避免按键触点抖动导致的误触发
  • 检测按键按下的瞬间(下降沿信号),而非持续按住的电平状态,确保按一次只触发一次动作
  • 增加舵机状态标记位,每次检测到有效按下动作就翻转标记状态,根据标记值控制舵机停留位置,松开按键不会改变舵机当前状态
修复后可直接运行的代码
#include <Servo.h>
Servo Myservo;

// 硬件引脚定义
const int buttonPin = 2;
const int servoPin = 3;

// 运行状态变量
bool servoRunState = false;  // 舵机状态标记:false=初始0度位置,true=180度动作位置
int lastBtnLevel = HIGH;     // 记录上一次读取的按键电平,默认松开状态为高电平
unsigned long debounceTimer = 0;
const int debounceTime = 20; // 按键消抖时长20ms,可根据实际按键手感调整

void setup()
{
  pinMode(buttonPin, INPUT);
  // 如果按键没有外接上拉电阻,可将上行改为pinMode(buttonPin, INPUT_PULLUP),按键一端接2脚一端接GND即可,无需额外元件
  Myservo.attach(servoPin);
  Myservo.write(0); // 上电默认舵机停在初始位置
}

void loop()
{
  int currentBtnLevel = digitalRead(buttonPin);
  
  // 检测到电平变化就重置消抖计时器
  if (currentBtnLevel != lastBtnLevel) {
    debounceTimer = millis();
  }

  // 电平稳定超过消抖时长,判定为有效按键动作
  if ((millis() - debounceTimer) > debounceTime) {
    // 仅在按键从松开变为按下的瞬间触发状态切换
    if (currentBtnLevel == LOW && lastBtnLevel == HIGH) {
      servoRunState = !servoRunState; // 翻转舵机状态
      servoRunState ? Myservo.write(180) : Myservo.write(0);
    }
  }

  lastBtnLevel = currentBtnLevel;
}
注意事项
  • 如果按键按下触发不灵敏或者会误触发,可适当调整debounceTime的数值,一般10~50ms范围内都属于正常范围
  • 使用内部上拉输入模式时,不要接错按键接线,避免电平逻辑反了导致触发异常

内容的提问来源于stack exchange,提问作者Samuel Flores G

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:54:28