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
相关产品推荐
相关产品推荐

