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

Arduino Uno项目技术求助:按键控制伺服与真空泵逻辑实现

Arduino Uno 按键控制顺序动作与分支执行方案

硬件引脚定义(可根据实际接线调整)

部件Arduino 引脚说明
servo1(升降系统)10PWM 驱动引脚
servo2(旋转龙头)11PWM 驱动引脚
真空泵1继电器2数字输出引脚
真空泵2继电器3数字输出引脚
真空泵3继电器4数字输出引脚
真空泵4继电器5数字输出引脚
按键16内部上拉输入(按下为LOW)
按键27内部上拉输入(按下为LOW)
按键38内部上拉输入(按下为LOW)
按键49内部上拉输入(按下为LOW)

核心代码实现

#include <Servo.h>

// 舵机对象初始化
Servo servo1;
Servo servo2;

// 继电器与按键引脚数组
const int relayPins[] = {2, 3, 4, 5};
const int buttonPins[] = {6, 7, 8, 9};

// 按键防抖变量
int buttonStates[4] = {HIGH, HIGH, HIGH, HIGH};
int lastButtonStates[4] = {HIGH, HIGH, HIGH, HIGH};
unsigned long lastDebounceTimes[4] = {0, 0, 0, 0};
const unsigned long debounceDelay = 50;

// 动作参数(需根据机械结构实际调整)
const int servo2TargetAngle = 70;       // 旋转龙头目标角度
const long servo1RotateDuration = 2000; // 升降舵机单方向转动时长(控制圈数)
const long pumpRunDuration = 3000;      // 真空泵运行时长

void setup() {
  // 初始化舵机引脚
  servo1.attach(10);
  servo2.attach(11);
  
  // 初始化继电器引脚(默认低电平关闭)
  for (int i = 0; i < 4; i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], LOW);
  }
  
  // 初始化按键为内部上拉输入
  for (int i = 0; i < 4; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
  
  // 旋转龙头归位到初始角度
  servo2.write(0);
}

// 控制servo1转动指定圈数(1=正转,-1=反转)
void rotateServo1(int direction) {
  int pulseWidth = (direction == 1) ? 2000 : 1000;
  unsigned long startTime = millis();
  
  while (millis() - startTime < servo1RotateDuration) {
    servo1.writeMicroseconds(pulseWidth);
    delay(20); // 维持舵机驱动脉冲
  }
  
  // 停止舵机(输出中立脉冲)
  servo1.writeMicroseconds(1500);
}

// 执行对应按键的顺序动作
void runSequence(int buttonIndex) {
  // 步骤1:servo1正转指定圈数
  rotateServo1(1);
  
  // 步骤2:servo2转到70度并等待到位
  servo2.write(servo2TargetAngle);
  delay(500);
  
  // 步骤3:触发对应真空泵并维持运行时长
  digitalWrite(relayPins[buttonIndex], HIGH);
  delay(pumpRunDuration);
  digitalWrite(relayPins[buttonIndex], LOW);
  
  // 步骤4:servo2转回初始角度并等待到位
  servo2.write(0);
  delay(500);
  
  // 步骤5:servo1反转指定圈数归位
  rotateServo1(-1);
}

void loop() {
  // 遍历检测4个按键状态
  for (int i = 0; i < 4; i++) {
    int currentReading = digitalRead(buttonPins[i]);
    
    // 按键状态变化时重置防抖计时器
    if (currentReading != lastButtonStates[i]) {
      lastDebounceTimes[i] = millis();
    }
    
    // 防抖时间过后更新按键状态
    if (millis() - lastDebounceTimes[i] > debounceDelay) {
      if (currentReading != buttonStates[i]) {
        buttonStates[i] = currentReading;
        
        // 检测到按键按下(内部上拉模式下,按下为LOW)
        if (buttonStates[i] == LOW) {
          runSequence(i);
        }
      }
    }
    
    lastButtonStates[i] = currentReading;
  }
}

关键说明

  1. 分支逻辑实现:通过按键索引传递给runSequence函数,函数内部根据索引触发对应继电器,避免编写重复的动作代码,实现按键与真空泵的一一对应。
  2. 舵机整圈转动:MG996R默认是角度舵机,通过持续输出极限脉冲(1000us/2000us)实现连续转动,servo1RotateDuration需根据实际机械结构调整,确保转动指定圈数。
  3. 按键防抖:使用millis()实现非阻塞防抖,避免按键抖动导致误触发,同时不影响后续动作执行。
  4. 电源提醒:MG996R舵机和真空泵需外接独立电源供电,不能直接使用Arduino Uno的5V引脚,否则会因电流不足导致故障,注意电源与Arduino共地。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 15:25:39