循迹小车---2

文章详细介绍了TCRT5000传感器的工作原理,如何通过其输出的高低电平来判断小车是否在黑色轨迹上。在循迹小车的构建中,传感器的接线、编程实现及问题调试进行了详述,包括如何通过调整传感器灵敏度和电机速度来改善小车的行驶平滑度和准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TCRT5000

TCRT5000传感器的红外发射二级管可以不断发射红外线。

模块输出端为高电平:当发射出的红外线没有或反射强度不够大时,红外线接收管就会一直处于关断状态,指示二级管一直处于熄灭状态

模块输出端为低电平:而当被检测物体出现再检测范围内导致红外线被反射回来且强度足够大,此时红外接收管饱和,指示二级管被点亮

说人话就是: 反射的强度不够时,DO为高,开关指示灯不亮反之DO为低,开关指示灯亮

 

 接线方式:

VCC -> 电源正

GND -> 电源负

DO -> TTL开关信号输出0或1

AO -> 模拟信号输出(不同距离输出不同的电压,此脚可以不接)

循迹小车的原理

根据刚刚的模块讲解可知,TCRT5000的DO和灯会根据红外线的反射强度而变化,而查阅资料可知:黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑色时,大部分红外线会被吸收从而导致DO输出高电平开关指示灯灭

所以这就实现了对于黑色的判断,如果在智能小车的左右侧各装上一枚TCRT5000,并在地面上铺设黑色的线,那么就可以由TCR5000的DO和灯的状态判断是否行驶在黑线上的判断,而当判断快要离开黑线时,通过上节学习的知识控制小车回到轨迹,这就是寻迹小车的实现。

循迹小车接线

关于两个TCRT5000传感器的正负极接线:

 注意:不能将传感器的正负极直接接在面包板的正负极,这样会导致电压过大烧坏传感器!

安装完两个传感器之后如图:(两个传感器的DO分别接在单片机的P2.6和P2.7)

循迹小车的编程实现

根据之前的逻辑,封装一个route_sensor.c:

#include "reg52.h"
#include "motor.h"
#include "timer0.h"

sbit sensor_left = P2^7;
sbit sensor_right = P2^6;

void sensor_react()
{
	if(sensor_left == 0 && sensor_right == 0){ //此时左右都没有检测到黑线,说明在轨迹上,直走, 两个灯都亮
		move_forward();
	}
	if(sensor_left == 1 && sensor_right == 0){ //此时左模块检测到黑线,说明车身偏右即将离开轨道,此时需要左转修正,只有右灯亮
		move_leftturn();
	}
	if(sensor_left == 0 && sensor_right == 1){ //此时右模块检测到黑线,说明车身偏左即将离开轨道,此时需要右转修正,只有左灯亮
		move_rightturn();
	}
	if(sensor_left == 1 && sensor_right == 1){ //此时左右都检测到黑线,说明不在轨迹上了,停止,两个灯都灭
		move_stop();
	}
	
}

main.c:

#include "intrins.h" //这个库加了,delay函数里面的nop()才不会报错
#include "motor.h"
#include "delay.h"
#include "UART.h"
#include "433M.h"
#include "timer0.h"
#include "route_sensor.h"


void main()
{
	while(1){
		sensor_react();
	}
		
}

实现效果:

1. 由于我的桌面是黑色的,所以如果不用白纸,那么就模拟了不在轨道上轮子不会动

2. 当白纸遮挡了左边传感器,就相当于右侧检测到黑线,模拟了小车向左偏离了轨道,需要右转修正,因此只有左轮动

3.  当白纸遮挡了右边传感器,就相当于左侧检测到黑线,模拟了小车向右偏离了轨道,需要左转修正,因此只有右轮动

4. 当白纸同时遮挡了两个传感器,就相当于黑线在传感器之间,模拟了小车正常行驶,需要直行,所以左右轮一起转动

实际循迹中的问题

这样乍一看似乎已经成功实现了,然而其实有些问题:当我实际搭建轨道试运行的时候,小车还是会经常性的跑离轨道,这就是小车的速度和灵敏度的配合问题了:用螺丝刀调整传感器的灵敏度(顺时针变灵敏逆时针变迟钝)并使用之前两轮分别进行调速的代码对左右轮进行微调,我修改了代码让小车的直行速度慢一些,(且由于我的小车的右电机似乎更强大一点,所以右电机的速度略慢于左电机达到平衡)

修改后的route_sensor.c:

#include "reg52.h"
#include "motor.h"
#include "timer0.h"

sbit sensor_left = P2^7;
sbit sensor_right = P2^6;

extern char speed_left;
extern char speed_right;

void sensor_react()
{
	if(sensor_left == 0 && sensor_right == 0){ //此时左右都没有检测到黑线,说明在轨迹上,直走, 两个灯都亮
		//move_forward();
		speed_left = 22; // 22/40 的时间在全速前进
		speed_right = 20; // 20/40 的时间在全速前进,所以会略慢于左轮,实际表现中就恰好是直行
	}
	if(sensor_left == 1 && sensor_right == 0){ //此时左模块检测到黑线,说明车身偏右即将离开轨道,此时需要左转修正,只有右灯亮
		move_leftturn();
	}
	if(sensor_left == 0 && sensor_right == 1){ //此时右模块检测到黑线,说明车身偏左即将离开轨道,此时需要右转修正,只有左灯亮
		move_rightturn();
	}
	if(sensor_left == 1 && sensor_right == 1){ //此时左右都检测到黑线,说明不在轨迹上了,停止,两个灯都灭
		//move_stop();//此处用STOP函数也不好,因为stop命令发送时,可能定时器还在计时发送PWM波,指令会有微小的冲突从而发出电流声
        speed_left = 0; 
		speed_right = 0; 
	}
	
}

实现的效果:

 PS:可以看到,小车行驶过程中其实还是不太平滑,那么其实平滑的方法也不难,现在不平滑的原因是转弯的时候一只轮子其实是不动的,那其实如果像我调整直线行驶一样,对两个轮子分别调速,只是确保左轮的speed_left 小于 speed_right就可以实现比较平滑的行驶了例如speed_left = 10;speed_right = 40 ),但是我认为平滑的代价就是转弯的灵敏度会下降,比如我铺设的道理的弯道比较密集,采用这种方法虽然可以平滑,但是也会导致小车更容易发生“还没转好就冲出轨道”的问题,所以我暂时没有修改这个平滑转弯的代码。

那有没有办法把以上的平滑代码更加细化呢,方法之一就是细化PWM波,现在调整PWM波的最小单位是0.5ms,如果减小这个时间,理论上就可以更加细化的调整速度。

#include #include "qudong.h" #include "duankou.h" #include "lcd1602.h" #include "celv.h" #define uchar unsigned char #define uint unsigned int #define CPU_F ((double)8000000) #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) //****************************************************************************** //全局变量 //****************************************************************************** float voltage=6.0; //实际电压值 int RS1=100; int LS1=100; int RS0=100; int LS0=100; char heixian=0x03; //不等于0x03表示检测到信号,等于0x03表示没检测到信号 char ji_shu=0; //表示第几次检测到黑线 char youxinhao=0; //=1表示检测到信号,=0表示没有检测到信号 uint total_time_count=0;//时间相关变量 uint start_low_speed=0; uint end_low_speed=0; uint end_all=0; uint start_all=0; uint LM_cap_new=0; //测速相关变量 uint LM_cap_old=0; uint LM_cap_count=0; uint LM_mai_kuai=0; float real_LM_speed=0.0; float top_speed=0; float average_speed=0; uint RM_cap_new=0; uint RM_cap_old=0; uint RM_cap_count=0; uint RM_mai_kuai=0; float real_RM_speed=0.0; float total_distance=0; //测量值转化为实际值相关变量 float dis1=0; float dis0=0; uint low_speed_time=0; uint total_time=0; //****************************************************************************** //系统时钟初始化,aclk=32768k,mclk=XT2,SMCLK = XT2。 //****************************************************************************** void Init_clock(void) { DCOCTL = DCO0 + DCO1 + DCO2; // Max DCO数字晶振最高频率 BCSCTL1 = RSEL0 + RSEL1 + RSEL2; // XT2on, max RSEL选择高速晶振最高频率 BCSCTL2 |=SELM_2+SELS; //MCLK=8M,SMCLK = XT2,系统主时钟选择高速晶振 do //清除振荡器失效标志,等振荡器稳定。 { IFG1&=~OFIFG; for(unsigned int i=0XFF;i>0;i--); } while((IFG1&OFIFG)!=0); } #pragma vector=ADC_VECTOR //ADC12 interrupt service routine __interrupt void ADC12_ISR (void) { if(ADC12MEM0<2816)P6OUT&=~BIT3; //欠压指示亮 else P6OUT|=BIT3; } //*************************
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值