标题:
基于单片机的智能小车的设计 附程序
[打印本页]
作者:
ljl8970
时间:
2020-1-14 17:47
标题:
基于单片机的智能小车的设计 附程序
基于单片机的智能小车的设计,还包括小车源码,功能齐全
硬件组成:电机模块是智能小车的整个动力系统,智能上车上搭载了一颗L293D双H桥路电机驱动芯片及2个减速电机,车轮为65mm防滑车轮。
工作原理:通过开发板输出控制信号给L293D,由L293D驱动左右2个减速马达正传或反转来实现小车的前后左右行驶动作。
将我们准备好的 6P 杜邦线接头按照排线原有颜色顺序整理成一排,一端接插至智能小车底板 J10 排针上,另一端根据 J10 排针标注的引脚丝印对应顺序接插至开发板的 P12~P17排针。
51hei.png
(50.75 KB, 下载次数: 24)
下载附件
2020-1-20 14:30 上传
3.4蓝牙模块设计
蓝牙模块主要为了实现数据传输,本设计是通过蓝牙转串口模块,实现无线通讯功能,所以本质上使用的是单片机串口通信。
蓝牙模块支持短距离无线传输,可以通过手机与蓝牙模块的配对实现对小车的无线控制。本小车采用的是BT-06蓝牙芯片,在BT-06蓝牙芯片,在BT-06芯片里已经将蓝牙协议封装好,只需要通过串口通信实现上位机(手机)与下位机(51单片机)的无线通信。
串行通信的特点是:数据按比特顺序传输,至少可以通过一条传输线即可完成,成本低,传输速度慢。串行通信的范围可以从几米到几公里。根据信息传输的方向,串行通信可以进一步分为三中类型:单、半双工和全双工。信息智能单向传输的为单工;能双向传递但不能同时双向传送的称为半双工;信息能够同时双向传送则成为全双工。串行通信可分为异步通信和同步通信。在单片机中,主要采用异步通信。
3.5PCB图设计
在电路原理图设计完成后,根据布线原理布置元件,布线,最后布置铜和撕裂。
焊接芯片的步骤:
1.将芯片平放在PCB板上,将芯片引脚对准焊盘然后用手指按住;
2.将芯片的两个对角焊牢;
3.在芯片的四周上适量焊锡;
4.将PCB板向着焊接引脚的方向下倾斜45度,用松香去掉烙铁头端多余的焊锡;
5.把粘有松香的焊铁头放在焊锡的部分;
6.来回拖动烙铁,将焊锡均匀的布在芯片的引脚上;
7.重复上述步骤焊接芯片的另外的引脚,如果发现引脚间有多余的焊锡就用吸锡丝将多余的焊锡吸掉。
3.6智能车结构分析
在本次设计中,小车使用双驱动,采用双轮+定向轮式的结构,来驱动小车做出相应的指令,定向轮有效的防止了方向偏移的问题,且双驱动两轮驱动式,动力更大,爬坡能力更强,整体性能优势明显,同事底盘的设计比较合理能够更大程度的发挥其空间,充分利用其空间结构进行不同模块的添加。
3.6.1底板设计
底盘是用来支撑车体的主要部件。同时也是用来固定车子零部件的,底板上主要有电机定位安装槽和走位孔,电池盒安装槽位,定向轮安装孔,电压检测模块安装槽,超声波模块安装槽位以及开发板安装槽位等拓展槽位。安装方便,结构可靠稳定。
3.6.2电机与底板的连接支架设计
电机主要通过将固定片固定在底板上的,每个电机用两块固定片绑定固定,通过槽孔和圆孔来绑定电机,利用螺丝及螺母进行固定安装。
首先,我们把 1 片固定片从智能小车底板电机旁接口穿入,接着再拿 1 片固定片贴在直流电机安装孔旁并穿入 2 只长螺丝,注意固定片与电机的组装方向。其次,我们把电机安装到指定位置,最后,我们把 2 个螺母分别拧上即可。
3.6.3整体装配图
3.6.4整车材料明细
整车包括:51开发板,智能小车底板,防滑车轮,蓝牙模块,减速电动机等组成,本次采用的双轮+定向轮驱动模式,结构复杂程度适中,并有效的避免了行进当中的方向偏向问题。
注意事项:5号锂电池初次使用时请先进行充电,注意电池极性切勿装反,当充电器绿灯亮起时表示电池电量已充满。充电时必须有人值守,避免发生意外。
电池盒电源线与智能小车底板电源接口连接时请将其缓和接入 J1 端子头,电源线的红线在 J1 端子头丝印为“+”一侧,黑线在 J1 端子头丝印为“-”一侧。
因为智能小车红外发射装置和电机等负载功耗大,所以智能小车累计行驶 10~20 分钟后请对电池进行充电。智能小车不使用的时请取下电池,电池长期闲置时请充满电。当电源电压小于 5V 时智能小车无法正常工作,请及时给供电电池充电,配送的锂电池电量不能用完,低于 4V 时必须充电,电量用完电池将会报废,配送电池充满状态电压为 7.2V~8V 左右。
智能小车不使用时请关闭智能小车电源,由于智能小车上红外避障和寻迹模块工作时功耗较大会造成电池放电量大。
单片机源程序如下:
#include <reg52.h> //51头文件
#include <intrins.h> //包含nop等系统函数
#include <QXA51.h>//QX-A51智能小车配置文件
unsigned char pwm_left_val = 140;//左电机占空比值 取值范围0-170,0最快
unsigned char pwm_right_val = 150;//右电机占空比值取值范围0-170 ,0最快
unsigned char pwm_t;//周期
unsigned char control=0X01;//车运动控制全局变量,默认开机为停车状态
/******************************
超声波定义
*******************************/
sbit RX = P2^0;//ECHO超声波模块回响端
sbit TX = P2^1;//TRIG超声波模块触发端
unsigned int time = 0;//传输时间
unsigned long S = 0;//距离
bit flag = 0;//超出测量范围标志位
void Delay10us(unsigned char i) //10us延时函数 启动超声波模块时使用
{
unsigned char j;
do{
j = 10;
do{
_nop_();
}while(--j);
}while(--i);
}
void delay(unsigned int z)//毫秒级延时
{
unsigned int x,y;
for(x = z; x > 0; x--)
for(y = 114; y > 0 ; y--);
}
/*小车前进*/
void forward()
{
left_motor_go; //左电机前进
right_motor_go; //右电机前进
}
/*小车左转*/
void left_run()
{
left_motor_stops; //左电机停止
right_motor_go; //右电机前进
}
/*小车右转*/
void right_run()
{
right_motor_stops;//右电机停止
left_motor_go; //左电机前进
}
/*PWM控制使能 小车后退*/
void backward()
{
left_motor_back; //左电机后退
right_motor_back; //右电机后退
}
/*PWM控制使能 小车高速右转*/
void right_rapidly()
{
left_motor_go;
right_motor_back;
}
/*小车高速左转*/
void left_rapidly()
{
right_motor_go;
left_motor_back;
}
//小车停车
void stop()
{
left_motor_stops; //左电机后退
right_motor_stops; //右电机后退
}
void keyscan()
{
for(;;) //死循环
{
if(key_s2 == 0)// 实时检测S2按键是否被按下
{
delay(5); //软件消抖
if(key_s2 == 0)//再检测S2是否被按下
{
while(!key_s2);//松手检测
beep = 0; //使能有源蜂鸣器
delay(200);//200毫秒延时
beep = 1; //关闭有源蜂鸣器
break; //退出FOR死循环
}
}
}
}
//初始化
void Init(void)
{
EA = 1; //开总中断
SCON |= 0x50; // SCON: 模式1, 8-bit UART, 使能接收
T2CON |= 0x34; //设置定时器2为串口波特率发生器并启动定时器2
TL2 = RCAP2L = (65536-(FOSC/32/BAUD)); //设置波特率
TH2 = RCAP2H = (65536-(FOSC/32/BAUD)) >> 8;
ES= 1; //打开串口中断
TMOD |= 0x01;//定时器0工作模块1,16位定时模式。T0用测ECH0脉冲长度
TH0 = 0;
TL0 = 0;//T0,16位定时计数用于记录ECHO高电平时间
ET0 = 1;//允许定时器0中断
TMOD |= 0x20; //定时器1,8位自动重装模块
TH1 = 220;
TL1 = 220; //11.0592M晶振下占空比最大比值是256,输出100HZ
TR1 = 1;//启动定时器1
ET1 = 1;//允许定时器1中断
}
/**************************************************
超声波程序
***************************************************/
void StartModule() //启动超声波模块
{
TX=1; //启动一次模块
Delay10us(2);
TX=0;
}
/*计算超声波所测距离*/
void Conut(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(float)(time*1.085)*0.17; //算出来是MM
if((S>=7000)||flag==1) //超出测量范围
{
flag=0;
}
}
/*超声波避障*/
void Avoid()
{
if(S < 400)//设置避障距离 ,单位毫米 刹车距离
{
stop();//停车
backward();//后退
delay(100);//后退时间越长、距离越远。后退是为了留出车辆转向的空间
do{
left_rapidly();//高速左转
delay(90);//时间越长 转向角度越大,与实际行驶环境有关
stop();//停车
delay(100);//时间越长 停止时间越久长
StartModule(); //启动模块测距,再次判断是否
while(!RX); //当RX(ECHO信号回响)为零时等待
TR0=1; //开启计数
while(RX); //当RX为1计数并等待
TR0=0; //关闭计数
Conut(); //计算距离
}while(S < 280);//判断前面障碍物距离
}
else
{
forward();//前进
}
}
//黑线寻迹
void BlackLine()
{
//为0 没有识别到黑线 为1识别到黑线
if(left_led1 == 1 && right_led1 == 1)//左右寻迹探头识别到黑线
{
forward();//前进
}
else
{
if(left_led1 == 1 && right_led1 == 0)//小车右边出线,左转修正
{
left_run();//左转
}
if(left_led1 == 0 && right_led1 == 1)//小车左边出线,右转修正
{
right_run();//右转
}
if(left_led1 == 0 && right_led1 == 0)//左右寻迹探头都没识别到黑线
{
backward();//后退
}
}
}
//红外避障
void IRAvoid()
{
//为0 识别障碍物 为1没有识别到障碍物
if(left_led2 == 1 && right_led2 == 1)//左右都没识别到障碍物
{
pwm_left_val = 140;//左电机占空比值 取值范围0-170,0最快
pwm_right_val = 150;//右电机占空比值取值范围0-170 ,0最快
forward();//前进
}
if(left_led2 == 1 && right_led2 == 0)//小车右侧识别到障碍物,左转躲避
{
pwm_left_val = 180;//左电机占空比值 取值范围0-170,0最快
pwm_right_val = 110;//右电机占空比值取值范围0-170 ,0最快
left_run();//左转
delay(40);//左转40毫秒(实现左小弯转)
}
if(left_led2 == 0 && right_led2 == 1)//小车左侧识别到障碍物,右转躲避
{
pwm_left_val = 100;//左电机占空比值 取值范围0-170,0最快
pwm_right_val = 180;//右电机占空比值取值范围0-170 ,0最快
right_run();//右转
delay(40);//右转40毫秒(实现右小弯转)
}
if(left_led2 == 0 && right_led2 == 0) //小车左右两侧都识别到障碍物,后退掉头
{
pwm_left_val = 150;//左电机占空比值 取值范围0-170,0最快
pwm_right_val = 160;//右电机占空比值取值范围0-170 ,0最快
backward();//后退
delay(100);//后退的时间影响后退的距离。后退时间越长、后退距离越远。
pwm_left_val = 140;//左电机占空比值 取值范围0-170,0最快
pwm_right_val = 150;//右电机占空比值取值范围0-170 ,0最快
right_rapidly();//高速右转
delay(180);//延时时间越长,转向角度越大。
}
}
//超声波避障
void Ultrasonic()
{
StartModule(); //启动模块测距
while(!RX); //当RX(ECHO信号回响)为零时等待
TR0=1; //开启计数
while(RX); //当RX为1计数并等待
TR0=0; //关闭计数
Conut(); //计算距离
Avoid(); //避障
delay(65); //测试周期不低于60MS
}
//红外物体跟随
void IRTracking()
{
//为0 识别障碍物 为1没有识别到障碍物
if(left_led2 == 0 && right_led2 == 0)//左右识别到障碍物,前进跟随
{
forward();//前进
}
if(left_led2 == 1 && right_led2 == 0)//小车右侧识别到障碍物,右转跟随
{
right_run();//右转
}
if(left_led2 == 0 && right_led2 == 1)//小车左侧识别到障碍物,左转跟随
{
left_run();//左转
}
}
void main()
{
keyscan();//等待按下S2启动小车
delay(1000);//延时1秒
Init();//定时器、串口初始化
while(1)
{
if(control>0X17)//如果成立,则表示接收的命令不在运行命令内
{
stop(); // 停车
}
switch(control)
{
case 0X02: forward(); break; //前进
case 0X03: backward(); break; //后退
case 0X04: left_run(); break; //左转
case 0X05: right_run(); break;//右转
case 0X01: stop(); break;//停车
case 0X06: left_rapidly(); break;//左旋转
case 0X07: right_rapidly(); break;//右旋转
case 0X08: beep = 0; break;//鸣笛
case 0X09: beep = 1; break;//停止鸣笛
case 0X11: Ultrasonic(); break;//超声波避障
case 0X12: BlackLine(); break;//黑线寻迹
case 0X13: IRAvoid(); break;//红外避障
case 0X15: IRTracking(); break;//红外-跟随物体
}
}
}
//定时器0中断
void timer0() interrupt 1
{
flag=1; //中断溢出标志
}
void timer1() interrupt 3 //T1中断用来计数器溢出
{
pwm_t++;//周期计时加
if(pwm_t == 255)
pwm_t = EN1 = EN2 = 0;
if(pwm_left_val == pwm_t)//左电机占空比
EN1 = 1;
if(pwm_right_val == pwm_t)//右电机占空比
EN2 = 1;
}
/******************************************************************/
/* 串口中断程序*/
/******************************************************************/
void UART_SER () interrupt 4
{
unsigned char n; //定义临时变量
if(RI) //判断是接收中断产生
{
RI=0; //标志位清零
n=SBUF; //读入缓冲区的值
control=n;
if((n >= 51) && (n <= 150))//左电机调速0~100个档位 手机端软件进行调节
pwm_left_val = 170-((n-50)*1.7);
if((n >= 151) && (n <= 250)) //右电机调速0~100个档位 手机端软件进行调节
pwm_right_val = 170-((n-150)*1.7);
}
}
复制代码
所有资料51hei提供下载:
小车程序.7z
(1.73 MB, 下载次数: 50)
2020-1-20 14:34 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
wngqiuchang
时间:
2022-3-14 11:22
有没有原理图噢
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1