一、所需配件:减速马达,底盘,C51控制板,L298N电机驱动,轮胎,万向轮,电池盒,杜邦线,铜柱,螺丝螺母。
控制板原理图
二、红外循迹模块
1.调试
①传感器不处于黑线上时指示灯没亮就顺时针调节电位器
②传感器处于黑线上时指示灯没灭就逆时针调节电位器
2.循迹传感器电路图
注:①VCC:电源线;DO:TTL开关信号输出;AD:模拟信号输出
②LM339:四路输出比较器,每路比较器有两个输入端和一个输出端,当同向输入端(+)>反向输入端(-)时,输出端为截止信号(需加上拉电阻,拉至高电平);当(+)<(-)时,输出端为低电平。
①工作原理:TCRT5000传感器的红外发射二极管不断发射红外线,当发射出的红外线没有被反射回来或被反射回来但强度不够大时,红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态;被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮。
三、L298N电机驱动(双H桥)
若T1,T4导通(B极为高电平),则如图
若T2,T3导通(B极为高电平),如图
1.通过控制这四个三极管的导通,就可以切换电机的正转和反转,若四个三极管都不导通,则没电流通过,电机停转。
2.控制ENA,IN1,IN2这三个引脚来控制三极管的导通
ENA:使能脚(总开关),它为高电平(1)时,IN1和IN2两个引脚的控制才有效。
若IN1为1,IN2为0,则T1,T3导通
若IN1为0,IN2为1,则T2,T3导通
若IN1和IN2为0,T2,T4导通,电机不转动
若IN1和IN2为1,T1,T3导通,电机不转动
四、直流有刷电机工作原理
注:磁极不动,线圈旋转,通电后,电流经过导体会产生磁场,磁铁同性相斥,异性相吸,从而产生安培力,转到后,换向器会,可改变绕组上的电流方向,再次产生磁场,产生力,从而实现不断转动。
五、pwm调速原理
靠占空比(改变脉冲宽度)来控制输出电压。对于单片机来说,可通过定时器设置定时初值,在中断服务函数中对占空比进行调整,从而实现电机的转速控制。
六、代码
1.电机模块
//电机模块
#include <REGX52.H>
sbit IN1=P1^0;//左轮
sbit IN2=P1^1;//左轮
sbit IN3=P1^2;//右轮
sbit IN4=P1^3;//右轮
void Left_Go()//左轮前进
{
IN1=1;
IN2=0;
}
void Right_G0()//右轮前进
{
IN3=1;
IN4=0;
}
void Left_Back()//左轮后退
{
IN1=0;
IN2=1;
}
void Right_Back()//右轮后退
{
IN3=0;
IN4=1;
}
void Left_Stop()//左轮停止
{
IN1=0;
IN2=0;
}
void Right_Stop()//右轮停止
{
IN3=0;
IN4=0;
}
函数封装
#ifdef __MOTOR_H__
#define __MOTOR_H__
void Left_Go();
void Right_G0();
void Left_Back();
void Right_Back();
void Left_Stop();
void Right_Stop();
#endif
2.运动模块
//动作模块
#include <REGX52.H>
#include "MOTOR.h"
void Car_Go()//小车前进
{
void Left_Go();
void Right_G0();
}
void Car_Left()//小车左转
{
void Left_Stop();
void Right_G0();
}
void Car_Right()//小车右转
{
void Right_Stop();
void Left_Go();
}
void Car_Stop()//小车停止
{
void Left_Stop();
void Right_Stop();
}
void Car_Back()//小车后退
{
void Left_Back();
void Right_Back();
}
函数封装
#ifndef __CAR_H__
#define __CAR_H__
void Car_Go();
void Car_Left();
void Car_Right();
void Car_Stop();
void Car_Back();
#endif
3.定时器模块
#include <REGX52.H>
sbit ENA_1 = P3^0;
sbit ENA_2 = P3^1;
sbit ENB_1 = P3^2;
sbit ENB_2 = P3^3;
/**
* @brief 定时器0初始化,100us@12.000MHz
* @param 无
* @retval 无
*/
void Timer0_Init(void) //100微秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = (65536-100)%256; //设置定时初始值
TH0 = (65536-100)/256; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
PT0 = 0;
}
unsigned int pwml,pwmr,t;//左右占空比,比较值
void Timer0_Routine() interrupt 1
{
TL0 = (65536-100)%256; //设置定时初始值
TH0 = (65536-100)/256; //设置定时初始值
t++;
if(t<pwml)
{
ENA_1 = 1;
ENA_2 = 1;
}
else
{
ENA_1 = 0;
ENA_2 = 0;
}
//左pwm
if(t<pwmr)
{
ENB_1 = 1;
ENB_2 = 1;
}
else
{
ENB_1 = 0;
ENB_2 = 0;
}
//右pwm
if(t>=100){t = 0;}
}
函数封装
#ifndef __TIMER0_H__
#define __TIMER0_H__
extern pwml;
extern pwmr;
extern t;
void Timer0_Init(void);
#endif
4.循迹模块
#include <REGX52.H>
#include "CAR.h"
#include "Timer_0.h"
sbit OUT1 = P2^4;//左调
sbit OUT2 = P2^1;//右调
extern pwml;
extern pwmr;
void Chack()
{
if(OUT1 == 1 && OUT2 == 1)//全黑线(或空中)停车
{
pwml = 0;
pwmr = 0;
Car_Stop();
}
if(OUT1 == 0 && OUT2 == 1)//偏左,右移
{
pwml = 20;
pwmr = 16;
Car_Go();
}
if(OUT1 == 1 && OUT2 == 0)//偏右,左移
{
pwml = 16;
pwmr = 20;
Car_Go();
}
if(OUT1 == 0 && OUT2 == 0)
{
pwml = 16;
pwmr = 16;
Car_Go();
}
}
函数封装
#ifndef __CHACK_H__
#define __CHACK_H__
#include "MOTOR.h"
void Chack();
#enfif
5.main函数
#include <REGX52.H>
#include "Timer_0.h"
#include "MOTOR.h"
#include "CAR.h"
#include "Chack.h"
void main()
{
Timer0_Init();
while(1)
{
Chack();
}
}