自走車紅外線循跡

Posted on Sat, Apr 9, 2022 Arduino C++

使用二路紅外線避障模組來做循線行進。並利用PID控制來增進控制的穩定度和流暢度。但結果沒有調整到很理想的狀態。我認為有以下幾個原因:

雖然有事先測量過使兩邊的轉速差不多,但因為沒有用輪子上紅外線的速度回饋,所以誤差還是存在,進而影響到PID的穩定性。

在遇到弧度較大的彎曲時,如果還來不及修正就讓兩個避障模組偵測到白色,以我的程式的算法就會認定成走在直線上而出軌,因此增加兩路變成四路就能有更長的修正時間就能解決問題。當然改一下感測器的輸入算法或繼續調整PID的參數也是可以,但我懶。

應該還有其他原因,但我目前想不到,就先這樣。

程式碼:

#include <AFMotor.h>
AF_DCMotor motorLeft(2);
AF_DCMotor motorRight(3);

int DigitalPin1 = A5;   
int DigitalPin2 = A2;
int cnt1 = 0;  
int last1 = 0;
int cnt2 = 0;  
int last2 = 0;
unsigned long timer;
unsigned long dt;
float rpm;
float power;
float intergral_bias[2], last_bias[2];

const int init_speed = 150;

const float Kp = 3.3;
const float Ki = 0.002;
const float Kd = 2.2;

int PID_motor(int rpm,int target,int i){
  float bias = -1*(rpm-target);
  intergral_bias[i] = intergral_bias[i]*0.7 + bias;
  float power = Kp*bias + Ki*intergral_bias[i] + -1*Kd*(bias-last_bias[i])+init_speed;
  if(power > 255){
    power = 255;
  }
  if(power < 10){
    power = 10;
  }
  last_bias[i] = bias;
  Serial.println(power);
  return power;
}

void setup()
{
  Serial.begin(115200);
  pinMode(DigitalPin1, INPUT);  
  pinMode(DigitalPin2, INPUT); 
  motorLeft.setSpeed(init_speed);
  motorLeft.run(FORWARD);       
  //motorRight.setSpeed(init_speed);
  //motorRight.run(FORWARD);       
}
void loop()
{
  timer = millis();
  //Serial.println(timer); 
  while(cnt1 < 10){
  boolean D_val1 = digitalRead(DigitalPin1);
  //boolean D_val2 = digitalRead(DigitalPin2);
  if(abs(last1 - D_val1) == 1){
    cnt1++;
  }
  //if(abs(last2 - D_val2) == 2){
  //  cnt2++;
  //}
  last1 = D_val1;
  //last2 = D_val2;
  }
  dt = millis() - timer;
  rpm = (60000/float(dt));
  //Serial.println("rpm= ");
  Serial.print(rpm); 
  Serial.print(" "); 
  cnt1 = 0;
  power = PID_motor(rpm,80,0);
  motorRight.setSpeed(power);
}

影片:

自走車紅外線循跡