智能小车的制作是学习51单片机中一个很重要的过程,下面是自己完成小车的一点心得,在这里和大家分享。
代码如下:
#include <reg51.h> //IO引脚定义:
sbit key1 = P3^7; //定义按键1
sbit key2 = P3^6; //定义按键2
sbit key3 = P3^5; //定义按键3
sbit key4 = P3^4; //定义按键4
sbit L_WXJ=P2^1; //四路寻迹模块接口第四路,左外录迹
sbit R_WXJ=P2^3; //四路寻迹模块接口第一路,右外寻迹
sbit IN1=P3^0;
sbit IN2=P3^1;
sbit IN3=P1^2;
sbit IN4=P1^3;
sbit IN11=P2^6;
sbit IN22=P2^7;
sbit IN33=P0^2;
sbit IN44=P0^3;
sbit L_PWM=P1^4; //左轮调速,接驱动模块ENA使能端,在这里输入PWM信号
sbit R_PWM=P1^6; //右轮调速,接驱动模块ENB使能端,在这里输入PWM信号
sbit L_PWM1=P0^4; //左轮调速,接驱动模块ENA使能端,在这里输入PWM信号
sbit R_PWM1=P0^5; //右轮调速,接驱动模块ENB使能端,在这里输入PWM信号
//宏定义
#define L_go IN1=0;IN2=1; //左轮前进
#define L1_go IN33=0;IN44=1; //左轮前进
#define L_back IN1=1;IN2=0; //左轮后退
#define L1_back IN33=1;IN44=0; //左轮后退
#define R_go IN3=0;IN4=1; //右轮前进
#define R1_go IN11=0;IN22=1; //右轮前进
#define R_back IN3=1;IN4=0; //右轮后退
#define R1_back IN11=1;IN22=0; //右轮后退
#define car_go L_go;R_go; //小车前进
#define car_go1 L1_go;R1_go;
#define car_back L_back;R_back //小车后退
#define car_back1 L1_back;R1_back;
#define car_left R_go;L_back
#define car_left1 R1_go;L1_back //小车左转弯
#define car_right L_go;R_back //小车右转弯
#define car_right1 L1_go;R1_back
#define car_stop L_stop;R_stop;L_stop;R_stop; //小车停车
//数据定义
unsigned char l_tt=0; //定时器计数用
unsigned char l_Lpwm=0; //左轮PWM占空比值,我们设计3个格,0-2,0为停止,2为全速
unsigned char l_Rpwm=0; //右轮PWM占空比值,我们设计3个格,0-2,0为停止,2为全速
unsigned char l_Lpwm1=0; //左轮PWM占空比值,我们设计3个格,0-2,0为停止,2为全速
unsigned char l_Rpwm1=0; //右轮PWM占空比值,我们设计3个格,0-2,0为停止,2为全速
//TIMER0中断服务子函数产生PWM信号
void timer0()interrupt 1 using 2
{
TH0=0XFC; //定时1毫秒,10格调速,为100HZ频率,此频率下效果比较好,过大有噪声,过小振动大
TL0=0X17;
l_tt++;
if(l_tt>3)l_tt=0; //比较用,3格调速
if((l_tt)<=l_Lpwm){//左调速,占空比数值越大,输出高电平时间越宽,电机转速越高,我们设计3个格,0-2,0为停止,2为全速
L_PWM=1;
L_PWM1=1;
}
else{
L_PWM=0;
L_PWM1=0;
}
if(l_tt<=l_Rpwm){//右调速,同上
R_PWM=1;
R_PWM1=1;
}
else{
R_PWM=0;
R_PWM1=0;
}
}
void XJmoto(void)
{
while(1){ //循环探测
if((R_WXJ == 0)&&(L_WXJ == 0))
{
car_go;
car_go1;
}
else if((R_WXJ ==0)&&(L_WXJ == 1))
{
car_right;
car_right1;
}
else if((R_WXJ == 1)&&(L_WXJ == 0))
{
car_left;
car_left1;
}
else {
car_go;
car_go1; //如果写成后退,易出现问题
}
}
}
/***********主函数开始********************************************************/
void main(void)
{
TMOD=0x01; //定时器0方式1,16位计数器,用来计数时间,定时器1做为波特率发生器
TH0=(65536-100)/256;
TL0=(65536-100)%256;
TR0= 1;
ET0= 1;
EA=1;
l_Lpwm=0;
l_Rpwm=0;
l_Lpwm1=0;
l_Rpwm1=0;
while(1){ //按键选择不同车速,以适应不同的赛道
if(key1==0){ //按下按钮S1启动寻迹功能
l_Lpwm=1;//设置速度
l_Rpwm=1;
l_Lpwm1=1;//设置速度
l_Rpwm1=1;
XJmoto();
}
if(key2==0){ //按下按钮S2启动寻迹功能
l_Lpwm=6;//设置速度
l_Rpwm=6;
l_Lpwm1=6;//设置速度
l_Rpwm1=6;
XJmoto();
}
if(key3==0){ //按下按钮S3启动寻迹功能
l_Lpwm=8;//设置速度
l_Rpwm=8;
l_Lpwm1=8;//设置速度
l_Rpwm1=8;
XJmoto();
}
if(key4==0){ //按下按钮S4启动寻迹功能
l_Lpwm=10;//设置速度
l_Rpwm=10;
l_Lpwm1=10;//设置速度
l_Rpwm1=10;
XJmoto();
}
}
}
上面的代码可以实现按键调速,但因为自己只利用key1,所以占空比没改,5:5和1:1,占空比都是50%,但因为5:5加速时间更长,所以速度可能是更快的。
还有一个关于占空比设置的小细节,格数多会有个问题,就是如果你把运动时间设置的比较短,因为每个电机的灵敏性不同,容易导致轮子有的转,有的不转,就算都转动了,也容易有快有慢,导致小车转圈。
在连线时要注意L298N要和单片机共地,通过L298N的5V输出端给单片机供电,L298N的12V输入可由锂电池供电。
红外检测模块的高度设置是一个很重要的问题,通过实践总结的经验是可以在走的路线上实测,当红外模块在黑线上信号灯灭,在白板上信号灯亮时,说明高度合适。并不是很多人说的越低越好,这点很重要。
当车轮打滑时,可以通过增加负重或减慢车速来有效规避。
以上是自己的一点拙见,希望对大家有用。