Files
433_STM32/docs/协议refer.md

9.7 KiB
Raw Blame History

蓝牙协议

/********************小程序 发数据到 BL**************************************/
===========================================================

BE BB  02  00  	XX 
-----  --  --  	--
  |		|	|	|
  |		|	|	指定传感器进行初始化01--六轴02--地磁03--气压计
  |		|	进行传感器的初始化/校准
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子


BE BB  02  01  	XX 
-----  --  --  	--
  |		|	|	|
  |		|	|	01--左脚02--右脚
  |		|  设置传感器采集的是哪只脚
  |	表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子


BE BB  02  02  	XX 
-----  --  --  	--
  |		|	|	|
  |		|	|	01表示读六轴状态02表示读地磁状态03表示读气压计状态
  |		|  读取传感器的状态
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子


BE BB  02  03  	XX 
-----  --  --  	--
  |		|	|	|
  |		|	|	01--开始02--停止
  |		|  采集数据并计算开始与停止
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子


BE BB  02  04  	01 
-----  --  --  	--
  |		|	|	|
  |		|	|	获取电量
  |		|  获取电量
  |	表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子


BE BB  02  05  	XX 
-----  --  --  	--
  |		|	|	|
  |		|	|	01:100Hz02:200Hz03:400Hz
  |		|  设置传感器采集频率
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子


BE BB  02  06  	XX 
-----  --  --  	--
  |		|	|	|
  |		|	|	00:禁用地磁01:使能地磁
  |		|  地磁使能指令
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子


BE BB  02  07  	XX 
-----  --  --  	--
  |		|	|	|
  |		|	|	00:禁用气压计01:使能气压计
  |		|  气压计使能指令
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子

BE BB  01  09
-----  --  --
  |		|	|
  |		|  开启地磁测试进程
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子

BE BB  01  0A
-----  --  --
  |		|	|
  |		|  关闭地磁测试进程
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子

BE BB  01  0B
-----  --  --
  |		|	|
  |		|  获取固件版本
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子

BE BB  01  0C
-----  --  --
  |		|	|
  |		|  获取rfid/uid
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子


BE BB 01 FF   扫描检测传感器
-----  --  --
  |		|	|
  |		|  扫描检测传感器
  |	   表示后面的数据长度
 包头BE表示小程序BB表示BL表示小程序发数据到蓝牙板子

===============================================================


/********************BL 发数据到小程序**************************************/
============================================================

BB BE  02  00  	XX
-----  --  --  	--
  |		|	|   |
  |		|	|	10六轴未初始化11六轴初始化成功20地磁未初始化21地磁初始化成功30气压计未初始化31气压计初始化成功
  |		|  返回传感器的初始化状态
  |	   表示后面的数据长度
包头BE表示小程序BB表示BL表示蓝牙板子发数据到小程序

### 地磁校准流程

地磁传感器需要校准,发送 BLE 命令后进行"画八字"校准,校准数据会保存到 VM 中,掉电后再次上电会自动加载。

**发送命令:**

BE BB 02 00 02 // 启动地磁校准


**BLE 反馈消息:**

| 消息 | 含义 | 说明 |
|------|------|------|
| BB BE 02 00 20 | 地磁初始化失败 | 传感器通信异常 |
| BB BE 02 00 21 | 地磁初始化成功 | 传感器正常,即将进入校准状态 |
| BB BE 02 00 22 | 提示开始校准 | 用户可以开始画八字 |
| BB BE 02 00 23 | 校准中 | 循环发送,正在采集数据 |
| BB BE 02 00 24 | 校准错误 | 数据范围不足,需重新画八字 |
| BB BE 02 00 25 | 校准完成 | 校准成功,数据已保存到 VM |

**校准成功后的行为:**
- 校准数据offset_x, offset_y, offset_z保存到 VMCFG_MAG_CALIBRATION
- 再次上电自动从 VM 加载校准数据,无需重复校准

BB BE  XX  00  	XX.......
-----  --  --  	--
  |		|	|	|
  |		|	|	16组传感器数据。每一组30字节
  |		|	数据包下标0-255
  |	 左/右脚数据
包头BE表示小程序BB表示BL表示蓝牙板子发数据到小程序

蓝牙助手设置

连接后要先将蓝牙的MTU设置为最大一般最大是512左右

image-20251205204926475

image-20251205204943926

image-20251205205027729

右边的调试助手可以查看传输速率。

数据采集

先后发送:初始化三个传感器

  • BE BB 02 00 01
    • 六轴初始化
    • 返回BB BE 02 00 11表示初始化成功
  • BE BB 02 00 02
    • 地磁初始化等到返回BB BE 02 00 21表示初始化成功
  • BE BB 02 00 03
    • 气压计初始化等到返回BB BE 02 00 31表示初始化成功

设定数据来源:

  • 发送BE BB 02 01 XX
    • 01左脚
    • 02右脚
  • 返回数据BB BE 06 05 XX
    • 41 -- 已设置为左脚42 -- 已设置为右脚

开始采集,传感器通过蓝牙发送数据

  • 发送BE BB 02 03 01
    • 如果返回BB BE 02 00 00说明有传感器没初始化成功可以发BE BB 02 02 XX 查看传感器初始化状态

一次完整的数据接收类似如下:

BE BB XX XX 后面每30字节为一组传感器数据,一个16

一次蓝牙发送共计484字节
    第一个xx:左右脚标志,41左脚,42右脚
    第二个xx:数据包下标,0-255,每到255就会重置为0

停止采集:

  • BE BB 02 03 02

获取电量

发送BE BB 02 04 01

  • 返回的是百分比的电量值,如:
    • 0x57
    • 转为十进制为87当前还剩87%的电量

开启地磁测试进程

发送BE BB 01 09

  • 返回地磁三轴 X Y Z数据每轴4字节的float类型。
    • BB BE 0D 09 XX XX XX XX XX XX XX XX XX XX XX XX

获取固件版本

发送BE BB 01 0B 返回: BB BE 03 0B XX XX 最后两字节就是版本号

获取设备ID/RFID

发送BE BB 01 0C 返回: BB BE 05 0C XX XX XX XX 最后四字节位就是RFID小端模式

扫描检测传感器

发送BE BB 01 FF 返回: 0xBB, 0xBE, 0x07, 0xFF, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX 最后6字节位对应扫描到的6个传感器目前实际最多只有3个。

采集速率修改

设置为100Hz

  • BE BB 02 05 01

设置200Hz

  • BE BB 02 05 02

设置400Hz

  • BE BB 02 05 03

数据解析


//data蓝牙拿到的数据484字节长度
void data_log(uint8_t* data){
    // 检查数据包头部
    if (data[0] != 0xBE || data[1] != 0xBB) {
        printf("Error: Invalid data packet header.\n");
        return;
    }

    //左右脚
     uint8_t package_foot = data[2];
    
    // 解析包索引
    uint8_t package_index = data[3];
    printf("--- Parsing Data Packet Index: %d ---\n", package_index);

    uint8_t* p = &data[4]; // 指向数据负载的起始位置

    // 循环解析16组数据
    for (int i = 0; i < MPU_FIFO_LEN; i++) {
        // 1. 解析六轴传感器数据 (12 bytes)
        int16_t imu_raw[6];
        for (int j = 0; j < 6; j++) {
            // 小端模式: 低字节在前, 高字节在后
            imu_raw[j] = (int16_t)(((uint16_t)p[1] << 8) | (uint16_t)p[0]);
            p += 2;
        }
        float acc_g[3];
        float gyr_dps[3];
        acc_g[0] = (float)imu_raw[0] / 2048.0f;
        acc_g[1] = (float)imu_raw[1] / 2048.0f;
        acc_g[2] = (float)imu_raw[2] / 2048.0f;
        gyr_dps[0] = (float)imu_raw[3] * 0.061f;
        gyr_dps[1] = (float)imu_raw[4] * 0.061f;
        gyr_dps[2] = (float)imu_raw[5] * 0.061f;

        // 2. 解析地磁传感器数据 (12 bytes)
        int32_t mag_raw[3];
        for (int j = 0; j < 3; j++) {
            // 小端模式
            mag_raw[j] = (int32_t)(((uint32_t)p[3] << 24) | ((uint32_t)p[2] << 16) | ((uint32_t)p[1] << 8) | (uint32_t)p[0]);
            p += 4;
        }
        float mag_gauss[3];
        mag_gauss[0] = (float)mag_raw[0] / 1000.0f;
        mag_gauss[1] = (float)mag_raw[1] / 1000.0f;
        mag_gauss[2] = (float)mag_raw[2] / 1000.0f;

        // 3. 解析温度数据 (2 bytes)
        int16_t temp_raw = (int16_t)(((uint16_t)p[1] << 8) | (uint16_t)p[0]);
        p += 2;
        float temperature = (float)temp_raw / 1000.0f;

        // 4. 解析气压数据 (4 bytes)
        uint32_t press_raw = (uint32_t)(((uint32_t)p[3] << 24) | ((uint32_t)p[2] << 16) | ((uint32_t)p[1] << 8) | (uint32_t)p[0]);
        p += 4;
        float pressure = (float)press_raw / 1000.0f;

        // 打印解析后的数据
        if(i % 8 == 0){
            printf("Package[%d]:====================\n", i);
            printf("  ACC(g):  x=%.3f, y=%.3f, z=%.3f\n", acc_g[0], acc_g[1], acc_g[2]);
            printf("  GYR(dps):x=%.3f, y=%.3f, z=%.3f\n", gyr_dps[0], gyr_dps[1], gyr_dps[2]);
            printf("  MAG(Gs): x=%.3f, y=%.3f, z=%.3f\n", mag_gauss[0], mag_gauss[1], mag_gauss[2]);
            printf("  TEMP(C): %.3f, PRESS(Pa): %.3f\n", temperature, pressure);
        }
        
    }
    printf("--- End of Packet ---\n\n");
}