基于Arduino红外控制循迹小车:详细代码教程

一、所需元件

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);
}

  • 20
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 32
    评论
### 回答1: 好的,我可以回答这个问题。以下是基于 Arduino红外循迹小车程序的示例代码: ``` // 定义红外传感器引脚 #define IR_LEFT A #define IR_MIDDLE A1 #define IR_RIGHT A2 // 定义电机引脚 #define MOTOR_LEFT 5 #define MOTOR_RIGHT 6 void setup() { // 初始化串口通信 Serial.begin(960); // 设置红外传感器引脚为输入模式 pinMode(IR_LEFT, INPUT); pinMode(IR_MIDDLE, INPUT); pinMode(IR_RIGHT, INPUT); // 设置电机引脚为输出模式 pinMode(MOTOR_LEFT, OUTPUT); pinMode(MOTOR_RIGHT, OUTPUT); } void loop() { // 读取红外传感器的值 int ir_left = digitalRead(IR_LEFT); int ir_middle = digitalRead(IR_MIDDLE); int ir_right = digitalRead(IR_RIGHT); // 输出红外传感器的值 Serial.print(ir_left); Serial.print(ir_middle); Serial.println(ir_right); // 判断小车应该往哪个方向移动 if (ir_left == LOW && ir_middle == LOW && ir_right == LOW) { // 直行 digitalWrite(MOTOR_LEFT, HIGH); digitalWrite(MOTOR_RIGHT, HIGH); } else if (ir_left == HIGH && ir_middle == LOW && ir_right == LOW) { // 左转 digitalWrite(MOTOR_LEFT, LOW); digitalWrite(MOTOR_RIGHT, HIGH); } else if (ir_left == LOW && ir_middle == LOW && ir_right == HIGH) { // 右转 digitalWrite(MOTOR_LEFT, HIGH); digitalWrite(MOTOR_RIGHT, LOW); } else if (ir_left == HIGH && ir_middle == LOW && ir_right == HIGH) { // 掉头 digitalWrite(MOTOR_LEFT, LOW); digitalWrite(MOTOR_RIGHT, HIGH); delay(500); digitalWrite(MOTOR_LEFT, HIGH); digitalWrite(MOTOR_RIGHT, LOW); delay(100); } else { // 停止 digitalWrite(MOTOR_LEFT, LOW); digitalWrite(MOTOR_RIGHT, LOW); } } ``` 这个程序可以让红外循迹小车根据红外传感器的值自动行驶,当小车遇到障碍物时会自动避开。 ### 回答2: 基于Arduino红外循迹小车程序可以实现小车根据地面上的红外线进行循迹移动。下面是一个简单的程序示例: 首先,需要连接红外传感器模块和电机驱动模块到Arduino板上。 1. 初始化引脚: ``` int leftMotorPin1 = 2; int leftMotorPin2 = 3; int rightMotorPin1 = 4; int rightMotorPin2 = 5; int leftIRSensorPin = A0; int rightIRSensorPin = A1; ``` 2. 设置引脚模式: ``` void setup() { pinMode(leftMotorPin1, OUTPUT); pinMode(leftMotorPin2, OUTPUT); pinMode(rightMotorPin1, OUTPUT); pinMode(rightMotorPin2, OUTPUT); pinMode(leftIRSensorPin, INPUT); pinMode(rightIRSensorPin, INPUT); } ``` 3. 定义小车运动函数: ``` void moveForward() { digitalWrite(leftMotorPin1, HIGH); digitalWrite(leftMotorPin2, LOW); digitalWrite(rightMotorPin1, HIGH); digitalWrite(rightMotorPin2, LOW); } void moveBackward() { digitalWrite(leftMotorPin1, LOW); digitalWrite(leftMotorPin2, HIGH); digitalWrite(rightMotorPin1, LOW); digitalWrite(rightMotorPin2, HIGH); } void turnLeft() { digitalWrite(leftMotorPin1, LOW); digitalWrite(leftMotorPin2, HIGH); digitalWrite(rightMotorPin1, HIGH); digitalWrite(rightMotorPin2, LOW); } void turnRight() { digitalWrite(leftMotorPin1, HIGH); digitalWrite(leftMotorPin2, LOW); digitalWrite(rightMotorPin1, LOW); digitalWrite(rightMotorPin2, HIGH); } void stopMoving() { digitalWrite(leftMotorPin1, LOW); digitalWrite(leftMotorPin2, LOW); digitalWrite(rightMotorPin1, LOW); digitalWrite(rightMotorPin2, LOW); } ``` 4. 实现循迹功能: ``` void loop() { int leftIRValue = digitalRead(leftIRSensorPin); int rightIRValue = digitalRead(rightIRSensorPin); if (leftIRValue == HIGH && rightIRValue == HIGH) { moveForward(); } else if (leftIRValue == LOW && rightIRValue == HIGH) { turnRight(); } else if (leftIRValue == HIGH && rightIRValue == LOW) { turnLeft(); } else if (leftIRValue == LOW && rightIRValue == LOW) { moveBackward(); } delay(100); } ``` 这个程序在循迹小车上使用了两个红外传感器,根据感测到的红外线信号来决定小车的运动方向。根据具体的电机驱动模块引脚连接情况,可以适当调整程序中的引脚定义和运动函数。 ### 回答3: 基于Arduino红外循迹小车程序可以实现小车根据红外传感器的信号来自动识别黑线并按照线路行驶。下面是一个简单的红外循迹小车程序示例: 1. 首先,我们需要连接红外传感器和电机到Arduino板上。 2. 在程序中,我们需要定义引脚的接口和各个传感器的位置。例如,我们可以定义左侧红外传感器接收信号的引脚为A0,右侧红外传感器接收信号的引脚为A1。 3. 接下来,我们需要设置Arduino作为输入,配置引脚模式。在setup()函数中,使用pinMode()函数将A0和A1引脚设置为输入模式。 4. 在loop()函数中,我们需要编写代码来读取红外传感器的值。使用analogRead()函数获取红外传感器引脚的值,并将其存储到相应的变量中。例如,使用变量leftSensor保存A0引脚的值,使用变量rightSensor保存A1引脚的值。 5. 接下来,我们需要编写代码来判断小车如何行驶。通过比较左侧和右侧红外传感器的值,判断小车是否离开黑线。如果左侧和右侧传感器都检测到黑线,则小车应该直行;如果只有左侧传感器检测到黑线,则小车应该向右转;如果只有右侧传感器检测到黑线,则小车应该向左转。 6. 根据判断结果,我们可以使用digitalWrite()函数控制电机引脚的电平来驱动小车。例如,如果小车要直行,则设置左右电机的引脚为HIGH;如果小车要向右转,则设置左电机引脚为HIGH,右电机引脚为LOW(或者设置一个较小的PWM值);如果小车要向左转,则设置左电机引脚为LOW,右电机引脚为HIGH(或者设置一个较小的PWM值)。 7. 最后,可以根据需要添加其他的功能,如遇到障碍物停止、加速减速等等。 这是一个简单的红外循迹小车程序示例,你可以根据你的具体需求进行修改和扩展。记得在编写代码之前,先安装好红外传感器和电机,并确保连接正确。
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云边牧风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值