一、小车1.0——基本蓝牙小车(仅蓝牙遥控小车运动方向)
二、小车2.0——蓝牙小车PLUS(可以蓝牙控制方向+蓝牙直接调节车速)
三、小车3.0——避障小车(超声波+舵机云台)
四、小车4.0——手柄方向感知操控小车((mpu6050+双蓝牙透传,是这篇博客)
建议:阅读这篇文章前最好先看看系列文章里的小车1.0
本文将介绍手柄方向感知操控小车,其实我也不知道取什么名字好 ,所谓手柄方向感知操控可以简单理解为向前倾—>小车前进,后倾—>小车后退,左倾—>小车左转,右倾—>小车右转,水平放置时—>小车停止。
提示:本文仅介绍方向感知操控手柄的相关代码以及原理,小车部分其实就是基本的蓝牙小车,关于小车部分的代码可以点击系列文章目录中的小车1.0
需要准备
STM32F103C8T6———————— 2个
12V电池 ————————————1个
9V电池 ——————-—————— 1个(这个只要能供5V或3.3V就行)
L298N电机驱动 —————————2个
小车底座———————————— 1个
稳压模块或者可调降压模块———— 2个
蓝牙模块HC-08————————— 2个
mpu6050(GY-521)————————1个
想要方向感知操控手柄与蓝牙小车实现通信,第一个想到的便是用蓝牙模块实现,在选择蓝牙模块的时候一定要选择一主一从,选择HC-08的原因是:它是主从一体的蓝牙,只需要设置一个HC-08为主机,另一个为从机,以及相同的波特率,即可实现蓝牙间的数据交换,而且是透传(透传即不再区分主机与从机),之后再次开启蓝牙会自动秒连。
下面讲一下设置:
因为由于HC-08蓝牙芯片默认状态为从机且波特率为9600Bits/s,所以只需要将手柄上的HC-08进行AT指令设置为主机即可,如下
具体操作:
1、将手柄上的HC-08与USB转TTL模块正确连接后接入PC;
2、通过串口调试助手完成AT指令的输入;
3、先检查串口是否正常工作,串口助手发送区输入AT(ASCII码输入),若返回 OK,进入下一步,否
则,检查芯片是否损坏,连线是否正确;
4、检测到串口正常工作后,键入AT+ROLE=M,若返回OK,则表明已经成功将其设为主机。
具体的AT指令集和相关操作可以参考——>汇承HC-08蓝牙模块间配对
(1)点击RCC开启HSE和LSE,并选择RC或晶体作为时钟源
(2)配置时钟树
最终最右侧显示为
目的是控制手柄的蓝牙发送数据
,因为只是利用串口发送数据,所以USART2的设置不需要开启串口中断
(1)点击Connectivity–>USART2,开启异步模式(Asynchronous)
(2)Parameter Settings的参数设置
我用的是SWD模式,这个看你自己的烧录模式,如果是用串口进行烧录那就可以忽略这步设置。
最终:
这里给出了main.c的代码以及部分我改动的mpu6050测试代码,关于mpu6050测量欧拉角的代码我是直接移植的官方DMP库。
官方DMP库的移植方法参考这篇博客——>MPU6050官方DMP的移植和使用
提示:改动部分是在DMP_test.c中修改了一开头的部分和最后一个 DMP_test(void)函数,以及在DMP文件中又添加了DMP_test.h
1.修改了DMP_test.c一开始的.h文件
#include "DMP_test.h"
float pitch,roll,yaw=0; //欧拉角
2.修改了DMP_test(void)函数
void DMP_test(void)
{
unsigned char i;
HAL_Delay(500);
//由MPU6050的官方DMP库说明,初始化时,必须使得z轴与竖直方向平行
//z轴向上活着向下都可以
//mpu_dmp_init()为mpu6050,dmp初始化,返回值:0,正常;其他,失败
i = mpu_dmp_init();
while(i)
{
HAL_Delay(500);
i = mpu_dmp_init();
printf("MPU6050 init error:%d\r\n",i);
}
printf("MPU6050 init OK\r\n");
}
添加DMP_test.h
#ifndef DMP_DMP_TEST_H_
#define DMP_DMP_TEST_H_
#include "stm32f1xx_hal.h"
#include
#include "main.h"
#include "math.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
#define q30 1073741824.0f //q30格式,long转float时的除数.
#define DEFAULT_MPU_HZ 200
extern float pitch,roll,yaw; //欧拉角
unsigned char run_self_test(void);
unsigned short inv_orientation_matrix_to_scalar(const signed char *mtx);
unsigned short inv_row_2_scale(const signed char *row);
void mget_ms(unsigned long *time);
unsigned char mpu_dmp_init(void);
unsigned char mpu_dmp_get_data(float *pitch,float *roll,float *yaw);
void DMP_test(void);
#endif /* DMP_DMP_TEST_H_ */
/* USER CODE BEGIN Includes */
#include "../../icode/DMP/DMP_test.h"
/* USER CODE END Includes */
/* USER CODE BEGIN 1 */
uint8_t USART2_TX_BUF[4]={0xA5,0x00,0xFF,0x5A};
//先定义一个数组,里面存放着数据包,数据包结构是由4个数据组成,即包头、原数据、校验码、包尾各一个字节,后续只用改变原数据和校验码发送不同数据给蓝牙小车
/* USER CODE END 1 */
/* USER CODE BEGIN 2 */
DMP_test();
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
/*pitch:俯仰角 精度:0.1° 范围:-90.0° <---> +90.0°, 向前向后倾,改变了俯仰角的值
roll:横滚角 精度:0.1° 范围:-180.0°<---> +180.0°,向左向右倾,改变了横滚角的值
yaw:航向角 精度:0.1° 范围:-180.0°<---> +180.0°,这个暂时不用
*/
{
if(pitch>30)//俯仰角大于30°,这里角度的值可以自己设定,其绝对值越小越灵敏
{
USART2_TX_BUF[1]=0x01;//小车前进
USART2_TX_BUF[2]=USART2_TX_BUF[1]%0x100;
HAL_UART_Transmit(&huart2, (uint8_t *)USART2_TX_BUF,4,0xFFFF);
}
else if(pitch<-30)//俯仰角小于-30°
{
USART2_TX_BUF[1]=0x04;//小车后退
USART2_TX_BUF[2]=USART2_TX_BUF[1]%0x100;
HAL_UART_Transmit(&huart2, (uint8_t *)USART2_TX_BUF,4,0xFFFF);
}
else if(roll<-30)//横滚角小于-30°
{
USART2_TX_BUF[1]=0x02;//小车左转
USART2_TX_BUF[2]=USART2_TX_BUF[1]%0x100;
HAL_UART_Transmit(&huart2, (uint8_t *)USART2_TX_BUF,4,0xFFFF);
}
else if(roll>30)//横滚角大于30°
{
USART2_TX_BUF[1]=0x03;//小车右转
USART2_TX_BUF[2]=USART2_TX_BUF[1]%0x100;
HAL_UART_Transmit(&huart2, (uint8_t *)USART2_TX_BUF,4,0xFFFF);
}
else
{
USART2_TX_BUF[1]=0x00;//小车停止
USART2_TX_BUF[2]=USART2_TX_BUF[1]%0x100;
HAL_UART_Transmit(&huart2, (uint8_t *)USART2_TX_BUF,4,0xFFFF);
}
}
}
/* USER CODE END 3 */
好了,遇到问题就及时解决,想到什么就动手去做
最后谢谢隔壁老王的好点子
欢迎大家积极交流,本文未经允许谢绝转载!!!