基于PID算法的循迹小车

基于PID算法的循迹小车这一期为创客们带来基于PID算法的循迹小车制作1.标准赛道示意图:(该赛道包含了:左直角、右直角、十字路口等路况)2.灰度传感器安装示意图:(可根据实际情况调节各传感器之间的间距)3.硬件原理图:4.控制逻辑:5.程序如下:#defineleftA_PIN7#defineleftB_PIN6#defineleft_Pwm_PIN5#defineSTBY…

这一期为创客们带来基于PID算法的循迹小车制作

1.标准赛道示意图:
(该赛道包含了:左直角、右直角、十字路口等路况)
在这里插入图片描述
2.灰度传感器安装示意图:
(可根据实际情况调节各传感器之间的间距)
在这里插入图片描述
3.硬件原理图:
在这里插入图片描述
4.控制逻辑:
在这里插入图片描述
5.程序如下:

#define leftA_PIN 7
#define leftB_PIN 6
#define left_Pwm_PIN 5

#define STBY 8

#define rightA_PIN 9
#define rightB_PIN 10
#define right_Pwm_PIN 11

#define leftA_track_PIN 2
#define leftB_track_PIN 3
#define middle_track_PIN 4
#define rightA_track_PIN 12
#define rightB_track_PIN 13
 
float Kp = 10, Ki = 0.5, Kd = 0;                      //pid弯道参数参数 
float error = 0, P = 0, I = 0, D = 0, PID_value = 0;  //pid直道参数 
float decide = 0;                                     //元素判断
float previous_error = 0, previous_I = 0;             //误差值 
int sensor[5] = { 
   0, 0, 0, 0, 0};                      //5个传感器数值的数组 
static int initial_motor_speed = 60;                  //初始速度 
 
void read_sensor_values(void);                        //读取初值 
void calc_pid(void);                                  //计算pid 
void motor_control(void);                             //电机控制 
void motor_pinint( );     //引脚初始化
void _stop();             //停车

void setup()
{ 
   
  Serial.begin(9600); //串口波特率115200(PC端使用)
  track_pinint();     //循迹引脚初始化
  motor_pinint();        //电机引脚初始化
 
}
void loop()
{ 
   
    read_sensor_values();         //循迹小车
    calc_pid();
    motor_control();
}
 
/*循迹模块引脚初始化*/
void track_pinint()
{ 
    
  pinMode (leftA_track_PIN, INPUT); //设置引脚为输入引脚
  pinMode (leftB_track_PIN, INPUT); //设置引脚为输入引脚
  pinMode (middle_track_PIN, INPUT);//设置引脚为输入引脚
  pinMode (rightA_track_PIN, INPUT); //设置引脚为输入引脚
  pinMode (rightB_track_PIN, INPUT); //设置引脚为输入引脚
}
 
/*电机引脚初始化*/
void motor_pinint()
{ 
   
  pinMode (leftA_PIN, OUTPUT); //设置引脚为输出引脚
  pinMode (leftB_PIN, OUTPUT); //设置引脚为输出引脚
  pinMode (left_Pwm_PIN, OUTPUT); //设置引脚为输出引脚
  
  pinMode (STBY, OUTPUT); //设置引脚为输出引脚
  
  pinMode (rightA_PIN, OUTPUT); //设置引脚为输出引脚
  pinMode (rightB_PIN, OUTPUT); //设置引脚为输出引脚
  pinMode (right_Pwm_PIN, OUTPUT); //设置引脚为输出引脚
}
 
//停车函数
void _stop()
{ 
   
    digitalWrite(leftA_PIN, LOW);
    digitalWrite(leftB_PIN, LOW);
    analogWrite(left_Pwm_PIN,255);   //左轮静止不动
      
    digitalWrite(rightA_PIN, LOW);
    digitalWrite(rightB_PIN, LOW);
    analogWrite(right_Pwm_PIN,255);   //右轮静止不动
}

//速度设定范围(-255,255)
void motorsWrite(int speedL, int speedR)
{ 
   
  digitalWrite(STBY, HIGH);
  
  if (speedR > 0) 
  { 
   
    digitalWrite(rightA_PIN, HIGH);
    digitalWrite(rightB_PIN, LOW);
    analogWrite(right_Pwm_PIN,speedR);
    
  } 
  else 
  { 
   
    digitalWrite(rightA_PIN, LOW);
    digitalWrite(rightB_PIN, HIGH);
    analogWrite(right_Pwm_PIN,-speedR);
  }
 
  if (speedL > 0) 
  { 
   
    digitalWrite(leftA_PIN, HIGH);
    digitalWrite(leftB_PIN, LOW);
    analogWrite(left_Pwm_PIN,speedL);
  }
  else 
  { 
   
    digitalWrite(leftA_PIN, LOW);
    digitalWrite(leftB_PIN, HIGH);
    analogWrite(left_Pwm_PIN,-speedL);
  }
}

//速度设定范围(-100,100)
void motorsWritePct(int speedLpct, int speedRpct) 
{ 
   
  //speedLpct, speedRpct ranges from -100 to 100
  motorsWrite(speedLpct * 2.55, speedRpct * 2.55);
}

void motorsStop() 
{ 
   
    digitalWrite(leftA_PIN, LOW);
    digitalWrite(leftB_PIN, LOW);
    analogWrite(left_Pwm_PIN,255);   //左轮静止不动
      
    digitalWrite(rightA_PIN, LOW);
    digitalWrite(rightB_PIN, LOW);
    analogWrite(right_Pwm_PIN,255);   //右轮静止不动
}
 
void read_sensor_values()
{ 
   
  sensor[0] = digitalRead(leftA_track_PIN);
  sensor[1] = digitalRead(leftB_track_PIN);
  sensor[2] = digitalRead(middle_track_PIN);
  sensor[3] = digitalRead(rightA_track_PIN);
  sensor[4] = digitalRead(rightB_track_PIN);
  
    if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 1)) 
   { 
   
      decide = 1;//十字路口 1 1 1 1 1 直行
   } 
   
    else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 0)) 
   { 
   
      decide = 1;//十字路口 0 1 1 1 0 直行
   }
   
    else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 1)) 
   { 
   
      decide = 2;//90度路口 0 0 1 1 1 右转90度
   } 
   
    else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 0)) 
   { 
   
      decide = 2;//90度路口 0 0 1 1 0 右转90度 
   } 
   
   else if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0))
   { 
   
      decide = 3;//90度路口 1 1 1 0 0 左转90度 
   } 
   
   else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0))
   { 
   
      decide = 3;//90度路口 0 1 1 0 0 左转90度 
   }
   
    else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0))
   { 
   
      decide = 3;//向上锐角 0 1 1 0 0 向上锐角 
   } 
   
    else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 1))
   { 
   
      error = 2;// 0 0 0 0 1
   }
   
    else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 1) && (sensor[4] == 0))
   { 
   
      error = 1;// 0 0 0 1 0
   } 
   
    else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0))
   { 
   
      error = 0;// 0 0 1 0 0
   }
   
    else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0))
   { 
   
      error = -1;// 0 1 0 0 0
   } 
   
    else if ((sensor[0] == 1) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0))
   { 
   
      error = -2;// 1 0 0 0 0
   } 
   
    else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0))
   { 
   
      if (error == -2) 
      { 
   // 0 0 0 0 0
        error = -3;
      }
      else
      { 
   
        error = 3;
      }
    }
}

void calc_pid()
{ 
   
  P = error;
  I = I + error;
  D = error - previous_error;
 
  PID_value = (Kp * P) + (Ki * I) + (Kd * D);
 
  previous_error = error;
}

void motor_control()
{ 
   
  int left_motor_speed = initial_motor_speed + PID_value;
  int right_motor_speed = initial_motor_speed + PID_value;
  
  if(left_motor_speed < -255)
  { 
   
    left_motor_speed = -255;
  }
  
  if(left_motor_speed > 255)
  { 
   
    left_motor_speed = 255;
  }
  
  motorsWrite(left_motor_speed,right_motor_speed);
 
  Serial.print("move_A: ");
  Serial.print(left_motor_speed, OCT);
  Serial.print(" move_B: ");
  Serial.print(right_motor_speed, OCT);
  Serial.print(" error: ");
  Serial.print(error, OCT);
  Serial.print(" P: ");
  Serial.print(Kp, OCT);
  Serial.print(" PID_value: ");
  Serial.print(PID_value, OCT);
  Serial.println();
} 

传送门:https://blog.csdn.net/qq_38351824/article/details/81275262
详情请关注亿航创客官方抖音账号:EhangGroup

今天的文章基于PID算法的循迹小车分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/27897.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注