项目效果:通过手机蓝牙向蓝牙模块发送指令,蓝牙模块接受指令并通过串口发送给单片机,单片机控制舵机旋转角度,实现开,关节能灯开关。
一.设备:
硬件:BT08-B蓝牙模块(较为便宜),MG90S舵机(较为便宜),
51单片机(STC89C52RC芯片);
软件:STC-ISP,keil 4,大夏龙雀—串口助手(微信小程序);
1. BT08-B(蓝牙模块):
BT08蓝牙模块资料:https://pan.baidu.com/s/1n1hVz_CiRZYZchYPTSr9lA 提取码: zu9r
蓝牙名称:BT04-A;
初始密码:1234;
蓝牙模块未连接成功,指示灯闪烁;连接成功则不闪烁。
如果出错,查阅AT指令。如果还有问题,bilibili上搜大夏龙雀有相关视频。
2.MG90S舵机介绍:
PWM信号线(黄色),电源线VCC(红色),地线GND(棕色)
使用电压:3.5-6V
分类:普通舵机分为180度舵机和360度舵机。
控制:所有的普通舵机都是由PWM控制的。舵机的控制一般需要一个20毫秒左右的时基脉冲,该脉冲的高电平部分一般为0.5-2.5ms(500-2500us)。
360度舵机是PWM控制它的旋转速度和旋转方向,500-1500us的PWM控制它正转,值越小,旋转速度越大;1500-2500us的PWM是控制它的反转,值越大,旋转速度越大。1500us的PWM控制它的停止。
180度舵机是PWM控制它的旋转角度,500-2500us的PWM对应控制180度舵机的0-180度,是一一对应的,一个PWM对应一个角度。
这个PWM图与我们用的PWM图略有不同,大家大概看一下,主要强调一下PWM的起始和最终位置都要为低电平,否则舵机不工作。
3.51单片机
有一块核心板即可,无需过多外设。(主要现在板子也挺贵的。。。)
IO口:P1^1(舵机PWM信号输出口接舵机黄色线);P3^0(单片机RXD接蓝牙模块TXD);
P3^1(单片机TXD接蓝牙模块RXD);只是VCC,GND接口需要加扩展板。
4. 大夏龙雀串口助手
进入小程序,设置UUID,BT16模块,确定。
操作:
连接操作:蓝牙模块通电,手机蓝牙连接上,然后进入微信小程序连接进入,等待连接成功,若长时间连接不成功,退出小程序重连。
断开操作:小程序断开,蓝牙模块指示灯不闪烁,小程序无法重连,需要手机蓝牙功能关闭才能重新连接。
数据发送:默认为字符格式。具体查阅ASCII表;
5.STC-ISP
烧录程序需要冷启动,下载程序时RXD,TXD最好断开。
代码展示:
#include <reg52.h>
sbit PWMOUT = P1^1;
unsigned char THRH = 0; // 高电平高字节
unsigned char THRL = 0;
unsigned char TLRH = 0; // 低电平低字节
unsigned char TLRL = 0;
unsigned char RXByte = '3'; //串口数据缓存区设初值为'3';
void ConfigPWM( float ms1,float ms2);
void ClosePWM(void);
void ConfigUART(unsigned int baud);
void main(void)
{
unsigned int i = 0;
for(i = 0;i<3000;i++);
EA = 1; //使能总中断
PWMOUT = 0; //舵机低电平起始,高电平触发
ConfigUART(9600); //配置波特率为9600
while(1)
{
switch(RXByte)
{
case 48: //'0'的十进制为48 ,'0'为关闭
ConfigPWM(0.5,19.5);
for(i = 20000; i > 0; i-- );
ClosePWM();
for(i = 1000; i > 0; i-- );
break;
case 49: //'1'的十进制为49,'1'为开启
ConfigPWM(2.5,17.5);
for(i = 20000; i > 0; i-- );
ClosePWM();
for(i = 1000; i > 0; i-- );
break;
case 51: //'3'的十进制为51,'3'为平衡位置
ConfigPWM(1.55,18.45);
for(i = 20000; i > 0; i-- );
ClosePWM();
for(i = 1000; i > 0; i-- );
break;
default:
break;
}
}
}
/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{
SCON = 0x50; //配置串口为模式1
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值
TL1 = TH1; //初值等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
}
/* UART中断服务函数 */
void InterruptUART(void) interrupt 4
{
if (RI) //接收到字节
{
RI = 0;
RXByte = SBUF;
SBUF = RXByte; //将接收到的字符反回以检验是否正确
}
if(TI) //发送字节
{
TI = 0;
}
}
void ConfigPWM( float ms1,float ms2) //配置 PWM
{
unsigned long high;
unsigned long low;
high = 11059200/12;
high = (high*ms1)/1000;
high = 65536 - high;
THRH = (unsigned char)(high >> 8);
THRL = (unsigned char) high;
low = 11059200/12;
low = (low*ms2)/1000;
low = 65536 - low;
TLRH = (unsigned char)(low >> 8);
TLRL = (unsigned char) low;
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = THRH;
TL0 = THRL;
ET0 = 1;
TR0 = 1;
PWMOUT = 1;
}
void InterruptTimer0(void) interrupt 1 // PWM中断
{
if(PWMOUT == 1)
{
TH0 = THRH;
TL0 = THRL;
PWMOUT = 0;
}
else
{
TH0 = TLRH;
TL0 = TLRL;
PWMOUT = 1;
}
}
void ClosePWM(void) //关闭PWM,停止舵机
{
TR0 = 0;
ET0 = 0;
PWMOUT = 0; //舵机最终低电平停止
并不完美,但实测可以运行。