文章目录
一.小车需要的材料
一个超声波模块,一个180度舵机模块,3节串联的18650电池盒和电池,一个L298N电机驱动模块,一个小面包板,51单片机,小车的模板 ,一个五路循迹循迹模块,两个红外避障模块。
二.小车电机与L298N电机驱动的接线以及单片机接线
图一中电机靠里面的线我称为电机上,靠地板那面我称为电机下,图2中是驱动电机与电机的连接方式,图3是单片机的接线,图4是连接实物图,图5是驱动电机的介绍图,电源的线尽量用硅胶线,不然容易烧。
图1
图2
图3
图4
图5
三.L298N驱动电机的方法和代码
3.1 L298N驱动电机方法
下图1的IN1——IN4分别对应OUT1——OUT4,IN1——IN4分别接在51单片机的P32,P33,P34,P35的IO口;L298N不调速情况下,是全速运行的,如果需要调速度,则使用PWM调速,占空比(高电平)越高,则速度越快,因为电机的转速不可能完全一样,会有摩擦力等等的干扰,所以如果不使用pid进行调速就只能用PWM,这个阶段用PWM即可,上图的L298N介绍图中,通道A使能对应的是IN1和IN2,通道使能B对应的是IN3和IN4,如下图2红圈位置接到单片机P05和P04的IO口中。
图1
图2
3.2 L298N驱动电机代码
//小车前进代码
#include <REGX52.H>
#include "INTRINS.H"
sbit IN1=P3^2;
sbit IN2=P3^3;
sbit IN3=P3^4;
sbit IN4=P3^5;
void Go_Head()
{
IN1=1;
IN2=0;
IN3=1;
IN4=0;
}
void main()
{
while(1)
{
Go_Head();
}
}
//小车后退
#include <REGX52.H>
#include "INTRINS.H"
sbit IN1=P3^2;
sbit IN2=P3^3;
sbit IN3=P3^4;
sbit IN4=P3^5;
void Go_Back()
{
IN1=0;
IN2=1;
IN3=0;
IN4=1;
}
void main()
{
while(1)
{
Go_Back();
}
}
//小车左转
#include <REGX52.H>
#include "INTRINS.H"
sbit IN1=P3^2;
sbit IN2=P3^3;
sbit IN3=P3^4;
sbit IN4=P3^5;
void Go_Left()
{
IN1=0;
IN2=0;
IN3=1;
IN4=0;
}
void main()
{
while(1)
{
Go_Left();
}
}
//小车右转
#include <REGX52.H>
#include "INTRINS.H"
sbit IN1=P3^2;
sbit IN2=P3^3;
sbit IN3=P3^4;
sbit IN4=P3^5;
void Go_Right()
{
IN1=1;
IN2=0;
IN3=0;
IN4=0;
}
void main()
{
while(1)
{
Go_Right();
}
}
//使用PWM进行调速
#include <REGX52.H>
#include "INTRINS.H"
sbit IN1=P3^2;
sbit IN2=P3^3;
sbit IN3=P3^4;
sbit IN4=P3^5;
sbit ENA=P0^5;
sbit ENB=P0^4;
unsigned char count,compare1,compare2;
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Timer0Init(void) //100微秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xA4; //设置定时初值
TH0 = 0xFF; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
PT0=0;
}
void Go_Head()
{
IN1=1;
IN2=0;
IN3=1;
IN4=0;
}
void main()
{
Timer0Init();
while(1)
{
Go_Head();
}
}
void Timer0_Rountime() interrupt 1
{
TL0 = 0xA4; //设置定时初值
TH0 = 0xFF; //设置定时初值
compare1=87;//左轮,100则速度最大
compare2=89;//右轮,100则速度最大
count++;
if(count>=100) //10ms
{
count=0;
}
if(count<compare1)
{
ENA=1;
}
else
{
ENA=0;
}
if(count<compare2)
{
ENB=1;
}
else
{
ENB=0;
}
}
四.串口或者蓝牙点击方式(HC_08)控制小车代码
如果用51最小开发板,车运行的时候,晶振可能抖动有问题会松,小车也运行不了。
Timer0.h
#ifndef TIMER0__H__
#define TIMER0__H__
void Timer0Init(void);
#endif
Timer0.c
#include <REGX52.H>
sbit ENA=P0^5;
sbit ENB=P0^4;
unsigned char count;
unsigned char speed=100;
void Timer0Init(void) //100微秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xA4; //设置定时初值
TH0 = 0xFF; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
PT0=0;
}
void Timer0_Rountime() interrupt 1
{
TL0 = 0xA4; //设置定时初值
TH0 = 0xFF; //设置定时初值
count++;
if(count==100) //10ms
{
count=0;
}
if(count<speed)
{
ENA=1;
ENB=1;
}
if(count>=speed)
{
ENA=0;
ENB=0;
}
}
Uart.h
#ifndef __MOTOR_H__
#define __MOTOR_H__
void UartInit(void); //9600bps@11.0592MHz
#endif
Uart.c
#include <REGX52.H>
#include "Motor.h"
#include <string.h>
sfr AUXR=0X8E;
char buffer[3];
void UartInit()
{
AUXR =0x01;
SCON = 0x50;//配置串口1,REN使能不接收,串口模式
TMOD &= 0x0F;//定时器模式
TMOD |= 0x20;
TH1 = 0xFD;//9600波特率的初值
TL1 = 0xFD;
TR1 = 1;//开始计时
ET1 = 0;//禁止定时器中断
ES =1;//串口中断开启
EA =1;
}
void Uart_Rountime() interrupt 4
{
static int i=0;
char temp;
if(RI==1)//中断处理函数,对于接收中断的响应
{
RI=0;
temp=SBUF;
if(temp=='M')
{
i=0;
}
buffer[i++]=temp;
if(buffer[0]=='M')
{
switch(buffer[1])//第一次buffer[0]='M',还没到buffer[1],所以不执行switch,第二次上面赋予buffer[1]值的时候才进入switch
{
case '1':Go_Head();break;
case '2':Go_Back();break;
case '3':Go_Left();break;
case '4':Go_Right();break;
case '5':Stop();break;
case '6':increase();break;
case '7':reduce();break;
}
}
if(i==3)
{
i=0;
memset(buffer,'\0',3);
}
}
}
Motor.h
#ifndef __MOTOR_H__
#define __MOTOR_H__
void Go_Left(void);
void Go_Right(void);
void Go_Back(void);
void Go_Head(void);
void Stop(void);
void increase(void);
void reduce(void);
#endif
Motor.c
#include <REGX52.H>
#include "Timer0.h"
sbit IN1=P3^2;
sbit IN2=P3^3;
sbit IN3=P3^4;
sbit IN4=P3^5;
extern unsigned char speed;
void Go_Left()
{
IN1=0;
IN2=0;
IN3=1;
IN4=0;
}
void Go_Right()
{
IN1=1;
IN2=0;
IN3=0;
IN4=0;
}
void Go_Back()
{
IN1=0;
IN2=1;
IN3=0;
IN4=1;
}
void Go_Head()
{
IN1=1;
IN2=0;
IN3=1;
IN4=0;
}
void Stop()
{
IN1=0;
IN2=0;
IN3=0;
IN4=0;
}
void increase(void)//加速
{
speed += 5; // 每次增加5
if(speed >= 100) // 上限是100
{
speed = 100;
}
}
void reduce(void)//减速
{
speed -= 5; // 每次减少5
if(speed <= 0) // 下限是0
{
speed = 0;
}
}
main.c
#include <REGX52.H>
#include "Uart.h"
#include "Motor.h"
#include "Timer0.h"
void main()
{
UartInit();
Timer0Init();
while(1)
{
}
}
下面四张图就是蓝牙控制小车,先打开设置方向按钮,设置好后,再关闭,小车动的过程,如果是最小开发板,晶振很可能抖动出问题,容易点没反应,在插一次晶振就好了,用最小开发板串口进行通信的话,电池需要拆下来一个,等通信完成在插上去。
五.循迹小车基本原理
5.1五路循迹模块图片
5.2 循迹模块介绍
五路循迹模块探测距离短,所以调试的时候让他对着白色区域看看led全部是否亮着,亮着说明距离合适,传感器放的位置也很重要,尽量在下图照片位置,放很出的话效果不好。
5.3 循迹模块的原理
当探头的红外发射管发射光线经地面反射进入接收管。输出端输出(out)高电平,主板对应的led灯亮(OUT1-OUT4分别对应D1-D4的led灯)。如果地面有黑色区域将吸收光线,接收管接收不到光线输出端就会输出低电平,主板的led灯会不点亮。
5.4 赛道的宽度
除了买的赛道,如果想自己做的话,建议黑线两个手指的宽度大小,不然传感器容易反应不过来跑飞出去,然后电压的大小也会影响小车循迹效果,可以买个充电器给电池充电,充满了在调试。
5.5 循迹小车代码
如果用51最小开发板,车运行的时候,晶振可能抖动有问题会松,小车也运行不了
main.c
#include <reg52.h>
#include "Motor.h"
#include "Timer0.h"
#include "xunji.h"
void main()
{
Timer0Init();
while(1)
{
xunji();
}
}
Timer0.h
#ifndef TIMER0__H__
#define TIMER0__H__
void Timer0Init(void);
#endif
Timer0.c
#include <reg52.h>
sbit ENA=P0^5;
sbit ENB=P0^4;
unsigned char i,j;
unsigned char PWMA,PWMB;//A是左轮,B是右轮
void Timer0Init(void) //100微秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xA4; //设置定时初值
TH0 = 0xFF; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
PT0=0;
}
void Timer0_Rountime() interrupt 1
{
TL0 = 0xA4; //设置定时初值
TH0 = 0xFF; //设置定时初值
i++;
j++;
if(i<PWMA)
{
ENA=1;
}
else
{
ENA=0;
if(i>=100)
{
i=0;
}
}
if(j<PWMB)
{
ENB=1;
}
else
{
ENB=0;
if(j>=100)
{
j=0;
}
}
}
Motor.h
#ifndef __MOTOR_H__
#define __MOTOR_H__
void Go_Left(void);
void Go_Left1(void);
void Go_Right(void);
void Go_Right1(void);
void Go_Head(void);
void Stop(void);
#endif
Motor.c
#include <reg52.h>
#include "Timer0.h"
sbit IN1=P3^2;
sbit IN2=P3^3;
sbit IN3=P3^4;
sbit IN4=P3^5;
extern unsigned char PWMA,PWMB;
void Go_Left()//正转的速度大于反转
{
IN1=0;
IN2=1;//左轮反转
PWMA=35;
IN3=1;
IN4=0;
PWMB=50;//右轮正转
}
void Go_Left1()
{
IN1=0;
IN2=1;
PWMA=50;
IN3=1;
IN4=0;
PWMB=65;
}
void Go_Right()
{
IN1=1;
IN2=0; //左轮正转
PWMA=50;//左边速度
IN3=0;
IN4=1; //右轮反转
PWMB=35;//右边速度
}
void Go_Right1()
{
IN1=1;
IN2=0;
PWMA=65;
IN3=0;
IN4=1;
PWMB=50;
}
void Go_Head()
{
IN1=1;
IN2=0;
PWMA=25;
IN3=1;
IN4=0;
PWMB=25;
}
void Stop()
{
IN1=0;
IN2=0;
PWMA=0;
IN3=0;
IN4=0;
PWMB=0;
}
xunji.h
#ifndef __XUNJI_H__
#define __XUNJI_H__
void xunji(void);
#endif
xunji.c
#include <reg52.h>
#include "Motor.h"
sbit D1=P1^1;
sbit D2=P1^2;
sbit D3=P1^3;
sbit D4=P1^4;
sbit D5=P1^5;
void xunji()
{
unsigned char flag =0;
if(D1 ==1 && D2 == 1 && D3==0 && D4 ==1 && D5 ==1)//中间检测到黑线
{
flag=0;
}
if(D1 ==1 && D2 == 1 && D3==1 && D4 ==1 && D5 ==1)//全部未检测到黑线
{
flag=0;
}
if(D1 ==1 && D2 == 0 && D3 ==1 && D4 ==1 && D5==1)//左边内测侧检测到黑线,小车缓慢向左移动
{
flag=1;
}
if(D1 ==1 && D2 == 0 && D3 ==0 && D4 ==1 && D5==1)//左边内测和中间侧检测到黑线,小车缓慢向左移动
{
flag=1;
}
if(D1 ==0 && D2 == 1 && D3 ==1 && D4 ==1 && D5==1)//左边外测侧检测到黑线,小车大幅度向左移动
{
flag=2;
}
if(D1 ==0 && D2 == 0 && D3 ==1 && D4 ==1 && D5 == 1)//左边内外侧检测到黑线,小车大幅度向左移动
{
flag=2;
}
if(D1 ==0 && D2 == 0 && D3 ==0 && D4 ==1 && D5 == 1)//左边内外侧和中间检测到黑线,小车大幅度向左移动
{
flag=2;
}
if(D1 ==1 && D2 == 1 && D3 ==1 && D4 ==0 && D5 ==1)//右边内测侧检测到黑线,小车缓慢向右移动
{
flag=3;
}
if(D1 ==1 && D2 == 1 && D3 ==0 && D4 ==0 && D5 ==1)//右边内测和中间侧检测到黑线,小车缓慢向右移动
{
flag=3;
}
if(D1 ==1 && D2 ==1 && D3 ==1 && D4 ==1 && D5 ==0)//右边外侧检测到黑线,小车大幅度向右移动
{
flag=4;
}
if(D1 ==1 && D2 == 1 && D3 ==1 && D4 ==0 && D5 ==0)//右侧内外检测到黑线,小车大幅度右转
{
flag=4;
}
if(D1 ==1 && D2 == 1 && D3 ==0 && D4 ==0 && D5 ==0)//右侧内外和中间检测到黑线,小车大幅度右转
{
flag=4;
}
if(D1 ==0 && D2 == 0 && D3 ==0 && D4 ==0 && D5 ==0)//全部检测到黑线时,停车
{
flag=5;
}
switch(flag)
{
case 0:Go_Head();break;
case 1:Go_Left();break;
case 2:Go_Left1();break;
case 3:Go_Right();break;
case 4:Go_Right1();break;
default:Stop();break;
}
}
5.6 循迹小车效果
六.跟随小车
6.1 红外避障模块图片
6.2 红外避障模块原理
(1).上面有旋转按钮可以调节红外避障的灵敏度(红外发射距离),当发出红外线时,返回红外线的话,模块输出低电平,当发射红外线时,没有返回红外线的话,模块输出高电平。
(2).左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转,右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转。
6.3 跟随小车代码
mian.c
#include <reg52.h>
#include "Motor.h"
sbit leftsensor=P1^7; //左边红外模块
sbit rightsensor=P1^6;//右边红外模块
void main()
{
while(1)
{
if(leftsensor == 0 && rightsensor == 0)
{
Go_Head();
}
if(leftsensor == 1 && rightsensor == 0)
{
Go_Right();
}
if(leftsensor == 0 && rightsensor == 1)
{
Go_Left();
}
if(leftsensor == 1 && rightsensor == 1)
{
Stop();
}
}
}
Motor.c
#include <REGX52.H>
sbit IN1=P3^2;
sbit IN2=P3^3;
sbit IN3=P3^4;
sbit IN4=P3^5;
void Go_Left()
{
IN1=0;
IN2=0;
IN3=1;
IN4=0;
}
void Go_Right()
{
IN1=1;
IN2=0;
IN3=0;
IN4=0;
}
void Go_Head()
{
IN1=1;
IN2=0;
IN3=1;
IN4=0;
}
void Stop()
{
IN1=0;
IN2=0;
IN3=0;
IN4=0;
}
Motor.h
#ifndef __MOTOR_H__
#define __MOTOR_H__
void Go_Left(void);
void Go_Right(void);
void Go_Head(void);
void Stop(void);
#endif
6.4 跟随小车效果
待更新…