基于51单片机光电对管智能小车从入门到精通全教程分解
- 格式:doc
- 大小:3.19 MB
- 文档页数:18
目录
第九章、基于51单片机的红外循迹小车 (2)
1、制作要求 (2)
2、制作目的 (2)
3、制作方案(硬件方面) (2)
3.1 系统概述 (2)
3.2 单片机模块 (3)
3.3 指示灯原理图 (4)
3.4 红外对管原理图 (4)
3.5 电机驱动模块 (5)
4、制作方案(软件方面) (7)
4、附录 (9)
5.1 实物和效果展示 (9)
5.2 参考程序: (9)
5.3 基于C51控制红外循迹小车原理图 (17)
第九章、基于51单片机的红外循迹小车
随着电子科技的迅猛发展,人们对技术也提出了更高的要求。
汽车的智能化在提高汽车的行驶安全性,操作性等方面都有巨大的优势,在一些特殊的场合下也能满足一些特殊的需要。
智能小车系统涉及到自动控制,车辆工程,计算机等多个领域,是未来汽车智能化是一个不可避免的大趋势。
本次红外寻迹小车采用了C51单片机作为控制核心,利用红外对管传感器检测黑线达到循迹目的,自动寻迹,整体系统的电路结构简单,可靠性能高。
1、制作要求
使用51单片机作为控制芯片,自制一台可自行检测道路并行驶的简易智能小车。
在这一次的制作活动中将会接触到51单片机、红外对管、电机驱动模块、简单的C语言编程,要求学会使用51单片机进行编程,入门单片机,能够独立的搭出单片机最小系统;了解红外对管的工作原理、电路图,掌握电压比较器的使用方法,学会调试红外对管;了解电机驱动的作用、工作原理;能够进行简单的C语言编程,给单片机编写程序使其能够正常工作。
2、制作目的
1、入门51单片机,进行简单的C语言编程;
2、掌握51单片机最小系统,中断,定时器/计数器等;
3、了解传感器的种类和原理,掌握红外传感器并学会调试;
4、学习C语言的基本语句,用C语言编写程序。
3、制作方案(硬件方面)
3.1 系统概述
智能循迹小车主要由单片机模块、红外检测模块、电机驱动模块组成。
单片机为主控模块,接受并判断各种信号,控制电机驱动。
在智能循迹小车系统设计过程中,用L293驱动两个电机,产生信号驱动小车前进时,是通过循迹模块里的红外对管ST188是否检测到黑线产生的电平信号通过LM339在返回到单片机,单片机再根据程序设计的要求作出相应的判断送给电机驱动模块,以实现小车自动循迹的功能(可对应附录里的系统原理图)。
图9-3-1 小车工作图
3.2 单片机模块
单片机模块为此次小车系统的核心,是作为系统信号采集和输出控制的重要部分。
51单片机的种类繁多,通常使用的是AT51单片机和STC51单片机,其中STC12单片机自带PWM,可以直接使用。
单片机模块为核心模块,其它由时钟、电源、串口MAX232与程序烧录、I/O 接口等组成。
通过各结构的工作加上丰富的I/O接口,实现数据处理,进而对外部模块进行控制。
我们队设计方案主要分为两种:
设计一个包含电源、串口与程序烧录、外接I/O口组成,实现现场的小车调试程序烧录。
本次制作智能循迹小车所需提供9V电源,一方面9V电源直接供给电机驱动,驱动电机直接转停,另一方面9V经过稳压芯片,将9V电压稳压到5V直接给单片机模块、红外、指示灯工作,才能使小车正常工作。
稳压芯片7805输出为+5V稳定电压,最高输入极限电压36,最低输入电压7V,集成稳压块的最佳工作状态是输入电压与输出电压间的压差在3~4V左右。
压差太大可在输入前端串联几个二极管降压,这样稳压块就不会很烫了。
图9-3-2 电源供应图9-3-3 程序下载口
图9-3-4 单片机最小模块
单片机系统作为循迹小车的核心控制器,起着控制小车所有运行状态的作用。
控制方法有许多,大部分采用单片机来控制。
单片机将红外对管采集的道路信息进行处理。
小车进入循迹模式后,即不停的扫描与循迹模块相连接的I/O口,一旦检测到某个I/O口有信号变化,程序进入判断程序,把相应的信号传给减速电机控制器L293从而纠正小车的状态。
单片机最小系统调试步骤:
方法一:
1.用万用表确定是否正常供电。
2.用示波器确定晶振是否起振。
3.单片机是否工作。
比如,单片机一上电,它的有些管脚ALE引脚会输出脉冲,可以通过示波器查看。
方法二:
1.查看是否可以烧录程序。
2.可以结合图上的指示灯电路点亮一个发光二级管。
参考程序在右边。
3.3 指示灯原理图
本模块是用4个发光二极管作为指示灯显示模块,通过红外对管对道路进行检测后传输信号给单片机,由单片机处理信号后,控制P2口的LED1、LED2、LED3、LED4(小车总原理图上)的输出高、低电平,控制NPN三极管的通断,来控制指示灯的亮、灭。
即以此来显示小车对道路的检测情况。
图9-3-5 指示灯电路
3.4 红外对管原理图
能够用来采集赛道数据的传感器有很多种,比如红外传感器、黑白线检测传感器、光电传感器和摄像头等;但综合价格、性能、使用三方面来看,红外传感器是较为理想的。
黑白线传感器如tk-20虽然性能优秀,但价格较高;光电传感器则受环境的影响太大,摄像头能很好的采集赛道数据,但使用起来不如前面几种传感器简单,且价格较贵;因此这次的小车采用的是ST188红外传感器,其检测距离可调整的范围大,4-10mm均可使用。
如图所示为st188红外传感器。
图9-3-6 红外对管外型图9-3-7 红外对管电路图在焊接st188时应该注意其引脚的位置,不要弄错了;同时在使用时也要小心,因为st188很容易烧掉,其价格在2-3元不等。
焊接完成后,检测st188是否正常工作可以使用手机的照相功能,若通过手机的照相功能能够观察到红光,则说明st188已经可以正常工作了。
接下来要调整可调电阻以达到一个合适的比较电压,可以使用示波器进行调整。
如图9-3-7所示,当有电流经过R4时,红外发射管发射红外线到轨道上,光线经过道路反射,红外接收管接收到红外线C和E引脚就有电流通过,此时C引脚的电压近似为0V。
若发射管发射的红外被黑线吸收,接收管接收不到,此时C和E之间可视为断开,此时C 脚的电压为5V。
红外对管的道路的检测越清楚,传输给单片机的信息越稳定,小车就能更好地循迹。
而红外循迹模块的调试首先要判定自己的红外对管用没有用,而红外对管的检测方案有:1):通过测量红外发光二极管的正反向电阻,还可以在很大程度上推测其性能的优劣。
把万用表拨在R×100或R×1K挡,黑表笔接红外发光二极管正极,红表笔接负极,测得正向电阻应在20≈40K;黑表笔接红外发光二极管负极,红表笔接正极,测得反向电阻应大于500K以上。
2):先给红外对管通电,采用手机摄像功能查看红外发射管是否是好的。
图9-3-8 LM339内部结构图
LM339电压比较器芯片内部装有四个独立的电压比较器,如图7所示当同相输入端的电压大于反相输入端时,输出正最大,此时7脚输出为5v;若反相输入端的电压大于同相输入端。
3.5 电机驱动模块
本次循迹小车的制作采用直流减速电机,直流减速电机转动力矩大,体积小、重量轻、装配简单、使用方便。
其内部由高速电机提供原动力,带动变速(减速)此轮组,产生较大扭力。
驱动模块采用芯片L293为电机驱动芯片,L293是一个具有高电压高电流的全桥驱动芯片,响应频率很高。
可以直流带动两个12V的直流电机。
L293内部的原理图如下:
6V动力电源
图9-3-9 L293内部原理图
OUT1与OUT2与小车的一个电机的正负极相连,OUT3与OUT4与小车的另一个电机的正负极相连,单片机通过控制IN1与IN2,IN3与IN4分别控制电机的正反转。
ENA与ENB分别控制两个电机的使能(控制电机停转)。
图9-3-10 L293N引脚图
图9-3-11 电机驱动电路
L293有两路电源分别为逻辑电源和动力电源,上图中6V为逻辑电源,12V为动力电源。
J4接入逻辑电源,J6接入动力电源,J1与J2分别为单片机控制两个电机的输入端,J3与J5分别与两个电极的正负极相连。
ENA与ENB直接接入6V逻辑电源也就是说两个电机时刻都工作在使能状态,控制电机的运行状态只有通过J1与J2两个接口。
由于我们使用的电机是线圈式的,在从运行状态突然转换到停止状态和从顺时针状态突然转换到逆时针状态时会形成很大的反向电流,在电路中加入二极管的作用就是在产生反向电流的时候进行泄流,保护芯片的安全。
4、制作方案(软件方面)
本次小车制作系统主控芯片为AT89S52,程序主要分为以下几个模块:
1、主函数;作为整个程序的开始,与结束。
Check_Load()、Deal_Message_of_Load()作为子
程序可在后调用。
例:
void main(void)
{
Timer_Init();
while(1)
{
Check_Load();
Deal_Message_of_Load();
}
}
2、赛道信息采集函数;对地面信号进行一个采集后,具体地对Load_Size进行赋值,以便
赛道处理按函数,对信号进行处理。
例:
void Deal_Message_of_Load(void)
{
switch(Load&0X0F)
{
case 0X01: Load_Size = 0X01; break; //0001
case 0x02: Load_Size = 0X02; break; //0010
case 0X03: Load_Size = 0X03; break; //0011
case 0x04: Load_Size = 0X04; break; //0100
case 0X06: Load_Size = 0X05; break; //0110
case 0x08: Load_Size = 0X06; break; //1000
case 0X0C: Load_Size = 0X07; break; //1100
case 0X00: Load_Size = 0X08; break; //0000
case 0x0f: Load_Size = 0X09; break; //1111
default: break;
}
P2 = Load&0X0F; //点亮指示灯
}
3、赛道处理函数;通过对赛道信息采集后,进行判断,并做出相应的指令控制电机转动。
例:
void Control_Wheels(void)
{
if(Load_Size == 0x01)
{
IN1 = !IN1;
Time_Count1++;
if(Time_Count1/20 == 0)
{
IN3 = 1;
}
else
{
IN3 = 0;
}
if(Time_Count1 == 255)
{
Time_Count1 = 0;
}
}
4、定时器初始化函数;顾名思义就是对时间进行计数,以方便中断的执行。
void Timer_Init(void)
{
TMOD = 0x11; //设定定时器T0和T1为工作方式1,为16位定时器/计数器
TH0 = (65536-60000)/256;
TL0 = (65536-60000)%256;
TR0 = 1;
IE = 0X8A;
IN1 = 1;
IN2 = 0;
IN3 = 1;
ENA = 1;
ENB = 1;
}
5、延时函数;对时间进行控制,使在一定时间后执行需要执行的指令。
例:
void Delay(uchar Time)
{
uchar i=0,j=0;
for(i=Time;i>0;i--)
for(j=100;j>0;j--);
}
6、定时器中断T0服务函数;暂停当前程序的执行,优先执行中断函数里的程序。
例:
void Timer0() interrupt 1
{
Time_Count2++;
ENA = 0;
ENB = 0;
if(Time_Count2==2)
{
ENA = 1;
ENB = 1;
TH0 = (65536-60000)/256;
TL0 = (65536-60000)%256;
Control_Wheels();
Time_Count2 = 0;
}
}
4、附录
5.1 实物和效果展示
图9-5-1 实物图图9-5-2 效果图
5.2参考程序:
主程序:
#include<reg52.h>
#include<Check_Load.h>
#include<change_direction.h>
#define uchar unsigned char
#define uint unsigned int
void main(void)
{
Timer_Init(); //定时器初始化配置
while(1)
{
Check_Load(); //获取当前赛道信息
Deal_Message_of_Load(); //小车只能转弯
}
}
下面为程序中的<Check_Load.h>头文件函数,作为子程序起到解释作用。
#ifndef _CHECK_LOAD_H_
#define _CHECK_LOAD_H_
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
/*************全局变量声明*********************/
uchar Load=0; //赛道信息存储变量
uchar Load_Size=0; //赛道类型存储变量
/***********************************************/
/****************************************
函数功能:提取赛道信息
入口参数:无
出口参数:无
****************************************/
void Check_Load(void)
{
P1 = 0XFF; //释放P1端口,此语句可以省略
Load = P1; //读取P1端口,初步提取赛道信息
}
/****************************************
电子科技协会--《电子实践制作教程》
函数功能:处理赛道信息 入口参数:Load 出口参数:无 备 注:誰誰 2012 2 17 *****************************************/ void Deal_Message_of_Load(void) { switch(Load&0X0F) { case 0X01: Load_Size = 0X01; break; case 0x02: Load_Size = 0X02; break; case 0X03: Load_Size = 0X03; break; case 0x04: Load_Size = 0X04; break; case 0X06: Load_Size = 0X05; break; case 0x08: Load_Size = 0X06; break; case 0X0C: Load_Size = 0X07; break; case 0X00: Load_Size = 0X08; break; case 0x0f: Load_Size = 0X09; break; default: break; } P2 = Load&0X0F; } #endif
//0001 //0010 //0011 //0100 //0110 //1000 //1100 //0000 //1111
//点亮指示灯
下面为<chang_direction.h>头文件也和上面的<Check_Load.h>头文件一样,作为子程序。
#ifndef _CHANGE_DERECTION_H_ #define _CHANGE_DERECTION_H_ sbit IN1=P0^0; sbit IN2=P0^1; sbit IN3=P0^2; sbit IN4=P0^3; sbit ENA=P0^4; sbit ENB=P0^5; uchar Time_Count1=0; uchar Time_Count2=0; void Delay(uchar Time); /******************************************* 函数功能:控制左右车轮的转动,实现小车的智能循迹 控制思想:当 Load_Size = 0x01 时,说明小车最右边的光电对管采到黑线,故小车应该 往右边转,应使得小车的左轮转得比右轮多,依此类推
11 / 18
//位定义
电子科技协会--《电子实践制作教程》
入口参数:无 出口参数:无 *******************************************/ void Control_Wheels(void) { /*按照赛道处理的结果(Load_Size)对应的处理左右轮子的转速实现转弯*/ if(Load_Size == 0x01) { IN1 = !IN1; Time_Count1++; if(Time_Count1/20 == 0) //20 { IN3 = 1; } else { IN3 = 0; } if(Time_Count1 == 255) { Time_Count1 = 0; } } else if(Load_Size == 0x02) { IN1 = !IN1; Time_Count1++; if(Time_Count1/10 == 0) { IN3 = 1; } else { IN3 = 0; } if(Time_Count1 == 255) { Time_Count1 = 0; } } else if(Load_Size == 0x03) {
12 / 18
//10
电子科技协会--《电子实践制作教程》
IN1 = !IN1; Time_Count1++; if(Time_Count1/15 == 0) { IN3 = 1; } else { IN3 = 0; } if(Time_Count1 == 255) { Time_Count1 = 0; } } else if(Load_Size == 0x04) { IN3 = !IN3; Time_Count1++; if(Time_Count1/10 == 0) { IN1 = 1; } else { IN1 = 0; } if(Time_Count1 == 255) { Time_Count1 = 0; } } else if(Load_Size == 0x06) { IN3 = !IN3; Time_Count1++; if(Time_Count1/10 == 0) { IN1 = 1; } else {
//15
13 / 18
电子科技协会--《电子实践制作教程》
IN1 = 0; } if(Time_Count1 == 255) { Time_Count1 = 0; } } else if(Load_Size == 0x07) { IN3 = !IN3; Time_Count1++; if(Time_Count1/15 == 0) { IN1 = 1; } else { IN1 = 0; } if(Time_Count1 == 255) { Time_Count1 = 0; } } else if((Load_Size == 0x05)||(Load_Size == 0x08)) { IN1 = !IN1; IN3 = !IN3; } else {;} } /******************************************* 函数功能:定时器初始化 入口参数:无 出口参数:无 ********************************************/ void Timer_Init(void) { TMOD = 0x11; //设定定时器 T0 和 T1 为工作方式 1,为 16 位定时器/计数 器
14 / 18
电子科技协会--《电子实践制作教程》
TH0 = (65536-60000)/256; TL0 = (65536-60000)%256; TR0 = 1; IE = 0X8A; IN1 = 1; IN2 = 0; IN3 = 1; IN4 = 0;
//初始化定时器高 8 位 //初始化定时器低 8 位 //启动定时器 T0 //开定时器 T0 中断,开总中断 //初始化 L293 的 IN1~IN4 引脚。
ENA = 1; //使能 OUT1、OUT2 ENB = 1; //使能 OUT3、OUT4 } /********************************************* 函数功能:延时 入口参数:Time 出口参数:无 备注:誰誰 2012 2 18 *********************************************/ void Delay(uchar Time) { uchar i=0,j=0; for(i=Time;i>0;i--) for(j=100;j>0;j--); } /********************************************* 函数功能:定时器 T0 中断服务函数(已验证) 入口参数:无 出口参数:无 备注:誰誰 2012 2 18 *********************************************/ void Timer0() interrupt 1 { Time_Count2++; ENA = 0; ENB = 0; if(Time_Count2==2) { ENA = 1; ENB = 1; /*设定时器初始值为 60000*/ TH0 = (65536-60000)/256; //重新载入定时器 TH0 初始值 TL0 = (65536-60000)%256; //重新载入定时器 TL0 初始值 Control_Wheels(); //控制轮子转速以实现转弯 Time_Count2 = 0;
15 / 18
电子科技协会--《电子实践制作教程》
} } /********************************************* 函数功能:定时器 T1 中断服务函数(已验证) 入口参数:无 出口参数:无 备注:誰誰 2012 2 18 *********************************************/ /*void Timer1() interrupt 3 { IN3 = !IN3; } */ #endif
16 / 18
单
片
机
下
载
口
电
电
排
针
电
电
排
针
排
针
电
机
驱
动
模
块
5.3 基于 C51 控制红外循迹小车原理图
排
针
电子科技协会--《电子实践制作教程》
17 / 18
排 针 排 针 小 系 统 红 外 检 测 模 块 基 于 红 外 循 迹 小 车 原 理 图 指 示 灯 模 块
排
针
单
片
机
最
排
针
圆
形
电
源
口
有
锁
开
关
稳
压
电
源
模
块
电子科技协会--《电子实践制作教程》
18 / 18
。