一、所需元件
Arduino板子(Uno);电机驱动模块LM298(这个型号无所谓明白端口含义就行);TCRT5000寻迹传感器四个,四个普通的小的直流电机 等等
二、元器件的详细介绍
额·····其实还是蛮多元件需要介绍的,但是之前做小车的图片什么的都不在手上现在,我这篇博文主要讲的是代码部分(代码已经亲测过没问题的了),要是新入门的需要了解接线什么的建议换一篇文章看,如果已经接好线的就等优质代码的,请留步!!!!
三、接线和拼装(略)
直接上跑起来的视频:
以上是原视频(1.0倍速)跑起来的GIF:经亲测,峰值速度达到3.1s/圈,能稳定跑>=8圈。
四、上代码:
#define leftA_PIN 9 //16\160\100-4.6-4.7=20/180/3k=22/180/3k;24/190/3k-4.4-4.5=27/200/3k=30/210/3k;33/220/3k-4.3-4.4=35/230/3k=45.5/240/3k;
#define leftB_PIN 6 //满电后的与上是不一样的,现在测试状态下:15/100-19/120-21.22/140-25/160-28.5/180-30/200-
#define righA_PIN 3 //新车型:15/100-20/120-
#define righB_PIN 5 //I=-0.5~17/140-能在五秒以内
#define leftA_track_PIN 2 //1-38/230/550-最终版!!!!!四圈均速3.1011秒
#define leftB_track_PIN 7
#define middle_track_PIN 8
#define righA_track_PIN 12
#define righB_track_PIN 13
float Kp = 38, Ki =0, Kd = 550; //pid弯道参数参数
float error = 0, P = 0, I = 0, D = 0, PID_value = 0;//pid直道参数
float previous_error = 0, previous_I = 0; //误差值
int sensor[5] = {0, 0, 0, 0, 0}; //
//5个传感器数值的数组
static int initial_motor_speed = 230; //初始速度
void read_sensor_values(void); //读取初值
void calc_pid(void); //计算pid
void motor_control(void); //电机控制
void track_pinint( ); //引脚-输入初始化
void motor_pinint( ); //引脚-输出初始化
void setup()
{
Serial.begin(9600); //串口波特率115200(PC端使用)
track_pinint( ); //循迹引脚初始化
motor_pinint(); //电机引脚初始化
}
void loop()
{
read_sensor_values(); //循迹小车
calc_pid(); //计算pid
motor_control(); //电机控制
}
/*循迹模块引脚初始化*/
void track_pinint( ) //引脚初始化
{
pinMode (leftA_track_PIN, INPUT); //设置引脚为输入引脚
pinMode (leftB_track_PIN, INPUT); //设置引脚为输入引脚
pinMode (middle_track_PIN, INPUT);//设置引脚为输入引脚
pinMode (righA_track_PIN, INPUT); //设置引脚为输入引脚
pinMode (righB_track_PIN, INPUT); //设置引脚为输入引脚
}
void motor_pinint( )
{
pinMode (leftA_PIN, OUTPUT); //设置引脚为输出引脚
pinMode (leftB_PIN, OUTPUT); //设置引脚为输出引脚
pinMode (righA_PIN, OUTPUT); //设置引脚为输出引脚
pinMode (righB_PIN, OUTPUT); //设置引脚为输出引脚
}
//速度设定范围(-255,255)
void motorsWrite(int speedL, int speedR)
{
if (speedL > 0)
{
analogWrite(leftA_PIN, speedL);
analogWrite(leftB_PIN, 0);
}
else
{
analogWrite(leftA_PIN, 0);
analogWrite(leftB_PIN, -speedL);
}
if (speedR > 0)
{
analogWrite(righA_PIN, speedR);
analogWrite(righB_PIN, 0);
}
else
{
analogWrite(righA_PIN, 0);
analogWrite(righB_PIN, -speedR);
}
}
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(righA_track_PIN);
sensor[4] = digitalRead(righB_track_PIN);
if (sensor[0] == 0 && sensor[1] != 0 && sensor[2] != 0 && sensor[3] != 0 && sensor[4] != 0)
{
error = -4;//01111只剩最左边压线了,要最大量的往左转,往左转-4
}
else if (sensor[0] == 0 && sensor[1] == 0 && sensor[2] != 0 && sensor[3] != 0 && sensor[4] != 0)
{
error = -3;//00111左边两个都压线,中幅度往左转-3
}
else if (sensor[1] == 0 && sensor[0] != 0 && sensor[2] != 0 && sensor[3] != 0 && sensor[4] != 0)
{
error = -2;//10111就剩左2的压线,往左拐弯,这个才是关键左转-2?
}
else if (sensor[1] == 0 && sensor[0] != 0 && sensor[2] == 0 && sensor[3] != 0 && sensor[4] != 0)
{
error = -1;//10011左2和中间压线,有可能是直行,防止直线抖动,最小幅度左偏就行。-1
}
else if (sensor[2] == 0 && sensor[1] != 0 && sensor[0] != 0 && sensor[3] != 0 && sensor[4] != 0)
{
error = 0;//11011只有中间的压线了,说明是直道,不用转往,加速就行。这个很重要
}
else if (sensor[3] == 0 && sensor[1] != 0 && sensor[2] == 0 && sensor[0] != 0 && sensor[4] != 0)
{
error = 1;//11001右2和中间压线,有可能是直行,防止直线抖动,小幅度右偏就行。1
}
else if (sensor[3] == 0 && sensor[1] != 0 && sensor[2] != 0 && sensor[0] != 0 && sensor[4] != 0)
{
error = 2;//11101就剩右2的压线,往右拐弯,这才是关键右转2
}
else if (sensor[4] == 0 && sensor[1] != 0 && sensor[2] != 0 && sensor[3] == 0 && sensor[0] != 0)
{
error = 3;//11100右边两个都压线,中幅度往右转3
}
else if (sensor[4] == 0 && sensor[1] != 0 && sensor[2] != 0 && sensor[3] != 0 && sensor[0] != 0)
{
error = 4;//11110只剩最右边压线了,最大程度右转,4
}
else if ((sensor[0] !=0) && (sensor[1] !=0) && (sensor[2] !=0) && (sensor[3] !=0) && (sensor[4] !=0)) {
if (previous_error == -4) //11111
error = -5;
if (previous_error == 4)
error = 5;
}
}
void calc_pid() //计算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 ;
int right_motor_speed ;
left_motor_speed = initial_motor_speed + PID_value;
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;
}
if (right_motor_speed < -255)
{
right_motor_speed = -255;
}
if (right_motor_speed > 255)
{
right_motor_speed = 255;
}
motorsWrite(left_motor_speed, right_motor_speed);
}