双红外反射式红外巡线传感器完全指南
一、传感器工作原理与类型
1. 红外巡线传感器基本原理
红外巡线传感器基于红外光的反射特性工作:
- 发射管:发射特定波长(通常850-950nm)的红外光
- 接收管:接收从地面反射回来的红外光
- 检测原理:
- 白色表面:反射率高,接收管接收到较强信号
- 黑色表面:吸收红外光,反射率低,接收信号弱
- 输出信号:数字量(高低电平)或模拟量(电压值)
2. 双红外传感器配置优势
| 配置方式 | 优点 | 适用场景 |
|---|---|---|
| 并排安装 | 可检测线路位置偏差 | 精确巡线,PID控制 |
| 前后安装 | 可预测线路走向 | 高速巡线,提前转向 |
| 角度安装 | 扩大检测范围 | 复杂路径跟踪 |
3. 常见传感器型号对比
| 型号 | 类型 | 检测距离 | 输出方式 | 特点 |
|---|---|---|---|---|
| TCRT5000 | 反射式 | 0.2-15mm | 数字/模拟 | 常用,性价比高 |
| RPR220 | 反射式 | 1-25mm | 数字 | 抗干扰强 |
| ITR20001 | 反射式 | 0-3mm | 模拟 | 高精度 |
| E18-D80NK | 漫反射 | 3-80cm | 数字 | 可调距离 |
二、硬件电路设计
1. TCRT5000传感器电路设计
1.1 发射电路
VCC (5V)
│
├─[限流电阻R1]─┬─[红外发射管LED]─┐
│ │ │
│ └─[单片机IO控制]─┘
│
GND
计算公式:
- 限流电阻:R1 = (VCC - Vf) / If
- 典型值:Vf=1.2V,If=20mA,R1=(5-1.2)/0.02=190Ω,取220Ω
1.2 接收电路(比较器输出)
VCC (5V)
│
├─[上拉电阻10k]─┬─[输出信号]→ 单片机IO
│ │
│ [LM393比较器]输出
│ │
│ [电位器]─┬─[调整阈值]
│ │
│ [红外接收管]─┬─[负载电阻]
│ │
│ GND
关键参数:
- 比较器:LM393或LM358
- 负载电阻:通常1-10kΩ,影响灵敏度
- 电位器:10kΩ可调,用于设置检测阈值
1.3 完整双传感器电路
/*
* 双TCRT5000巡线传感器电路连接
* 左传感器:OUT1 → P3.2
* 右传感器:OUT2 → P3.3
* 电源:VCC=5V,GND共地
* 电位器:分别调节左右传感器灵敏度
*/
2. 直接ADC读取方案(无比较器)
对于需要模拟量读取的应用:
红外接收管
│
├─[负载电阻R2]─┬─[ADC输入]→ 单片机ADC引脚
│ │
│ [滤波电容0.1uF]
│ │
│ GND
ADC值关系:
- 白色表面:ADC值高(接近1023)
- 黑色线路:ADC值低(接近0)
- 阈值:通常设为中间值512
三、STC15F104E接口设计
1. 引脚分配方案
STC15F104E只有6个I/O口,需合理分配:
P3.0 (RxD): 保留给串口通信
P3.1 (TxD): 保留给串口通信
P3.2 (INT0): 左传感器数字输出
P3.3 (INT1): 右传感器数字输出
P3.4 (T0): 左传感器PWM控制(可选)
P3.5 (T1): 右传感器PWM控制(可选)
2. 接口电路优化
由于STC15F104E资源有限,推荐以下方案:
方案A:纯数字输入(最简单)
// 直接读取数字电平
sbit LEFT_SENSOR = P3^2; // 左传感器
sbit RIGHT_SENSOR = P3^3; // 右传感器
// 传感器状态
#define ON_LINE 0 // 检测到黑线(低电平)
#define OFF_LINE 1 // 检测到白色(高电平)
方案B:ADC模拟读取(需外接ADC)
// 使用外部ADC芯片(如PCF8591)
// I2C接口连接
sbit SDA = P3^4; // I2C数据线
sbit SCL = P3^5; // I2C时钟线
四、软件编程实现
1. 基础巡线程序(数字传感器)
#include <STC15F104E.H>
#include <intrins.h>
// 传感器引脚定义
sbit LEFT_SENSOR = P3^2; // 左传感器
sbit RIGHT_SENSOR = P3^3; // 右传感器
// 电机控制引脚(假设通过L298N驱动)
sbit LEFT_MOTOR_F = P3^4; // 左电机前进
sbit LEFT_MOTOR_B = P3^5; // 左电机后退
sbit RIGHT_MOTOR_F = P3^0; // 右电机前进(复用RxD)
sbit RIGHT_MOTOR_B = P3^1; // 右电机后退(复用TxD)
// 延时函数
void DelayMS(uint ms) {
uint i, j;
for(i = ms; i > 0; i--)
for(j = 114; j > 0; j--);
}
// 电机控制函数
void Motor_Stop() {
LEFT_MOTOR_F = 0;
LEFT_MOTOR_B = 0;
RIGHT_MOTOR_F = 0;
RIGHT_MOTOR_B = 0;
}
void Motor_Forward() {
LEFT_MOTOR_F = 1;
LEFT_MOTOR_B = 0;
RIGHT_MOTOR_F = 1;
RIGHT_MOTOR_B = 0;
}
void Motor_Left() {
LEFT_MOTOR_F = 0;
LEFT_MOTOR_B = 0;
RIGHT_MOTOR_F = 1;
RIGHT_MOTOR_B = 0;
}
void Motor_Right() {
LEFT_MOTOR_F = 1;
LEFT_MOTOR_B = 0;
RIGHT_MOTOR_F = 0;
RIGHT_MOTOR_B = 0;
}
void Motor_Backward() {
LEFT_MOTOR_F = 0;
LEFT_MOTOR_B = 1;
RIGHT_MOTOR_F = 0;
RIGHT_MOTOR_B = 1;
}
// 基础巡线算法
void Line_Following_Basic() {
bit left_state, right_state;
while(1) {
left_state = LEFT_SENSOR;
right_state = RIGHT_SENSOR;
// 状态判断
if(left_state == 0 && right_state == 0) {
// 00: 都在线上 - 直行
Motor_Forward();
}
else if(left_state == 0 && right_state == 1) {
// 01: 左在线,右离线 - 左转
Motor_Left();
DelayMS(50); // 小角度调整
}
else if(left_state == 1 && right_state == 0) {
// 10: 左离线,右在线 - 右转
Motor_Right();
DelayMS(50);
}
else {
// 11: 都离线 - 停止或搜索
Motor_Stop();
// 可选:小范围搜索
Motor_Left();
DelayMS(100);
}
DelayMS(10); // 控制循环频率
}
}
void main() {
// 初始化I/O
P3M0 = 0x00; // 准双向模式
P3M1 = 0x00;
// 初始停止
Motor_Stop();
DelayMS(1000); // 启动延时
// 开始巡线
Line_Following_Basic();
}
2. 改进型巡线算法(带记忆功能)
// 改进版巡线,记录上次状态
void Line_Following_Advanced() {
static bit last_left = 1, last_right = 1;
static uchar lost_count = 0;
while(1) {
bit left_state = LEFT_SENSOR;
bit right_state = RIGHT_SENSOR;
// 状态机处理
switch((left_state << 1) | right_state) {
case 0: // 00: 都在线上
Motor_Forward();
lost_count = 0;
break;
case 1: // 01: 左在线,右离线
if(last_left == 0) {
// 上次左也在线,轻微右偏
Motor_Right();
DelayMS(30);
} else {
// 新检测到,正常左转
Motor_Left();
DelayMS(50);
}
lost_count = 0;
break;
case 2: // 10: 左离线,右在线
if(last_right == 0) {
// 上次右也在线,轻微左偏
Motor_Left();
DelayMS(30);
} else {
// 新检测到,正常右转
Motor_Right();
DelayMS(50);
}
lost_count = 0;
break;
case 3: // 11: 都离线
lost_count++;
if(lost_count < 10) {
// 短暂丢失,按上次方向继续
if(last_left == 0) {
Motor_Left();
} else if(last_right == 0) {
Motor_Right();
} else {
Motor_Forward(); // 默认直行
}
} else {
// 长时间丢失,停止并搜索
Motor_Stop();
Search_Line();
lost_count = 0;
}
break;
}
// 更新上次状态
last_left = left_state;
last_right = right_state;
DelayMS(10);
}
}
// 寻线搜索函数
void Search_Line() {
uchar i;
// 向左搜索
for(i = 0; i < 5; i++) {
Motor_Left();
DelayMS(100);
if(LEFT_SENSOR == 0 || RIGHT_SENSOR == 0) {
return; // 找到线
}
}
// 向右搜索
for(i = 0; i < 10; i++) {
Motor_Right();
DelayMS(100);
if(LEFT_SENSOR == 0 || RIGHT_SENSOR == 0) {
return; // 找到线
}
}
// 向后搜索
Motor_Backward();
DelayMS(300);
Motor_Stop();
}
3. PWM调速巡线(更平滑)
// PWM调速巡线控制
void Line_Following_PWM() {
// PWM参数
uchar left_speed = 100; // 左电机速度 0-100
uchar right_speed = 100; // 右电机速度 0-100
uchar pwm_counter = 0;
// 定时器0初始化(PWM生成)
TMOD &= 0xF0;
TMOD |= 0x01; // 定时器0模式1
TH0 = 0xFC; // 1ms定时
TL0 = 0x67;
ET0 = 1;
TR0 = 1;
EA = 1;
while(1) {
// 读取传感器
bit left_state = LEFT_SENSOR;
bit right_state = RIGHT_SENSOR;
// 根据传感器状态调整速度
if(left_state == 0 && right_state == 0) {
// 直行
left_speed = 80;
right_speed = 80;
}
else if(left_state == 0 && right_state == 1) {
// 左转:左轮慢,右轮快
left_speed = 40;
right_speed = 100;
}
else if(left_state == 1 && right_state == 0) {
// 右转:左轮快,右轮慢
left_speed = 100;
right_speed = 40;
}
else {
// 都离线:慢速前进
left_speed = 60;
right_speed = 60;
}
DelayMS(20); // 控制更新频率
}
}
// 定时器0中断服务函数(PWM生成)
void Timer0_ISR() interrupt 1 {
static uchar pwm_counter = 0;
TH0 = 0xFC;
TL0 = 0x67;
pwm_counter++;
if(pwm_counter >= 100) {
pwm_counter = 0;
}
// 左电机PWM控制
if(pwm_counter < left_speed) {
LEFT_MOTOR_F = 1;
LEFT_MOTOR_B = 0;
} else {
LEFT_MOTOR_F = 0;
LEFT_MOTOR_B = 0;
}
// 右电机PWM控制
if(pwm_counter < right_speed) {
RIGHT_MOTOR_F = 1;
RIGHT_MOTOR_B = 0;
} else {
RIGHT_MOTOR_F = 0;
RIGHT_MOTOR_B = 0;
}
}
参考代码 双红外反射式红外巡线传感器 www.youwenfan.com/contentcnt/134013.html
五、传感器校准与调试
1. 硬件校准步骤
-
安装高度调整
- 最佳高度:传感器距地面5-15mm
- 使用支架固定,确保两个传感器高度一致
- 高度影响:太高→灵敏度低,太低→易受地面不平影响
-
电位器调节
步骤: 1. 将传感器置于白色区域 2. 调节电位器使LED刚好熄灭(或输出高电平) 3. 将传感器移至黑色线路 4. 确认LED亮起(或输出低电平) 5. 重复微调至最佳状态 -
间距设置
- 标准间距:略大于线路宽度
- 例如:线路宽2cm,传感器间距2.5-3cm
- 可调间距设计便于适应不同线路
2. 软件校准程序
// 自动阈值校准程序
void Sensor_Calibration() {
uchar i;
uint left_sum = 0, right_sum = 0;
uint left_white, left_black, right_white, right_black;
// 白色区域采样
UART_SendString("请将传感器放在白色区域,按任意键开始...\r\n");
while(!KEY); // 等待按键
for(i = 0; i < 100; i++) {
left_sum += LEFT_SENSOR;
right_sum += RIGHT_SENSOR;
DelayMS(10);
}
left_white = left_sum / 100;
right_white = right_sum / 100;
UART_SendString("白色区域采样完成\r\n");
// 黑色线路采样
UART_SendString("请将传感器放在黑色线路,按任意键开始...\r\n");
while(!KEY);
left_sum = right_sum = 0;
for(i = 0; i < 100; i++) {
left_sum += LEFT_SENSOR;
right_sum += RIGHT_SENSOR;
DelayMS(10);
}
left_black = left_sum / 100;
right_black = right_sum / 100;
// 计算阈值(中间值)
left_threshold = (left_white + left_black) / 2;
right_threshold = (right_white + right_black) / 2;
// 输出结果
UART_SendString("校准完成:\r\n");
UART_SendString("左传感器阈值:");
UART_SendNum(left_threshold);
UART_SendString("\r\n右传感器阈值:");
UART_SendNum(right_threshold);
UART_SendString("\r\n");
}
// 带阈值的传感器读取函数
bit Read_Left_Sensor() {
return (LEFT_SENSOR > left_threshold) ? 1 : 0;
}
bit Read_Right_Sensor() {
return (RIGHT_SENSOR > right_threshold) ? 1 : 0;
}
3. 调试技巧
- LED指示:为每个传感器添加状态LED,直观显示检测状态
- 串口输出:通过串口实时输出传感器数值,便于调试
- 可变电阻:使用多圈电位器,调节更精细
- 屏蔽罩:添加遮光罩,减少环境光干扰
六、高级应用:PID巡线算法
1. PID控制原理
误差 = 传感器位置偏差
输出 = Kp×误差 + Ki×积分 + Kd×微分
2. PID巡线实现
// PID巡线控制器
typedef struct {
float Kp, Ki, Kd; // PID参数
float integral; // 积分项
float last_error; // 上次误差
float output; // 输出值
} PID_Controller;
PID_Controller pid;
// PID初始化
void PID_Init(float kp, float ki, float kd) {
pid.Kp = kp;
pid.Ki = ki;
pid.Kd = kd;
pid.integral = 0;
pid.last_error = 0;
pid.output = 0;
}
// PID计算
float PID_Calculate(float error, float dt) {
float derivative;
// 积分项(带抗饱和)
pid.integral += error * dt;
if(pid.integral > 100) pid.integral = 100;
if(pid.integral < -100) pid.integral = -100;
// 微分项
derivative = (error - pid.last_error) / dt;
// PID输出
pid.output = pid.Kp * error +
pid.Ki * pid.integral +
pid.Kd * derivative;
// 限幅
if(pid.output > 100) pid.output = 100;
if(pid.output < -100) pid.output = -100;
pid.last_error = error;
return pid.output;
}
// 基于PID的巡线控制
void Line_Following_PID() {
float error;
float pid_output;
uchar base_speed = 70; // 基础速度
uchar left_speed, right_speed;
// 初始化PID参数
PID_Init(30.0, 0.1, 5.0); // 需要根据实际调整
while(1) {
// 计算位置误差(-1到+1)
if(LEFT_SENSOR == 0 && RIGHT_SENSOR == 0) {
error = 0; // 在线中间
}
else if(LEFT_SENSOR == 0 && RIGHT_SENSOR == 1) {
error = -0.5; // 偏左
}
else if(LEFT_SENSOR == 1 && RIGHT_SENSOR == 0) {
error = 0.5; // 偏右
}
else {
// 都离线,使用上次误差
// 或执行搜索程序
}
// PID计算
pid_output = PID_Calculate(error, 0.01); // dt=10ms
// 转换为电机速度
left_speed = base_speed + pid_output;
right_speed = base_speed - pid_output;
// 限幅
if(left_speed > 100) left_speed = 100;
if(left_speed < 0) left_speed = 0;
if(right_speed > 100) right_speed = 100;
if(right_speed < 0) right_speed = 0;
// 设置电机速度(通过PWM)
Set_Motor_Speed(left_speed, right_speed);
DelayMS(10); // 控制周期10ms
}
}
七、常见问题与解决方案
1. 传感器问题排查表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 传感器无反应 | 1. 电源接反 2. 发射管损坏 3. 接收管损坏 |
1. 检查电源极性 2. 更换发射管 3. 更换接收管 |
| 灵敏度太低 | 1. 安装高度过高 2. 发射电流太小 3. 负载电阻太大 |
1. 降低安装高度 2. 减小限流电阻 3. 减小负载电阻 |
| 误触发频繁 | 1. 环境光干扰 2. 阈值设置不当 3. 地面反光 |
1. 添加遮光罩 2. 重新校准 3. 调整传感器角度 |
| 两传感器不一致 | 1. 高度不一致 2. 元件参数差异 3. 电路不对称 |
1. 调整安装高度 2. 分别校准 3. 检查电路连接 |
2. 抗干扰设计
- 调制解调技术:使用38kHz载波调制,避免环境光干扰
- 软件滤波:多次采样取平均,消除偶然误差
- 硬件滤波:添加RC低通滤波器,平滑信号
- 时序控制:分时点亮传感器,避免相互干扰
3. 性能优化建议
- 动态阈值:根据环境光自动调整阈值
- 自适应速度:根据线路曲率调整巡线速度
- 预测算法:根据历史数据预测线路走向
- 多传感器融合:增加更多传感器提高可靠性
八、项目实例:智能巡线小车
1. 完整系统框图
电源模块(5V)
│
├─ STC15F104E主控
│ ├─ 左红外传感器 → P3.2
│ ├─ 右红外传感器 → P3.3
│ ├─ 左电机驱动 → P3.4/P3.5
│ └─ 右电机驱动 → P3.0/P3.1
│
├─ L298N电机驱动
│ ├─ 左直流电机
│ └─ 右直流电机
│
└─ 调试接口
├─ 状态指示灯
└─ 串口通信
2. 完整程序框架
#include <STC15F104E.H>
// 系统状态定义
typedef enum {
STATE_IDLE, // 空闲
STATE_CALIB, // 校准
STATE_FOLLOW, // 巡线
STATE_SEARCH, // 寻线
STATE_ERROR // 错误
} SystemState;
SystemState current_state = STATE_IDLE;
// 主程序
void main() {
System_Init(); // 系统初始化
Sensor_Calibration(); // 传感器校准
while(1) {
switch(current_state) {
case STATE_IDLE:
if(Start_Button_Pressed()) {
current_state = STATE_FOLLOW;
}
break;
case STATE_FOLLOW:
Line_Following_PID(); // PID巡线
if(Both_Sensors_Offline() > 2) {
current_state = STATE_SEARCH;
}
break;
case STATE_SEARCH:
Search_Line();
if(Line_Found()) {
current_state = STATE_FOLLOW;
} else if(Search_Timeout()) {
current_state = STATE_ERROR;
}
break;
case STATE_ERROR:
Motor_Stop();
Error_Indicator();
break;
}
// 状态指示灯
Update_Status_LED();
// 看门狗喂狗
WDT_CONTR = 0x35;
}
}
3. 扩展功能建议
- 速度显示:添加OLED显示当前速度
- 路径记忆:记录行驶路径,实现自动学习
- 无线控制:添加蓝牙/WiFi模块,手机控制
- 避障功能:增加超声波传感器,避让障碍
- 数据记录:记录巡线数据,分析优化
九、总结与进阶
双红外反射式巡线传感器是机器人巡线应用中最经典、最可靠的解决方案之一。通过合理的设计和编程,可以实现从基础巡线到高级PID控制的多种功能。STC15F104E虽然资源有限,但完全能够胜任基本的巡线任务。
浙公网安备 33010602011771号