技术分享:基于RW007 高速 WIFI 模块 BLE透传mpu6050数据

[复制链接]
 楼主| shadow12 发表于 2021-4-14 23:51 | 显示全部楼层 |阅读模式
本帖最后由 shadow12 于 2021-4-15 00:15 编辑

硬件准备
  • 1.STM32F411-NUCLEO 开发板,RW007 EVB模块
  • 2.PC 电脑
  • 3.USB 数据线
  • 4.BLE 数据透传模块(如HC-08模块、KT6368A蓝牙模块等)
  • 5.STM32F401-NUCLEO开发板,MPU6050模块
  • 6.USB-TTL 模块(如CH340等)
  • 7.杜邦线若干条

软件准备
  • 1.RT-Thread Studio IDE软件
  • 2.串口调试软件(xshell、SSCOM 等)

要实现MPU6050传感器数据BLE透传的功能,需要分为发送端设备和接收端设备。
发送端设备:
由 STM32F401-NUCLEO读取 mpu6050传感器数据配合KT6368A蓝牙模块数据透传。
可以分为以下的 7 个步骤:
  • 步骤1:创建 RT-Thread Studio IDE 工程
  • 步骤2:项目工程配置 I2C设备框架和硬件IO 引脚配置及硬件连接
  • 步骤3:添加mpu6050软件包,测试 mpu6050 数据获取
  • 步骤4:项目工程配置开启 uart6串口配置和硬件连接
  • 步骤5:测试 uart6串口功能
  • 步骤6:把获取的mpu6050数据通过 uart6串口输出
  • 步骤7:把KT6368A蓝牙模块的RXD引脚接在uart6串口配置的TXD

其中各个步骤的具体操作如下:
步骤1:创建 RT-Thread Studio IDE 工程
由于使用RT-Thread Studio IDE如何创建STM32F401-NUCLEO的工程,这个在官方的文档中心中有相关的文档说明,这里只作简单说明。
(1)通过点击新建RT-Thread项目,选择基于开发板,型号选择STM332F401-NUCLEO,输入工程名称,点击完成按钮开始创建工程。

步骤2:项目工程配置 I2C设备框架和硬件IO 引脚配置及硬件连接
在配置I2C设备框架前,先确定使用那组硬件 IO 引脚,在这里使用 PA4 连接到mpu6050模块的SCL,PA1连接到mpu6050模块的SCK.由于使用的是软件模拟的 I2C功能,只需确保对应的IO引脚没有被复用即可。

STM32引脚名
Pin序号
MPU6050引脚
功能
PA04SCLSCL
PA11SCKSCK

配置完成后,编译工程烧录到板子上,通过串口验证是否I2C设备框架正常工作。
注意:如果程序下载过程中提示 Warning: The core is locked up,需要在属性中配置为 system Reset 的复位模式
如图,通过list_device可以查看到有i2c1这个 device,表明配置已经生效。
步骤3:添加mpu6050软件包,测试 mpu6050 数据获取
关于 mpu6050软件包的使用,可以参考官方文档关于mpu6050传感器的使用,在这里仅是说明如何使用从官网相关文档中下载的mpu6050驱动包,获取数据。mpu6050软件驱动包的下载连接:https://www.rt-thread.org/document/site/application-note/driver/i2c/i2c-mpu6050.rar下载后的软件包中包含的文件如下图
在工程目录中刷新后可以显示添加的文件。
添加mpu6050软件包后需要适当修改SConscript 脚本
添加mpu6050软件包后需要适当修改drv_mpu6050.c 文件中的 MPU6050_I2CBUS_NAME为 i2c1。
然后编译工程,烧录测试mpu6050的功能。
步骤4:项目工程配置开启 uart6串口配置和硬件连接
由于默认创建的工程中没有开启uart6串口的配置,需要使用CubeMX开启 uart6的串口功能配置。
由于默认的图形化配置中没有UART6的配置,需要手动修改添加。
修改 Kconfig添加 UART6的配置后,需要图形化配置。
如图,默认USART6串口功能的RXD引脚是PC7,TXD引脚是PC6.
此时,可以使用一个 USB-TTL串口模块的与STM32F401-NUCLEO进行连接测试uart6的功能。
STM32引脚名
UART功能
连接 USB-TTL 模块引脚
PC6TXDRXD
PC7RXDTXD
GNDGND
步骤5:测试 uart6串口功能
关于 uart通信的示例,在官网的文档中心中有相关详细的说明,这里就不进行详细的描述。
直接从相关文档中参考一小段代码进行测试。

  1. #define SAMPLE_UART_NAME       "uart6"    /* 串口设备名称 */
  2. static rt_device_t serial;                /* 串口设备句柄 */
  3. char str[] = "hello RT-Thread!\r\n";
  4. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 配置参数 */
  5. /* 查找串口设备 */
  6. serial = rt_device_find(SAMPLE_UART_NAME);

  7. /* 以中断接收及轮询发送模式打开串口设备 */
  8. rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
  9. /* 发送字符串 */
  10. rt_device_write(serial, 0, str, (sizeof(str) - 1));

把上面的代码添加到工程里面的main.c文件中,通过MSH命令启动测试。
此时通过 SSCOM 串口调试工具观察 USB-TTL串口模块接收来自STM32F401-NUCLEO串口 UART6发送的数据。
到此,验证uart6串口功能正常。
步骤6:把获取的mpu6050数据通过 uart6串口输出
这里需要把获取的mpu6050数据通过uart6串口输出,需要适当修改代码,主要是添加 uart6串口的初始化还有把mpu6050数据通过uart6输出。
在main.c文件中,添加BLE_UART_NAME和serial的声明。
  1. #define BLE_UART_NAME       "uart6"    /* 串口设备名称 */
  2. static rt_device_t serial;                /* 串口设备句柄 */

在main函数中,添加 uart6串口的初始化代码。
  1. /* 查找系统中的串口设备 */
  2.     serial = rt_device_find(BLE_UART_NAME);
  3.     if (!serial)
  4.      {
  5.            rt_kprintf("find %s failed!\n", BLE_UART_NAME);
  6.            return RT_ERROR;
  7.      }
  8.      rt_kprintf("open uart6 ok...\n");
  9.      rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);

在mpu6050_thread_entry函数中,添加把mpu6050数据通过uart6输出的功能代码。
  1. void mpu6050_thread_entry(void *parameter)
  2. {
  3.     rt_int16_t temp;        //温度
  4.     rt_int16_t gx,gy,gz;    //三轴加速度
  5.     rt_int16_t ax,ay,az;    //三轴角速度

  6.     char TempStr[15] = {0};
  7.     //char Gx[10] = {0};

  8.     rt_err_t ret;

  9.     while(1)
  10.     {
  11.         ret = mpu6050_temperature_get(&temp);
  12.         if (ret != RT_EOK)
  13.         {
  14.             rt_kprintf("mpu6050 : get temperature error\r\n");
  15.         }
  16.         ret = mpu6050_accelerometer_get(&ax, &ay, &az);
  17.         if (ret != RT_EOK)
  18.         {
  19.             rt_kprintf("mpu6050 : get acc error\r\n");
  20.         }
  21.         ret = mpu6050_gyroscope_get(&gx, &gy, &gz);
  22.         if (ret != RT_EOK)
  23.         {
  24.             rt_kprintf("mpu6050 : get gyro error\r\n");
  25.         }
  26.         if (ret == RT_EOK)
  27.         {
  28.             //rt_kprintf("mpu6050: temperature=%-6d gx=%-6d gy=%-6d gz=%-6d ax=%-6d ay=%-6d az=%-6d\r\n",temp/100,gx,gy,gz,ax,ay,az);
  29.             sprintf(TempStr,"55temp=%dAA",temp/100);
  30.             rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));
  31.             memset(TempStr,0,sizeof(TempStr)/sizeof(char));
  32.             rt_thread_delay(rt_tick_from_millisecond(500));
  33.             sprintf(TempStr,"55gx=%dAA",gx);
  34.             rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));
  35.             memset(TempStr,0,sizeof(TempStr)/sizeof(char));
  36.             rt_thread_delay(rt_tick_from_millisecond(500));

  37.             sprintf(TempStr,"55gy=%dAA",gy);
  38.             rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));
  39.             memset(TempStr,0,sizeof(TempStr)/sizeof(char));
  40.             rt_thread_delay(rt_tick_from_millisecond(500));

  41.             sprintf(TempStr,"55gz=%dAA",gz);
  42.             rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));
  43.             memset(TempStr,0,sizeof(TempStr)/sizeof(char));
  44.             rt_thread_delay(rt_tick_from_millisecond(500));

  45.             sprintf(TempStr,"55ax=%dAA",ax);
  46.             rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));
  47.             memset(TempStr,0,sizeof(TempStr)/sizeof(char));
  48.             rt_thread_delay(rt_tick_from_millisecond(500));

  49.             sprintf(TempStr,"55ay=%dAA",ay);
  50.             rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));
  51.             memset(TempStr,0,sizeof(TempStr)/sizeof(char));
  52.             rt_thread_delay(rt_tick_from_millisecond(500));

  53.             sprintf(TempStr,"55az=%dAA",az);
  54.             rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));
  55.             memset(TempStr,0,sizeof(TempStr)/sizeof(char));
  56.         }
  57.         rt_thread_delay(rt_tick_from_millisecond(1000));
  58.     }
  59. }
说明:由于 BLE设备单次发送的数据长度有限制,需要拆分mpu6050的数据,并在发送的一帧数据前加上55作为数据头,在一帧数据后添加AA作为数据尾,这样方便接收方解析数据。
步骤7:把KT6368A蓝牙模块的RXD引脚接在uart6串口配置的TXD
基于前面的步骤,这里距离蓝牙数据透传功能的实现仅需要进行最后一步,把KT6368A蓝牙模块的RXD引脚接在uart6串口配置的TXD,由于KT6368A蓝牙模块一旦被连接后,就自动进入了透传模式,这时候可以参考上面的使用手机调试的方法,尝试读取数据。
到此,STM32F401-NUCLEO读取 mpu6050传感器数据配合KT6368A蓝牙模块数据透传的功能完成。
接收端设备:
STM32F411-NUCLEO通过 RW007 BLE 功能读取mpu6050传感器数据。
可以分为以下的 2 个步骤:
  • 步骤1:创建 RT-Thread Studio IDE 工程
  • 步骤2:添加BLE功能读取mpu6050传感器数据并解析的功能实现代码

步骤1:创建 RT-Thread Studio IDE 工程
这里可以参考前面 使用STM32F411-NUCLEO通过RW007BLE 功能测试BLE蓝牙模块数据传输功能 这部分的内容,进行创建工程,在这个工程的基础上,只需要添加一小部分代码就可以实现读取mpu6050传感器数据的功能。这里在 application目录下添加ble_example.c文件,并修改applications目录下的SConscript脚本,把ble_example.c添加到工程编译。
步骤2:添加BLE功能读取mpu6050传感器数据并解析的功能实现代码
在ble_example.c文件中添加BLE功能读取mpu6050传感器数据并解析的功能实现代码,主要参考rw007软件包中的ble_cmd_rw007.c里面关于ble命令的使用。
(1)添加RW007 BLE 功能初始化
  1. static int ble_example_init(void)
  2. {
  3.     rt_kprintf("ble_example_init\n");
  4.     rt_uint8_t roles = 0;
  5.     roles = RW007_BLE_INIT_ROLE_CENTRAL;

  6.     rw007_ble_init(roles);

  7.     rw007_ble_resp_handle_cb_reg(rw007_ble_resp_handle);
  8.     rw007_ble_ntf_handle_cb_reg(rw007_ble_ntf_handle);
  9.     return 0;

  10. }

说明: 上面代码实现RW007 BLE 功能作为主机初始化并设置相关回调的功能,rw007_ble_resp_handle 和 rw007_ble_ntf_handle函数可以直接参考ble_cmd_rw007.c文件里面的,具体的可以查询相关的代码。
(2)添加RW007 BLE 功能通过addr连接指定的BLE设备由于前面的步骤中,明确了需要连接的BLE设备的addr(即mac地址),这里就使用了。
  1. static int ble_example_connect(void)
  2. {
  3.     rt_kprintf("ble_example_connect\n");
  4.     ble_addr_t addr;
  5.     addr.type = RW007_BLE_ADDR_PUBLIC;
  6.     rt_kprintf("str_addr: %s\n", "ee:dd:ff:ee:cc:aa");

  7.     _hexstrtoaddr("ee:dd:ff:ee:cc:aa", addr.val);

  8.     rt_kprintf("mac addr: %2x:%2x:%2x:%2x:%2x:%2x\n", addr.val[0], addr.val[1],
  9.                                                           addr.val[2], addr.val[3],
  10.                                                           addr.val[4], addr.val[5]);
  11.     rw007_ble_connect(&addr);
  12.     return 0;
  13. }

说明:上面代码实现通过BLE设备的addr(即mac地址)进行连接。
(3)添加RW007 BLE 功能通过UUID接收数据在前面的步骤中,知道可以通过 UUID=0XFFF1来接收BLE设备的数据。
  1. static int ble_example_gatt_notify_change_by_uuid(void)
  2. {
  3.     rt_kprintf("ble_example_gatt_notify_change_by_uuid\n");
  4.     rt_uint16_t conn_handle = 0;
  5.     rt_uint16_t char_value = 0;

  6.     int uuidint;
  7.     ble_uuid_any_t uuid;

  8.     conn_handle = 1;
  9.     char_value = 1;

  10.     uuid.u16.u.type = BLE_UUID_TYPE_16;
  11.     sscanf("0xfff1", "%x", &uuidint);
  12.     uuid.u16.value = uuidint & 0xFFFFu;

  13.     rw007_ble_gatt_notify_change_by_uuid(conn_handle, &uuid, char_value);
  14.     return 0;
  15. }

说明:上面的代码中实现,通过设置UUID=0XFFF1来接收BLE设备的数据`
(4)添加数据解析部分的功能通过前面的测试中,可以知道BLE_TEST设备会把数据通过NOTIFY发送,此时只需要在RW007_BLE_NTF_TYPE_NOTIFY_RX中进行处理,把接收的数据解析(去掉数据头55、数据尾AA)
  1. case RW007_BLE_NTF_TYPE_NOTIFY_RX:
  2.         {    rt_kprintf("RW007_BLE_NTF_TYPE_NOTIFY_RX\n");
  3.             int offset = 0, notify_data_len = 0;
  4.             char *pcBegin = NULL;
  5.             char *pcEnd = NULL;
  6.             char cRes[15]={0};
  7.             struct ble_gap_event *event = RT_NULL;
  8.             void *notify_data = RT_NULL;

  9.             event = (struct ble_gap_event *)data;
  10.             offset = sizeof(struct ble_gap_event);
  11.             notify_data = data + offset;
  12.             notify_data_len = size - offset;

  13.             //hex_dump(notify_data, notify_data_len);
  14.             
  15.             pcBegin = strstr(notify_data,"55");
  16.             pcEnd = strstr(notify_data,"AA");
  17.             if(pcBegin == NULL || pcEnd == NULL || pcBegin > pcEnd)
  18.             {
  19.               rt_kprintf("data not found!!!\n");
  20.             }
  21.             else {
  22.                 pcBegin += strlen("55");
  23.                 rt_memcpy(cRes, pcBegin, pcEnd-pcBegin);
  24.                 rt_kprintf("data:%s\n",cRes);
  25.             }

  26.             break;
  27.         }

(5)添加启动测试命令在调试过程中,可以把启动的函数导出到msh命令中执行。
  1. static int ble_example_start(void)
  2. {
  3.     ble_example_init();
  4.     rt_thread_delay(1000);
  5.     ble_example_connect();
  6.     rt_thread_delay(5000);
  7.     ble_example_gatt_notify_change_by_uuid();

  8.     return 0;

  9. }
  10. MSH_CMD_EXPORT(ble_example_start,ble_example_start)

说明:把ble_example_start函数导出到msh命令行中执行,代码中添加一些适当的延时是考虑到BLE设备执行连接需要等待一些时间。
(6)工程编译与下载按照上面的步骤操作后,重新编译工程下载到板子上,在STM32F411-NUCLEO的调试串口上输入ble_example_start的命令进行通过 RW007 BLE 功能读取mpu6050传感器数据。
到此,STM32F411-NUCLEO通过 RW007 BLE 功能读取mpu6050传感器数据功能完成。
常见问题
1.下载程序过程中提示Warning: The core is locked up,导致程序烧录失败。
一般在属性设置中重新配置工程的复位模式即可解决。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

13

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部