Arduino PID直流电机位置控制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Arduino PID直流电机位置控制相关的知识,希望对你有一定的参考价值。

我正在做一个控制工程项目,为自动天线跟踪系统实现PID电机位置控制。该系统包含直流电机,绝对编码器和电机驱动器。

一切都按预期工作,但有一点。电机不能在0度(350 - 359,0 - 10度)附近的设定值停止。使用过的代码:

#include <PID_v1.h>
int RPWM = 5;
int LPWM = 6;
int L_EN = 7;
int R_EN = 8;
boolean pin_state[10];
byte input_pin[] = {1, 2, 3, 4, 9, 10, 11, 12, 13};
int dec_position = 0;
int dc = 0;
double kp = 50, ki = 45, kd = 2;
double input = 0, output = 0, setpoint = 0;
volatile long encoderPos = 0;
PID myPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);

void setup() {
  pinMode(L_EN, OUTPUT);
  pinMode(R_EN, OUTPUT);
  pinMode(RPWM, OUTPUT);
  pinMode(LPWM, OUTPUT);
  for (byte i = 0; i < 9; i++) {
    pinMode(input_pin[i], INPUT);
  }
  TCCR1B = TCCR1B & 0b11111000 | 1; 
  myPID.SetMode(AUTOMATIC);
  myPID.SetSampleTime(1);
  myPID.SetOutputLimits(-255, 255);          
  digitalWrite(L_EN, HIGH);
  digitalWrite(R_EN, HIGH);
}

void loop() {
  if (Serial.available() > 0) {
    String baca = Serial.readString();
    setpoint = baca.toInt();
  }
  ReadEncoder();
  input = dc;
  myPID.Compute();
  pwmOut(output);
}

void pwmOut(int out) {
  if (out > 0) {
    analogWrite(RPWM, out);//Sets speed variable via PWM
  }
  else {
    analogWrite(LPWM, abs(out));//Sets speed variable via PWM
  }
}

void ReadEncoder() {
// FOR READING ENCODER POSITION, GIVING 0-359 OUTPUT CORRESPOND TO THE ENCODER POSITION
  for (byte i = 0; i < 9; i++) {
    pin_state[i] = !(digitalRead(input_pin[i]));
  }
  dec_position = (pin_state[8] * 256) + (pin_state[7] * 128) + (pin_state[6] * 64) + (pin_state[5] * 32) + (pin_state[4] * 16) + (pin_state[3] * 8) + (pin_state[2] * 4) + (pin_state[1] * 2) + pin_state[0];
  dc = map(dec_position, 0, 500, 0, 360);
}

当设定点为10 - 350之间的值时,系统运行良好。但如果不是,电机永远不会停止旋转。

我知道问题是由于位置过冲导致编码器读取非常大的错误。

例如,如果设定值为0度,则电机旋转到达它。当“现在”位置接近0度时,电机旋转速度减慢,但系统没有超调。因此,即使1度过冲也会导致误差值为-359(设定值 - 现在位置),电机再次旋转到达所需位置。

需要帮助如何克服这个问题。抱歉英文不好。

答案

这是解决方案

double error; 
if (SP>PV) {
     if (abs(SP-PV) < abs(-360 + SP - PV)) error = SP - PV;
     else  error = -360 + SP - PV;
}
else{
     if(abs(SP-PV)< abs(360 - PV + SP)) error = SP - PV;
     else  error = 360 - SP + PV;
}

取而代之的是简单的现值减去错误的设定点。上面的代码返回从当前值到设定点的最短路径。

另一答案

我还没有读你的代码。但是,要达到“设定值”(SV),您应该为“现值”(PV)提供误差允许值(EA)

例如:EA = SV - PV。如果EA =( - 2,+ 2)度,则达到“现在位置”

并且,你不应该使用度数角度,你应该将其转换为位置(通过脉冲计算)

希望这个概念可以帮到你。

以上是关于Arduino PID直流电机位置控制的主要内容,如果未能解决你的问题,请参考以下文章

Arduino控制舵机

在线仿真Arduino 直流电机在线仿真调速控制

arduino的L298N电机驱动模块如何和直流电机接线?

在线仿真Arduino UNO PWM 控制直流电机转速

使用单电机控制 Arduino (Uno) 库控制两个步进电机

哪位大神能帮我写一个arduino 控制两个直流电机正反转,加减速和拐弯的程序啊?arduino程序,非常感谢。