小型龙门吊PID控制:X轴定位与摆角归零的冲突解决问询
小型龙门吊PID控制摆角抑制问题
我用PID控制器控制小型龙门吊头部,已实现X、Y轴目标位置移动,但核心问题是X轴控制器与摆角(theta)控制器均向X轴电机的pin_pwm_x引脚输出信号,导致信号冲突。
当台车从X=0移动到X=10的目标位置后,吊头会呈钟摆状摆动,此时需要摆角控制器驱动台车抵消摆动,直至吊头角度归零,但当前信号输出逻辑无法实现这一需求。
- 龙门吊示意图:包含台车、吊头、X/Y轴传动机构的小型龙门吊结构示意
- X轴级联控制回路图:X轴位置控制与摆角抑制的级联控制逻辑框图
代码说明
控制小型龙门吊头部的Arduino PID控制代码逻辑如下:
- 导入必要库并定义系统连接变量;
- 配置Y轴、X轴、摆角(theta)控制器的PID整定参数;
- 创建对应PID对象;
getAngleFromHead()函数通过串口读取吊头角度传感器数据;readInput()函数读取X、Y轴位置传感器及吊头角度数据;setup()函数初始化串口、引脚模式、变量、设定值及PID配置;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
相关产品推荐
相关产品推荐

