基本驱动
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°,检测距离可以通过电位器进行调节,顺时针调电位器,检测距离增加;逆时针调电位器,检测距离减少。
传感器主动红外线反射探测,因此目标的反射率和形状是探测距离的关键。其中黑色探测距离小,白色大;小面积物体距离小,大面积距离大。