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

小型龙门吊PID控制:X轴定位与摆角归零的冲突解决问询

小型龙门吊PID控制摆角抑制问题

我用PID控制器控制小型龙门吊头部,已实现X、Y轴目标位置移动,但核心问题是X轴控制器与摆角(theta)控制器均向X轴电机的pin_pwm_x引脚输出信号,导致信号冲突。
当台车从X=0移动到X=10的目标位置后,吊头会呈钟摆状摆动,此时需要摆角控制器驱动台车抵消摆动,直至吊头角度归零,但当前信号输出逻辑无法实现这一需求。

  • 龙门吊示意图:包含台车、吊头、X/Y轴传动机构的小型龙门吊结构示意
  • X轴级联控制回路图:X轴位置控制与摆角抑制的级联控制逻辑框图

代码说明

控制小型龙门吊头部的Arduino PID控制代码逻辑如下:

  1. 导入必要库并定义系统连接变量;
  2. 配置Y轴、X轴、摆角(theta)控制器的PID整定参数;
  3. 创建对应PID对象;
  4. getAngleFromHead()函数通过串口读取吊头角度传感器数据;
  5. readInput()函数读取X、Y轴位置传感器及吊头角度数据;
  6. setup()函数初始化串口、引脚模式、变量、设定值及PID配置;
  7. loop()函数为主执行循环,完成输入读取、PID计算、电机驱动及调试信息输出。

代码实现

// Include libraries
#include <Arduino.h>
#include "pinDefinitions.h"
#include <PID_v1.h>

// Define Variables we'll be connecting to
double Setpoint_y, Input_y, Output_y,
    Setpoint_x, Input_x, Output_x,
    Setpoint_theta, Input_theta, Output_theta;

// Specify the links and initial tuning parameters
double Kp_y = 32.4,
       Ki_y = 0,     
       Kd_y = 12.96,     
       kg_y = 1,

       Kp_x = 2.4,
       Ki_x = 0,
       Kd_x = 1.92,
       kg_x = 1,
       
       Kp_theta = 22.6,
       Ki_theta = 0, 
       Kd_theta = 11.3, 
       kg_theta = 1;

PID_v1 yPID(&Input_y, &Output_y, &Setpoint_y, Kp_y *kg_y, Ki_y *kg_y, Kd_y *kg_y, DIRECT);
PID_v1 xPID(&Input_x, &Output_x, &Setpoint_x, Kp_x *kg_x, Ki_x *kg_x, Kd_x *kg_x, DIRECT);
PID_v1 thetaPID(&Input_theta, &Output_theta, &Setpoint_theta, Kp_theta *kg_theta, Ki_theta *kg_theta, Kd_theta *kg_theta, DIRECT);

float getAngleFromHead()
{
  float angle;
  if (Serial3.available() > 0)
  {
    String angleData = Serial3.readStringUntil('\n');
    angle = angleData.toFloat();
    // Serial.println(angle);
  }
  return angle;
}

// Function that reads the inputs to the system
void readInput()
{
  Input_y = analogRead(pin_pos_y); 
  Input_x = analogRead(pin_pos_x);

  Input_theta = getAngleFromHead();

  // Sanity check angle data
  while (Input_theta > 90 || Input_theta < -90)
  {
    digitalWrite(pin_enable_x, LOW); // Stop motors!
    digitalWrite(pin_enable_y, LOW);
    Serial.println("//Insane angle data");
    Input_theta = getAngleFromHead();
  }
}

void setup()
{
  Serial.begin(115200);
  Serial3.begin(9600);

  ; // Set input pinMode
  pinMode(pin_pos_x, INPUT);
  pinMode(pin_pos_y, INPUT);

  // Set output pinMode
  pinMode(pin_enable_x, OUTPUT);
  pinMode(pin_enable_y, OUTPUT);
  pinMode(pin_pwm_x, OUTPUT);
  pinMode(pin_pwm_y, OUTPUT);

  // Initialize the variables we're linked to
  Input_y = analogRead(pin_pos_y);
  Input_x = analogRead(pin_pos_x);

  Setpoint_y = 400;
  Setpoint_x = 300;
  Setpoint_theta = 0;

  yPID.SetSampleTime(10);  //Sample rate expressed in ms, 10ms = 100 Hz
  xPID.SetSampleTime(10);
  thetaPID.SetSampleTime(1); //Angle sampling rate is 10x times faster than xPID

  xPID.SetOutputLimits(255 * 0.1, 255 * 0.9); // PWM Range for the specific motors
  yPID.SetOutputLimits(255 * 0.1, 255 * 0.9);
  thetaPID.SetOutputLimits(255 * 0.1, 255 * 0.9);

  // turn the PID on
  yPID.SetMode(AUTOMATIC);
  xPID.SetMode(AUTOMATIC);
  thetaPID.SetMode(AUTOMATIC);

  Serial.println("Setup done!");
}

void loop()
{
  readInput();
  yPID.Compute();
  xPID.Compute();
  thetaPID.Compute();

  digitalWrite(pin_enable_y, HIGH); //Turns on motor
  digitalWrite(pin_enable_x, HIGH);

  analogWrite(pin_pwm_y, Output_y);
  analogWrite(pin_pwm_x, Output_x);
  analogWrite(pin_pwm_x, Output_theta); // Pin_pwm_x is being overwritten, not so good. 

  Serial.println("PID Input_x: " + String(Input_x) + ", PID Setpoint_x: " + String(Setpoint_x) + ", PID Output_x: " + String(Output_x) + ", Angle: " + String(Input_theta) + ", Kp_y: " + String(Kp_y));
}

已尝试方案

试过将X轴PID输出与摆角PID输出做加减运算后输出到pin_pwm_x,比如analogWrite(pin_pwm_x, Output_x-Output_theta);或analogWrite(pin_pwm_x, Output_theta-Output_x);,但未取得有效效果。

目标效果

实现无摆动的快速定位,摆角抑制参考钟摆式系统的PID控制逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:52:02