基本驱动
L298N电机驱动模块负责供电和控制电机驱动
将电池12V供电接到12V供电上,作为输入。单片机及其他器件供电可以使用5V供电,这里的GND都接到一起。
输出A和输出B接到电机上,负责给电机供电和控制电机。
通道A使能和通道B使能以及逻辑输入部分都接到单片机上,在这里通道A使能和通道B使能接高电平使能,接PWM信号可以控制输出A和输出B的转速。
IN1 和 IN2 控制输出A
IN1=1,IN2=0,对应电机A正转
IN1=0,IN2=1,对应电机A反转
IN1、IN2同时输入高电平HIGH或低电平LOW,对应电机A停止转动
IN3 和 IN4 控制输出B
IN3=1,IN4=0,对应电机B正转
IN3=0,IN4=1,对应电机B反转
IN3、IN4同时输入高电平HIGH或低电平LOW,对应电机B停止转动
这里还要注意,如果电机堵转可能会烧毁其他器件,要注意不要让电机堵转。
代码参考
// 定义电机控制引脚
#include<REG52.H>
sbit IN1=P1^1; //左后轮
sbit IN2=P1^2; //左前轮
sbit IN3=P1^3; //右后轮
sbit IN4=P1^4;//右前轮
void L_motor_go()//左轮前进
{
IN2=1;
IN1=0;
}
void L_motor_back()//左轮后退
{
IN2=0;
IN1=1;
}
void R_motor_go() //右轮前进
{
IN4=1;
IN3=0;
}
void R_motor_back() //右轮后退
{
IN4=0;
IN3=1;
}
void L_motor_stop() //左轮停止
{
IN2=0;
IN1=0;
}
void R_motor_stop() //右轮停止
{
IN4=0;
IN3=0;
}
#include <REGX52.H>
#include "motor.h"
#include "CAR.H"
sbit ENA=P1^5; //左使能端
sbit ENB=P1^6; //右使能端
unsigned char speed=50;//小车速度
void timer0_Init() //100微秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TH0 = 0xff;
TL0 = 0xa4;
TF0 = 0;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许定时器0中断
EA = 1; // 总中断允许
}
void timer0() interrupt 1
{
static unsigned char count=0;
TH0 = 0xff;
TL0 = 0xa4;
count++;
if(count >=100)
{
count = 0;
}
if(count < speed)//小车PWM
{
ENA = 1;
ENB = 1;
}
else
{
ENA = 0;
ENB = 0;
}
}
void car_go()
{
R_motor_go();
L_motor_go();
}
void car_back()
{
R_motor_back();
L_motor_back();
}
void car_left()
{
R_motor_back();
L_motor_go();
}
void car_right()
{
R_motor_go();
L_motor_back();
}
void car_stop()
{
R_motor_stop();
L_motor_stop();
}
蓝牙模块
TXD:发送端,一般表示为自己的发送端,正常通信必须接另一个设备的RXD。
RXD:接收端,一般表示为自己的接收端,正常通信必须接另一个设备的TXD。
只当作串口来用接VCC、GND、TXD、RXD就够了,使用前先测试以下,使用手机蓝牙调试器连接蓝牙,电脑使用USB转TTL接到蓝牙模块上,然后用串口助手测试收发是否正常。正常波特率9600,如果不知道可以使用AT指令修改或查询。
先按住HC05蓝牙模块上面的按键,再给蓝牙模块通电。蓝牙模块上面的LED进入慢闪模式(约1秒钟闪烁一次),即可进行AT命令测试
AT命令格式为:波特率38400,8个数据位,1个停止位,无校验。每条指令输入完成后,必须按一下回车键再发送!
例如:输入AT,按一下回车键发送,蓝牙模块会返回OK
HC06在未连接蓝牙时可直接发送AT指令。
参考代码,主要实现控制小车和调试功能
#include <REGX52.H>
#include "CAR.H"
#include "BLE.H"
#include "CHAOSHENGBO.H"
unsigned char U_data; //接受数据存放
unsigned char str[]=" Speed: ";//发送数据存放
unsigned char str1[]=" Length: ";
extern unsigned char flag1;
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设置定时初始值
TH1 = 0xFD; //设置定时重载值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
EA = 1;
ES = 1;
}
void receive(unsigned char m)//接受数据
{
switch(m)
{
case 'W': //前进
car_go();
break;
case 'A':
car_left(); // 左转
break;
case 'D':
car_right(); // 右转
break;
case 'S':
car_back(); // 后退
break;
case 'I': // 停止
car_stop();
break;
case 'Q': // 速度加
speed+=5;
uart_send_string(str);
uart_send_byte(speed/10+'0');
uart_send_byte(speed%10+'0');
break;
case 'E': // 速度减
speed-=5;
uart_send_string(str);
uart_send_byte(speed/10+'0');
uart_send_byte(speed%10+'0');
break;
case 'B': // 显示信息
showInfo();
break;
case 'N': // 舵机角度加
angle++;
if(angle>25)angle=25;
break;
case 'M': // 舵机角度减
angle--;
if(angle<5)angle=5;
break;
case 'P': //循迹模式切换
flag1=!flag1;
uart_send_byte(flag1);
break;
default:
break;
}
}
//发送一个字符
void uart_send_byte(unsigned char byte_data)
{
SBUF = byte_data;
while(!TI);
TI=0;
}
//发送一串字符串
void uart_send_string(unsigned char *str)
{
while(*str)
{
uart_send_byte(*str++);
}
}
//显示信息
void showInfo()
{
uart_send_string(str);
uart_send_byte(speed/10+'0');
uart_send_byte(speed%10+'0');
uart_send_string(str1);
uart_send_byte(Length/100+'0');
uart_send_byte(Length/10%10+'0');
uart_send_byte(Length%10+'0');
}
//***************************************************************************
void UartInit_seve() interrupt 4
{
if(RI==1)
{
RI = 0; //清除接受中断标志位
U_data = SBUF; //接受数据
receive(U_data);
}
}
循迹模块
调节可调电阻设置测量距离,做到测到地板上黑线灯灭,没测到黑线灯亮的状态,通过排列所有情况组合可以达到循迹的效果
参考代码
#include <REGX52.H>
#include "CAR.H"
sbit left1=P2^0;
sbit left2=P2^1;
sbit right3=P2^2;
sbit right4=P2^3;
/*循迹情况分析*/
void xunji()
{
unsigned char a;
if(left1==0 &&left2==0 &&right3==0 &&right4==0) //0000
a = 1;
else if(left1==0 &&left2==0 &&right3==0 &&right4==1) //0001
a = 3;
else if(left1==0 &&left2==0 &&right3==1 &&right4==0) //0010
a = 1;
else if (left1==0 &&left2==0 &&right3==1 &&right4==1) //0011
a = 3;
else if(left1==0 &&left2==1 &&right3==0 &&right4==0) //0100
a = 1;
else if(left1==0 &&left2==1 &&right3==0 &&right4==1) //0101
a = 3;
else if(left1==0 &&left2==1 &&right3==1 &&right4==0) //0110
a = 1;
else if(left1==0 &&left2==0 &&right3==1 &&right4==1) //0111
a = 3;
else if(left1==1 &&left2==0 &&right3==0 &&right4==0) //1000
a = 2;
else if(left1==1 &&left2==0 &&right3==0 &&right4==1) //1001
a = 1;
else if(left1==1 &&left2==0 &&right3==1 &&right4==0) //1010
a = 2;
else if(left1==1 &&left2==0 &&right3==1 &&right4==1) //1011
a = 1;
else if(left1==1 &&left2==1 &&right3==0 &&right4==0) //1100
a = 2;
else if(left1==1 &&left2==1 &&right3==0 &&right4==1) //1101
a = 1;
else if(left1==1 &&left2==1 &&right3==1 &&right4==0) //1110
a = 2;
else if(left1==1 &&left2==1 &&right3==1 &&right4==1) //1111
a = 1;
switch (a)
{
case 1:car_go();break;
case 2:car_left();break;
case 3:car_right();break;
case 4:car_stop();break;
default:break;
}
}
超声波模块
给Trlg引脚至少10us高电平,之后Echo引脚就会返回高电平,通过计算高电平时间即可完成测距,如果需要测距更精确可加入温度补偿。
参考代码
#include <REGX52.H>
#include <intrins.h>
#include "car.h"
#include "BLE.H"
sbit Trig = P2^7;
sbit Echo = P2^6;
unsigned char Length; //测距结果
unsigned char mindistance = 10; //小车与障碍物的距离
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 Delay20us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 6;
while (--i);
}
void chaoshengbo()
{
T2MOD = 0; //初始化模式寄存器
T2CON = 0; //初始化控制寄存器
TL2 = 0; //设置定时初值
TH2 = 0; //设置定时初值
RCAP2L = 0; //设置定时重载值
RCAP2H = 0; //设置定时重载值
Trig = 1;
Delay20us();
Trig = 0;
while(!Echo);
TR2 = 1;
while(Echo);
TR2 = 0;
Length = ((TH2*256+TL2)*0.034)/2+1;
if(mindistance > Length)
{
car_stop();
}
}
舵机驱动
型号:SG90 重量13克 角度0度-180度
信号线(黄线)红线(电源线)棕色(地线)
舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度伺服为例,那么对应的控制关系是这样的:
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;
参考代码
#include <REGX52.H>
sbit servo=P2^5 ;
unsigned char angle=13;//舵机角度,5-25对应0-180度
void timer0_Init() //100微秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TH0 = 0xff;
TL0 = 0xa4;
TF0 = 0;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许定时器0中断
EA = 1; // 总中断允许
}
void timer0() interrupt 1
{
static unsigned char count=0;
TH0 = 0xff;
TL0 = 0xa4;
count++;
if(count >=200)
{
count = 0;
}
if(count < angle)//舵机PWM
{
servo = 1;
}
else
{
servo = 0;
}
}
避障模块
该传感器模块对环境光线适应能力强,其具有一对红外线发射与接收管,发射管发射出一定频率的红外线,当检测方向遇到障碍物(反射面)时,红外线反射回来被接收管接收,经过比较器电路处理之后,绿色指示灯会亮起,同时信号输出接回输出数字信号(一个低电平信号),可通过电位器旋钮调节检测距离,有效距离范围2~30cm,工作电压为3.3v-5v。该传感器的探测距离可以通过电位器调节、具有干扰小、便于装配、使用方便等特点,可以广泛应用于机器人避障、避障小车、流水线计数及黑白线循迹等众多场合。
当模块检测到前方障碍物信号时,电路板上绿色指示灯点亮,同时OUT端口持续输出低电平信号
该模块测距离2~~30cm,检测角度35°,检测距离可以通过电位器进行调节,顺时针调电位器,检测距离增加;逆时针调电位器,检测距离减少。
传感器主动红外线反射探测,因此目标的反射率和形状是探测距离的关键。其中黑色探测距离小,白色大;小面积物体距离小,大面积距离大。