Hi,大家好,这里是丹成学长,今天向大家介绍一个 单片机项目
基于单片机的智能小车
大家可用于 课程设计 或 毕业设计
技术解答、毕设帮助、开题指导
print("Q 746876041")
智能化作为现代电子产品的新趋势, 是今后的电子产业的发展方向。智能化设计的电子产品可以按照预先设定的模式在一个环境里自动运作, 不需要人为的管理, 可应用于科学勘探、 环境监测、 智能家居等方面。 基于单片机的智能小车控制就是其中的一个体现。 本设计实现了一种基于 51 单片机的自动避障智能模型车系统, 通过红外传感器采集路况信息, 通过对检测信息的分析, 自动控制转向电机转向, 改变行驶路径, 绕过障碍物, 从而实现车稳定避障。
本设计学长采用直流减速电机, 电机专用驱动芯片L298N进行电机驱动控制, 主控芯片为STC89C52, 测距部分采用超声波模块, 控制器采用24L01无线电通信模块, 自动避障部分采用红外收发模块。
这个设计虽然只是学长的一个演示模型, 但是具有充分的科学性和实用性。 首先我们根据交通路面的复杂情况, 按照适当的比例制作出一个路况模型, 包括弯道、直道以及路面上设置的障碍物等。 在弯、 直道上, 小车沿着预定轨道自由行使,当小车遇到障碍物时, 脉冲调制的红外线传感器将检测到的信号发送给单片机,单片机根据程序发出相应的控制信号控制小车自动避开障碍物。 由无线模块控制小车进行倒车、 前进、 左转、 右转等动作。
小车的无线通信模块采用红外遥控, 红外收发遥控是目前大部份遥控小车采用的遥控手段, 红外遥控具有代码简单, 操作性强的特点。 如图为红外遥控模块实物图。
小车的通信模块采用无线电 NRF24L01 模块, NRF24L01 是一款工作在 2. 4~2. 5GHz, 世界通用 ISM 频段的单片无线收发器芯片。 无线收发器包括:频率发生器、 增强型 SchockburstTM 模式控制器、 功率放大器、 晶体振荡器、 调制器、 解调器。 输出功率、 频道选择和协议的设置可以通过 SPI 接口进行设置。如下图为 NRF24L01 无线模块实物图。
小车的电机驱动部分采用自己搭建的 9012 三极管电路来实行小车的驱动, 9012 三极管电路具有电路简单, 操作方便的等特点。
小车的电机驱动部分采用 L298N 芯片直流电机驱动模块, 该模块具有较大的驱动带载能力, 驱动部分端子供电范围 Vs: +5V~+35V, 并且另外自带了 5V、 3V 的输出端口。
方案论证
本设计为 4 轮驱动的小车, 对于小车驱动部分要求能够有较大的帯载能力, 并且在小车的实际设计过程中, 需要不同的输出电压来提供给小车的各个模块。 因此综上所述采用方案二, 小车的电机驱动部分使用 L298N 芯片直流电机驱动模块。
本设计主要分为两部分: 遥控部分和小车部分。 遥控部分主要由电源电路,单片机最小系统, 无线电模块组成, 遥控部分的系统框图如图所示。
小车部分由电源电路, 单片机最小系统, 显示电路, 无线电木块, 报警电路,超声波电路等电路模块组成, 小车部分的系统框图如图所示。
注意这里学长设计的是蓝牙通信方式的小车
1.4wd小车一台,包含马达,两个底盘,和螺丝等(要自己组装)
L298N电机驱动模块两个,用来控制马达的转速,方向,停止与否。
51单片机最小系统板一个和STC89C52RC芯片一个
HC-05蓝牙模块一个(蓝牙遥控)和usb转TTL转接模块一个(用于设置和调试蓝牙模块)
8650电池四个和18650电池盒和杜邦线若干。
一个L298N有四个输出口(out1,out2,out3,out4)接马达,每两个输出口控制一个马达,因此可以控制两个马达,12v接口接电源正极,5v接口是给最小系统板供电,所以5v接系统板5v口。
四个IO输入口(in1,in2,in3,in4)通过芯片控制输出口。两个使能端口(A,B),只有高电平时电机才有有效,低电平时电机不转转。因为有两个电机只有一个供电源所以两个电机要并联连接在一起。
下面是电机的控制表,当使能端位低电平(0)时电机处于停止状态,当输出口为(00或11)时处于制动状态,阻止电机转动。
L298N无效,无法驱动马达的原因(1.电压不够,起码要7v以上。2.使能端没有处于高电平状态 。3.L298N或马达坏了).
蓝牙的接线
蓝牙接在最小系统板,蓝牙的TXD(发送口)口接系统板的RXD(接收口)口,RXD口接TXD口也就是交叉连接,发送口对接收口。
在接在系统板之前,要对蓝牙进行一些设置(名称,密码,波特率),这时就要用到usb转TTL模块。
接在电脑上,打开串口调试助手(软件在后面的链接),进入AT模式 (进入方法,蓝牙模块上面有个按钮,在usb口插入电脑前,长按不放,插入电脑即可,如果看到蓝牙模块上的灯在快速闪烁,说明已经进入AT模式,慢闪是工作模式)。
红外的接线
红外模块的接线很简单,按照引脚上的说明,一一对应接在系统板上即可。
遥控部分主程序流程图如图所示。 程序从主函数开始执行, 无线蓝牙模块初始化, 同时在主函数中定义单片机口对应的按键按下时所发出的函数值。接下来判断是否有按键按下, 如果有按键按下, 则发送相应的按键对应的函数值,接着判断是否又有按键按下。 如果未发现按键按下则在主函数中循环判断是否有按键按下。
小车部分主程序流程图如图所示。
程序从主函数开始执行, 蓝牙无线模块初始化, 液晶显示模块初始化, 蓝牙无线电模块初始化, 超声波模块初始化。
各个模块初始化完毕后, 单片机判断是否接受到了信号, 如果接收到信号,则判断相应的按键值, 如果没有接收到按键值则返回继续判断是否接受到信号。接收到信号后, 小车开始执行键值对应的相应的命令。 而超声波测距, 并在液晶上显示相应距离, 危险距离报警都是贯穿在整个 while(1) 的语句中的。
/************************************************
作者:丹成学长,Q746876041
************************************************/
#include
#include
sbit LEA=P1^0;//左边轮的使能端A
sbit LEB=P1^1;//左边轮的使能端B
//左前轮
sbit LIN1=P1^2;//
sbit LIN2=P1^3;//
//左后轮
sbit LIN3=P1^4;
sbit LIN4=P1^5;
sbit REA=P3^2;//右边轮使能端A
sbit REB=P3^3;//右边轮使能端B
//右前轮
sbit RIN1=P3^4;
sbit RIN2=P3^5;
//右后轮
sbit RIN3=P3^6;
sbit RIN4=P3^7;
//方向控制
void delay(int time);//延时函数
void forward();//前进
void back();//后退
void stop();//停止
void start();//启动
void turnLeft();//左转
void turnRight();//右转
//蓝牙模块
//定时器1用作串口发生器,用于与蓝牙通信
void time1Init();//定时器1的初始化
void processMsg();//处理蓝牙接收到的信息
//红外模块
//从右到左
//in1是最右边的红外灯
sbit in1=P2^0;
sbit in2=P2^1;
sbit in3=P2^2;
sbit in4=P2^3;
int isTrace=0;//是否开启循迹功能
void trace();//红外循迹
//PWM调速
//通过控制使能端高低电平输出的时间从而控制速度
int count=0; //用于计数
int pwm=20; //表示启动的时间,20表示启动20ms
void time0Init();//定时器0的初始化.
//用于控制高低电平的时间
//定时器比较准确
void go();//启动 使能端为高电平 1
void pause();//停止 使能端为低电平 0
void time0Fun();//定时器0的中断函数
int main()
{
EA=1;//打开总中断
time1Init();//定时器1初始化
time0Init();//定时器0初始化
start();//使车的方向一开始向前
while(1)
{
if(isTrace)
trace();
if(count>=100) //100ms一个周期
count=0;
if(count<pwm) //pwm表示启动的时间
//pwm越大 速度越快
go();
else if(count>=pwm)
pause();
}
return 0;
}
void delay(int time)//延时函数
{
int i;
for(i=0;i<time;i++)
{
_nop_();//在晶振12M下
//一个nop函数延时1us
}
}
void forward()//前进
{
//前进,所有轮正转
LIN1=0;
LIN2=1;
LIN3=0;
LIN4=1;
RIN1=0;
RIN2=1;
RIN3=0;
RIN4=1;
}
void back()//后退
{
//前进,所有轮反转
LIN1=1;
LIN2=0;
LIN3=1;
LIN4=0;
RIN1=1;
RIN2=0;
RIN3=1;
RIN4=0;
}
void turnLeft()//左转
{
//左转 左边的轮正转,右边轮反转
LIN1=0;
LIN2=1;
LIN3=0;
LIN4=1;
RIN1=1;
RIN2=0;
RIN3=1;
RIN4=0;
delay(5000);//延时5ms 控制转弯的角度
}
void turnRight()//右转
{
//右转,左边轮反转,右边轮正转
LIN1=1;
LIN2=0;
LIN3=1;
LIN4=0;
RIN1=1;
RIN2=0;
RIN3=1;
RIN4=0;
delay(5000);//延时5ms 控制转弯的角度
}
void stop()//停止
{
//停止,全部高电平或低电平
LIN1=0;
LIN2=0;
LIN3=0;
LIN4=0;
RIN1=0;
RIN2=0;
RIN3=0;
RIN4=0;
}
void start()
{
forward();//一开始,前进方向
}
//定时器1用作串口发生器,用于与蓝牙通信
void time1Init()//定时器1的初始化
{
TMOD=0x20;//定时器1,工作模式2,8位自动重装模式
TH1=0xfd;//9600波特率,要与蓝牙的一致
TL1=0xfd;
//串口通信方式1
SM0=0;
SM1=1;
PCON=0x00;//波特率不加倍
SCON=0x50;//工作方式一
REN=1;//允许接收
ES=1;//开启串口中断
TR1=1;//启动定时1
}
void processMsg() interrupt 4 //中断4
//处理蓝牙接收到的信息
{
char ch;
//等待接收完毕
while(!RI)//当RI为0时没有接收完毕
; //为1时接收完毕
//信息存存在sbuf中
ch=SBUF;//获取接收的信息
switch(ch)
{
case 'f': //前进
forward();
break;
case 'b': //后退
back();
break;
case 'l': //左转
turnLeft();
break;
case 'r': //右转
turnRight();
break;
case 's': //停止
stop();
break;
case 'o':
start();
break;//启动
case 't': //开启循迹功能
isTrace=1;
break;
case '1': //一档
pwm=20;
break;
case '2': //二档
pwm=60;
break;
case '3': //三档
pwm=100;
break;
default:
break;
}
}
void trace()//红外循迹
{
//当红外遇到黑线时吸收红外光,输出高电平
//遇到白线时反射红外,输出低电平
int dir=0;//0表示直走
//1 代表左转
//2 代表右转
//0 0 0 0
if(in1==0&&in2==0&&in3==0&&in4==0)
dir=0;
//1 0 0 0
else if (in1==1&&in2==0&&in3==0&&in4==0)
dir=2;
//1 1 0 0
else if (in1==1&&in2==1&&in3==0&&in4==0)
dir=2;
//1 1 1 0
else if (in1==1&&in2==1&&in3==1&&in4==0)
dir=0;
//1 1 1 1
else if (in1==1&&in2==1&&in3==1&&in4==1)
dir=0;
//0 1 0 0
else if (in1==0&&in2==1&&in3==0&&in4==0)
dir=2;
//0 1 1 0
else if (in1==0&&in2==1&&in3==1&&in4==0)
dir=0;
//0 1 1 1
else if (in1==0&&in2==1&&in3==1&&in4==1)
dir=1;
//0 0 1 0
else if (in1==0&&in2==0&&in3==1&&in4==0)
dir=1;
//0 0 1 1
else if (in1==0&&in2==0&&in3==1&&in4==1)
dir=1;
//1 0 1 0
else if (in1==1&&in2==0&&in3==1&&in4==0)
dir=1;
//1 1 1 0
else if (in1==1&&in2==1&&in3==1&&in4==0)
dir=2;
//1 0 1 1
else if (in1==1&&in2==0&&in3==1&&in4==1)
dir=0;
//1 0 0 1
else if (in1==1&&in2==0&&in3==0&&in4==1)
dir=0;
//0 0 0 1
else if (in1==0&&in2==0&&in3==0&&in4==1)
dir=1;
//1 1 0 1
else if (in1==1&&in2==1&&in3==0&&in4==1)
dir=0;
switch(dir)
{
case 0:
forward();
break;
case 1:
turnLeft();
break;
case 2:
turnRight();
break;
}
}
void time0Init()//定时器0的初始化.
//用于控制高低电平的时间
//定时器比较准确
{
TMOD|=0x01;//工作方式一
//用或运算是为了不改变
//定时器1对应位的值。
TH0=0xfc;
TL0=0x66; //定时1ms
ET0=1;//开启定时器0的中断
TR0=1;//启动定时器0
}
void go()//启动 使能端为高电平 1
{
LEA=1;
LEB=1;
REA=1;
REB=1;
}
void pause()//停止 使能端为低电平 0
{
LEA=0;
LEB=0;
REA=0;
REB=0;
}
void time0Fun() interrupt 1
{
TH0=0xfc;
TL0=0x66;
//1ms 中断一次,count加一
count++;
}
/*******************************************************************
篇幅有限,只展示部分代码
作者:丹成学长,Q746876041
********************************************************************/
技术解答、毕设帮助、开题指导
print("Q 746876041")
单片机毕设项目大全:
https://blog.csdn.net/huawei123444/article/details/119822845