智能循迹小车实现方案

一、系统概述

智能循迹小车通过红外传感器检测地面黑色轨迹线,由微控制器处理传感器数据并控制电机实现自动循迹行驶。

二、硬件组件清单

核心控制模块

  1. 主控板:Arduino UNO R3(或STM32、ESP32)
  2. 电机驱动模块:L298N双H桥直流电机驱动板
  3. 循迹传感器:TCRT5000红外反射传感器 ×4-5个
  4. 电源系统
    • 18650锂电池 ×2(7.4V)
    • 5V降压模块(LM2596)
    • 开关电源模块

执行机构

  1. 直流减速电机:TT马达 ×2(3-6V,减速比1:48)
  2. 车轮:65mm橡胶轮 ×2
  3. 万向轮:1个(前部支撑)

辅助组件

  1. 车体底盘:亚克力或铝合金底盘
  2. 杜邦线:公对公、公对母若干
  3. 传感器支架:可调节高度的安装支架

三、电路连接图

电源连接

锂电池(7.4V) → L298N(12V输入) → 5V输出 → Arduino VIN
              ↓
              LM2596降压 → 传感器组(5V)

传感器连接(4路方案)

TCRT5000模块引脚 → Arduino引脚
VCC → 5V
GND → GND
DO1(最左) → A0
DO2(左中) → A1  
DO3(右中) → A2
DO4(最右) → A3

电机驱动连接

L298N模块 → Arduino → 电机
ENA → 5(PWM控制左轮速度)
IN1 → 6(左轮方向1)
IN2 → 7(左轮方向2)
ENB → 10(PWM控制右轮速度)
IN3 → 8(右轮方向1)
IN4 → 9(右轮方向2)
OUT1/OUT2 → 左电机正负极
OUT3/OUT4 → 右电机正负极

完整接线示意图

┌─────────────────────────────────────────────┐
│             智能循迹小车电路连接图           │
├─────────────────────────────────────────────┤
│ 锂电池7.4V                                  │
│     │                                       │
│     ├─→ L298N(12V输入)                     │
│     │      ├─5V输出→Arduino VIN            │
│     │      ├─OUT1/2→左电机                 │
│     │      └─OUT3/4→右电机                 │
│     │                                       │
│     └─→ LM2596(降压至5V)→传感器组VCC       │
│                                            │
│ Arduino UNO引脚分配:                       │
│ 数字引脚:                                  │
│ 5(ENA) 6(IN1) 7(IN2) → L298N左电机控制     │
│ 8(IN3) 9(IN4) 10(ENB) → L298N右电机控制    │
│                                            │
│ 模拟引脚:                                  │
│ A0-A3 → TCRT5000传感器DO输出               │
└─────────────────────────────────────────────┘

四、核心程序代码(Arduino)

基础循迹程序(4传感器)

/*
 * 智能循迹小车程序
 * 使用4路TCRT5000红外传感器
 * L298N电机驱动模块
 */

// 电机控制引脚定义
#define ENA 5    // 左电机PWM速度控制
#define IN1 6    // 左电机方向1
#define IN2 7    // 左电机方向2
#define ENB 10   // 右电机PWM速度控制  
#define IN3 8    // 右电机方向1
#define IN4 9    // 右电机方向2

// 传感器引脚定义
#define SENSOR_LEFT A0    // 最左侧传感器
#define SENSOR_MID_LEFT A1  // 左侧传感器
#define SENSOR_MID_RIGHT A2 // 右侧传感器
#define SENSOR_RIGHT A3   // 最右侧传感器

// 速度参数(PWM值,0-255)
#define BASE_SPEED 150    // 基础速度
#define TURN_SPEED 180    // 转弯速度
#define SLOW_SPEED 100    // 慢速

// 传感器阈值(根据实际调整)
#define SENSOR_THRESHOLD 500  // 黑白区分阈值

// 传感器状态变量
int sensorLeft, sensorMidLeft, sensorMidRight, sensorRight;
int sensorValues[4];  // 存储传感器值

void setup() {
  Serial.begin(9600);
  
  // 初始化电机控制引脚
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  
  // 初始化传感器引脚
  pinMode(SENSOR_LEFT, INPUT);
  pinMode(SENSOR_MID_LEFT, INPUT);
  pinMode(SENSOR_MID_RIGHT, INPUT);
  pinMode(SENSOR_RIGHT, INPUT);
  
  // 初始停止状态
  stopCar();
  delay(1000);
  
  Serial.println("智能循迹小车启动完成!");
}

void loop() {
  // 1. 读取传感器数据
  readSensors();
  
  // 2. 显示传感器状态(调试用)
  displaySensorStatus();
  
  // 3. 根据传感器状态控制小车
  lineFollowing();
  
  // 短暂延迟
  delay(10);
}

// 读取所有传感器值
void readSensors() {
  sensorLeft = analogRead(SENSOR_LEFT);
  sensorMidLeft = analogRead(SENSOR_MID_LEFT);
  sensorMidRight = analogRead(SENSOR_MID_RIGHT);
  sensorRight = analogRead(SENSOR_RIGHT);
  
  // 转换为二值化数据(0:白线,1:黑线)
  sensorValues[0] = (sensorLeft > SENSOR_THRESHOLD) ? 1 : 0;
  sensorValues[1] = (sensorMidLeft > SENSOR_THRESHOLD) ? 1 : 0;
  sensorValues[2] = (sensorMidRight > SENSOR_THRESHOLD) ? 1 : 0;
  sensorValues[3] = (sensorRight > SENSOR_THRESHOLD) ? 1 : 0;
}

// 显示传感器状态
void displaySensorStatus() {
  Serial.print("传感器状态: ");
  Serial.print(sensorValues[0]);
  Serial.print(" ");
  Serial.print(sensorValues[1]);
  Serial.print(" ");
  Serial.print(sensorValues[2]);
  Serial.print(" ");
  Serial.print(sensorValues[3]);
  Serial.println();
}

// 循迹控制逻辑
void lineFollowing() {
  // 情况1:正常在轨迹上(中间两个传感器检测到黑线)
  if (sensorValues[1] == 1 && sensorValues[2] == 1) {
    forward(BASE_SPEED);
    Serial.println("状态:直行");
  }
  
  // 情况2:轻微左偏(只有左侧传感器检测到)
  else if (sensorValues[0] == 1 && sensorValues[1] == 1) {
    turnLeft(TURN_SPEED);
    Serial.println("状态:左转修正");
  }
  
  // 情况3:轻微右偏(只有右侧传感器检测到)
  else if (sensorValues[2] == 1 && sensorValues[3] == 1) {
    turnRight(TURN_SPEED);
    Serial.println("状态:右转修正");
  }
  
  // 情况4:大幅左偏(只有最左侧传感器检测到)
  else if (sensorValues[0] == 1) {
    sharpLeft(TURN_SPEED);
    Serial.println("状态:急左转");
  }
  
  // 情况5:大幅右偏(只有最右侧传感器检测到)
  else if (sensorValues[3] == 1) {
    sharpRight(TURN_SPEED);
    Serial.println("状态:急右转");
  }
  
  // 情况6:丢失轨迹(所有传感器都检测到白色)
  else if (sensorValues[0] == 0 && sensorValues[1] == 0 && 
           sensorValues[2] == 0 && sensorValues[3] == 0) {
    // 尝试寻找轨迹
    searchLine();
    Serial.println("状态:寻找轨迹");
  }
  
  // 情况7:十字路口(所有传感器都检测到黑色)
  else if (sensorValues[0] == 1 && sensorValues[1] == 1 && 
           sensorValues[2] == 1 && sensorValues[3] == 1) {
    handleCrossroad();
    Serial.println("状态:十字路口");
  }
}

// 电机控制函数
void forward(int speed) {
  // 左电机前进
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  analogWrite(ENA, speed);
  
  // 右电机前进
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENB, speed);
}

void backward(int speed) {
  // 左电机后退
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  analogWrite(ENA, speed);
  
  // 右电机后退
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  analogWrite(ENB, speed);
}

void turnLeft(int speed) {
  // 左电机慢速或停止
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  analogWrite(ENA, speed * 0.3);
  
  // 右电机正常速度
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENB, speed);
}

void turnRight(int speed) {
  // 左电机正常速度
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  analogWrite(ENA, speed);
  
  // 右电机慢速或停止
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENB, speed * 0.3);
}

void sharpLeft(int speed) {
  // 左电机后退
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  analogWrite(ENA, speed * 0.5);
  
  // 右电机前进
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENB, speed);
}

void sharpRight(int speed) {
  // 左电机前进
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  analogWrite(ENA, speed);
  
  // 右电机后退
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  analogWrite(ENB, speed * 0.5);
}

void stopCar() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  analogWrite(ENA, 0);
  analogWrite(ENB, 0);
}

// 寻找轨迹(当丢失轨迹时)
void searchLine() {
  // 先停止
  stopCar();
  delay(100);
  
  // 尝试向左转寻找
  turnLeft(SLOW_SPEED);
  delay(200);
  
  // 检查是否找到轨迹
  readSensors();
  if (sensorValues[1] == 1 || sensorValues[2] == 1) {
    return; // 找到轨迹
  }
  
  // 如果没找到,尝试向右转
  stopCar();
  delay(100);
  turnRight(SLOW_SPEED);
  delay(400);
  
  // 再次检查
  readSensors();
  if (sensorValues[1] == 1 || sensorValues[2] == 1) {
    return; // 找到轨迹
  }
  
  // 如果还没找到,后退一点
  backward(SLOW_SPEED);
  delay(300);
  stopCar();
}

// 处理十字路口
void handleCrossroad() {
  // 这里可以根据需要实现不同的十字路口处理策略
  // 示例:直行通过
  forward(BASE_SPEED);
  delay(500); // 通过十字路口的时间
  
  // 或者:右转
  // turnRight(TURN_SPEED);
  // delay(300);
  // forward(BASE_SPEED);
  // delay(200);
}

高级版本(带PID控制)

/*
 * PID循迹控制版本
 * 提供更平滑的循迹效果
 */

// PID参数
float Kp = 25;   // 比例系数
float Ki = 0.1;  // 积分系数  
float Kd = 15;   // 微分系数

float error = 0, lastError = 0;
float P = 0, I = 0, D = 0;
float PID_value = 0;

// 电机基础速度
int leftMotorSpeed = 0;
int rightMotorSpeed = 0;
int motorBaseSpeed = 150;

void pidLineFollowing() {
  // 计算误差值(-3到+3)
  error = calculateError();
  
  // PID计算
  P = error;
  I = I + error;
  D = error - lastError;
  
  PID_value = (Kp * P) + (Ki * I) + (Kd * D);
  lastError = error;
  
  // 计算电机速度
  leftMotorSpeed = motorBaseSpeed - PID_value;
  rightMotorSpeed = motorBaseSpeed + PID_value;
  
  // 限制速度范围
  leftMotorSpeed = constrain(leftMotorSpeed, 0, 255);
  rightMotorSpeed = constrain(rightMotorSpeed, 0, 255);
  
  // 设置电机速度
  setMotorSpeed(leftMotorSpeed, rightMotorSpeed);
}

// 计算误差值
int calculateError() {
  int errorValue = 0;
  
  // 传感器权重分配
  // 从左到右:-3, -1, +1, +3
  if (sensorValues[0] == 1) errorValue = -3;
  else if (sensorValues[1] == 1) errorValue = -1;
  else if (sensorValues[2] == 1) errorValue = 1;
  else if (sensorValues[3] == 1) errorValue = 3;
  else errorValue = lastError; // 保持上次误差
  
  return errorValue;
}

// 设置电机速度
void setMotorSpeed(int leftSpeed, int rightSpeed) {
  // 左电机
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  analogWrite(ENA, leftSpeed);
  
  // 右电机
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  analogWrite(ENB, rightSpeed);
}

参考代码 智能循迹小车电路图和程序及仿真图 www.youwenfan.com/contentcnt/134324.html

五、调试与优化建议

1. 传感器校准

void calibrateSensors() {
  Serial.println("开始传感器校准...");
  Serial.println("将传感器放在白色区域,按任意键继续");
  while(!Serial.available());
  
  int whiteValues[4];
  readRawSensors();
  for(int i=0; i<4; i++) whiteValues[i] = sensorRaw[i];
  
  Serial.println("将传感器放在黑色轨迹上,按任意键继续");
  while(!Serial.available());
  
  int blackValues[4];
  readRawSensors();
  for(int i=0; i<4; i++) blackValues[i] = sensorRaw[i];
  
  // 计算阈值
  for(int i=0; i<4; i++) {
    thresholds[i] = (whiteValues[i] + blackValues[i]) / 2;
    Serial.print("传感器");
    Serial.print(i);
    Serial.print("阈值:");
    Serial.println(thresholds[i]);
  }
}

2. 常见问题解决

问题现象 可能原因 解决方案
小车左右摇摆 PID参数不合适 减小Kp,增加Kd
无法检测黑线 传感器距离地面太远 调整传感器高度至5-10mm
电机不转或反转 接线错误 检查IN1-IN4接线顺序
电源重启 电流不足 使用更大容量电池或电容滤波

3. 扩展功能建议

  1. 蓝牙遥控:添加HC-05/06模块实现手机控制
  2. 超声波避障:增加HC-SR04模块实现避障功能
  3. 速度编码器:安装光电编码器实现精确速度控制
  4. OLED显示:添加0.96寸OLED显示传感器状态和速度
  5. 多模式切换:增加按键实现手动/自动模式切换

六、轨迹制作建议

  1. 轨迹材料:黑色电工胶带(宽度15-20mm)
  2. 背景要求:浅色平整地面(白色或浅灰色)
  3. 转弯半径:最小半径建议≥15cm
  4. 交叉角度:十字路口90度垂直交叉

七、安全注意事项

  1. 确保所有接线牢固,避免短路
  2. 锂电池充电使用专用充电器
  3. 调试时小车架空,避免意外启动
  4. 电机堵转时间不超过10秒,防止烧毁
posted @ 2026-04-22 16:54  康帅服  阅读(14)  评论(0)    收藏  举报