九轴运动传感器--BMX160,硬件开发与程序设计

九轴运动传感器–BMX160,硬件开发与程序设计

前言

  和之前OPT3001传感器一块板子上的九轴传感器的代码我写完啦,和大家分享一下

硬件部分介绍

BMX160介绍

  BMX160是博世的九轴运动传感器,集成了加速度、陀螺仪、磁力计三种传感器,其中加速度传感器基于BMI160,磁力计基于BMM150,可以说是BMX160是由BMI160、BMM150组成的。但性能参数在一些地方有差距。但在程序设计过程中,可以感觉到加速度陀螺仪和磁力计两部分的寄存器之间是有割裂的。磁力计的部分需要做特殊的间接读写。
  BMX160支持SPI和IIC通讯,支持FIFO、多种运动中断等高级玩法。

应用

  我想集成运动传感器的最初始的想法只是想要知道目前姿态,来设置屏幕的水平和垂直,但为了学习和日后的高级玩法,我还是喜欢功能、性能多一些的传感器。

电路部分

参考官方的的电路,电路部分很简单。

在这里插入图片描述

程序设计

程序架构介绍

程序一共有7个文件,所以我没有直接集成在ST的库中,而是直接单列了个文件夹。
  BMX160_use.c:主要存放功能函数,一般外部文件只需要调用该文件中的函数,也是架构最外层的部分
  BMX160_Control.c:主要存放底层函数和设备配置策略函数,比如SPI、IIC的读写,BMX160初始化过程中的配置参数、IIC地址、中断引脚等,一般移植需要修改这部分参数。
  BMX160_Algorithm.c:主要存放一些计算类的函数,方便use文件直接调用。目前因为没有涉及太多的姿态运算,所以该文件目前只有些二进制位运算函数。
  BMX160_Register.h:主要存放BMX160的寄存器位置。处于架构的最内层

移植部分

移植只需要BMX160_Control.c文件中的这部分。

Sensor_BMX160 BMX160_1;
int BMX160_Pretreatment(void)
{
    BMX160_1.COM_Mode = BMX160_COM_Mode;
#if BMX160_COM_Mode == BMX160_IIC
    BMX160_1.IIC_Aisle = hi2c1;
    BMX160_1.IIC_ADDR = 0x69;
#else
    BMX160_1.SPI_Aisle;
#endif
    /**********加速度策略**********/
    BMX160_1.ACC_CONF_RANGE.ACC_RANGE = BMX160_ACC_RANGE_2g;
    /**********陀螺仪策略**********/
    BMX160_1.GYR_CONF_RANGE.GYR_RANGE = BMX160_GYR_RANGE_125;
    /**********磁力计策略**********/
    BMX160_1.MAG_CONF_RANGE.MAG_XY_Mode = BMX160_MAG_Mode_HighPrecision;
    BMX160_1.MAG_CONF_RANGE.MAG_Z_Mode = BMX160_MAG_Mode_HighPrecision;
    BMX160_1.MAG_CONF_RANGE.MAG_odr = BMX160_MAG_RANGE_12_5;
    /**********校准策略**********/
    BMX160_1.ACC_GYR_FOC_off.FOC_GYR_EN = BMX160_FOC_GYR_ON;
    BMX160_1.ACC_GYR_FOC_off.FOC_ACC_X = BMX160_FOC_ACC_Recoup_0g;
    BMX160_1.ACC_GYR_FOC_off.FOC_ACC_Y = BMX160_FOC_ACC_Recoup_0g;
    BMX160_1.ACC_GYR_FOC_off.FOC_ACC_Z = BMX160_FOC_ACC_Recoup_P_1g;
    BMX160_1.ACC_GYR_FOC_off.Off_ACC_EN = BMX160_off_ACC_ON;
    BMX160_1.ACC_GYR_FOC_off.Off_GYR_EN = BMX160_off_GYR_ON;
    return BMX160_OK;
}

  默认是使用IIC通讯,SPI通讯的接口我做了兼容,但底层函数需要自己写一下。然后修改BMX160_Control.h这行代码

#define BMX160_COM_Mode BMX160_IIC //BMX160的通讯方式
修改为:
#define BMX160_COM_Mode BMX160_SPI//BMX160的通讯方式

  其中如果没有其他特殊需求,四个配置策略不用修改,只需要修改接口部分的参数就可以了。
  在BMX160_use.c中的初始化函数中,我做了一个例程,循环输出三种传感器的数值

int BMX160_Init(void)
{
    if (BMX160_Pretreatment() != BMX160_OK) //初始化结构体
    {
        return BMX160_Error;
    }
    //读取设备ID
    uint8_t DATA = {0};
    BMX160_Get_ChipID(&BMX160_1, &DATA);
    printf("%X\n", DATA);
    //重置设备
    BMX160_CMD(&BMX160_1, BMX106_CMD_Softreset);
    HAL_Delay(100);
    //将三个传感器设置为普通模式
    BMX160_CMD(&BMX160_1, BMX106_CMD_PMU_ACC_Normal);
    HAL_Delay(10);
    BMX160_CMD(&BMX160_1, BMX106_CMD_PMU_GYR_Normal);
    HAL_Delay(80);
    BMX160_CMD(&BMX160_1, BMX106_CMD_PMU_MAG_Normal);
    HAL_Delay(10);
    //读取功率模式
    int Mode[3];
    BMX160_Get_PMU_STATUS(&BMX160_1, &Mode[0], &Mode[1], &Mode[2], Report_Y);
    float DATA1 = 0;
    BMX160_Get_Temperature(&BMX160_1, &DATA1);
    printf("%f\n", DATA1);
    //配置加速度计采样策略
    BMX160_ACC_Sampling_Mode(&BMX160_1, BMX160_ACC_Normal_Oversampling, BMX160_ACC_ODR_100);
    BMX160_ACC_RANGE(&BMX160_1, BMX160_1.ACC_CONF_RANGE.ACC_RANGE);
    //配置陀螺仪采样策略
    BMX160_GYR_Sampling_Mode(&BMX160_1, BMX160_GYR_Normal_Oversampling, BMX160_GYR_ODR_100);
    BMX160_GYR_RANGE(&BMX160_1, BMX160_1.GYR_CONF_RANGE.GYR_RANGE);
    //配置磁力计采样策略
    BMX160_MAG_Sampling_Mode(&BMX160_1, BMX160_1.MAG_CONF_RANGE.MAG_XY_Mode, BMX160_1.MAG_CONF_RANGE.MAG_Z_Mode, BMX160_1.MAG_CONF_RANGE.MAG_odr);
    //校准
    BMX160_Auto_Calibration(&BMX160_1);

    //读取数据
    float ACC_DATA[3] = {0};
    float GYR_DATA[3] = {0};
    float MAG_DATA[3] = {0};
    while (1)
    {
        BMX160_Get_ACC(&BMX160_1, &ACC_DATA[0], &ACC_DATA[1], &ACC_DATA[2]);
        BMX160_Get_GYR(&BMX160_1, &GYR_DATA[0], &GYR_DATA[1], &GYR_DATA[2]);
        BMX160_Get_MAG(&BMX160_1, &MAG_DATA[0], &MAG_DATA[1], &MAG_DATA[2]);
        printf("加速度:");
        printf("X:%.2f", ACC_DATA[0]);
        printf(",");
        printf("Y:%.2f", ACC_DATA[1]);
        printf(",");
        printf("Z:%.2f", ACC_DATA[2]);
        printf("\r\n");
        printf("陀螺仪:");
        printf("X:%.2f", GYR_DATA[0]);
        printf(",");
        printf("Y:%.2f", GYR_DATA[1]);
        printf(",");
        printf("Z:%.2f", GYR_DATA[2]);
        printf("\r\n");
        printf("磁力计:");
        printf("X:%.2f", MAG_DATA[0]);
        printf(",");
        printf("Y:%.2f", MAG_DATA[1]);
        printf(",");
        printf("Z:%.2f", MAG_DATA[2]);
        printf("\r\n\r\n\r\n");

        HAL_Delay(500);
    }
}

在校准程序之后的代码都可以根据自己需要进行修改,但不建议删除输出数据上面的一些配置代码。配置策略的配置参数在BMX160_Control.h中存放,可以直接赋值过来修改。

API介绍

当初始化完成之后,最主要的就是三个传感器+温度的数据获取了。

/**
  * @brief 直接获取磁力计的三轴参数
  * @param BMX160:目标设备
  * @param DATA_X:X轴参数
  * @param DATA_Y:Y轴参数
  * @param DATA_Z:Z轴参数
  * @retval 初始化结果
  */
int BMX160_Get_MAG(Sensor_BMX160 *BMX160, float *DATA_X, float *DATA_Y, float *DATA_Z)


/**
  * @brief 直接获取加速度计的三轴参数
  * @param BMX160:目标设备
  * @param DATA_X:X轴参数
  * @param DATA_Y:Y轴参数
  * @param DATA_Z:Z轴参数
  * @retval 初始化结果
  */
int BMX160_Get_ACC(Sensor_BMX160 *BMX160, float *DATA_X, float *DATA_Y, float *DATA_Z)

/**
  * @brief 直接获取陀螺仪的三轴参数
  * @param BMX160:目标设备
  * @param DATA_X:X轴参数
  * @param DATA_Y:Y轴参数
  * @param DATA_Z:Z轴参数
  * @retval 初始化结果
  */
int BMX160_Get_GYR(Sensor_BMX160 *BMX160, float *DATA_X, float *DATA_Y, float *DATA_Z)

/**
  * @brief 获取传感器温度
  * @param BMX160:目标设备
  * @param DATA:温度值
  * @retval 获取是否成功
  */
int BMX160_Get_Temperature(Sensor_BMX160 *BMX160, float *DATA)

BMX160比较有意思的是,有一个寄存器比较特殊,CMD命令寄存器,重置、调整三传感器的功率模式等都需要通过该寄存器实现。

/**
  * @brief CMD命令
  * @param BMX160:目标设备
  * @param CMD:CMD命令
  * @retval 发送结果
  */
int BMX160_CMD(Sensor_BMX160 *BMX160, uint8_t CMD)

CMD命令可以为(在BMX_use.h文件中复制):
#define BMX160_CMD_PMU_ACC_Suspend 0x10     //加速度计暂停模式
#define BMX160_CMD_PMU_ACC_Normal 0x11      //加速度计普通模式
#define BMX160_CMD_PMU_ACC_LowPower 0x12    //加速度计低功耗模式
#define BMX160_CMD_PMU_GYR_Suspend 0x14     //陀螺仪计暂停模式
#define BMX160_CMD_PMU_GYR_Normal 0x15      //陀螺仪计普通模式
#define BMX160_CMD_PMU_GYR_FastStartUp 0x17 //陀螺仪计快速启动模式
#define BMX160_CMD_PMU_MAG_Suspend 0x18     //磁力计计暂停模式
#define BMX160_CMD_PMU_MAG_Normal 0x19      //磁力计计普通模式
#define BMX160_CMD_PMU_MAG_LowPower 0x1a    //磁力计计低功耗模式
#define BMX160_CMD_StartFoc 0x03            //加速度和陀螺仪的快速偏移校准
#define BMX160_CMD_ProgNvm 0xa0             //写入NVM
#define BMX160_CMD_FifoFlush 0xb0           //清除Fifo中所有数据
#define BMX160_CMD_IntReset 0xb1            //重置中断引擎
#define BMX160_CMD_Softreset 0xb6           //重启
#define BMX160_CMD_StepCntClr 0xb2          //步数计数器重置

中断部分

BMX160的中断部分比较复杂,我目前还不打算写,一是目前没有这个需求,因为只是在面包板阶段,等到了集成到总电路板的时候,我也会写。二是需要运动测试,面包板太大不太方便测试,到做成手持设备时候在测试就好多了。可以期待一下吧,当然,我如果写中断部分也是全部写完了,不会需要那部分写哪部分了。

开源地址

和OPT3001是一个库,后续的两个传感器我也会抓紧开发。
可以去白嫖了~下载的时候求求点一下星星,抱拳了!
github :https://github.com/lijinlong21549/Sensor-collection
关于硬件有什么问题欢迎私信。

版权声明:本文为CSDN博主「zhe_boy_is_z」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhe_boy_is_z/article/details/120140240

生成海报
点赞 0

zhe_boy_is_z

我还没有学会写个人说明!

暂无评论

相关推荐

4路红外循迹模块使用教程

4路红外循迹模块使用教程 个人原创博客:点击浏览模块详细信息: 工作电压:DC 3.3V~5V 工作电流:尽量选择1A以上电源供电 工作温度:-10℃~50℃ 安装孔

STM32使用各种传感器的demo

各种传感器的demo 最近有假期有空整理了一些传感器的使用方式 激光测距 激光测距是我在完成电磁炮项目用的模块,大家也可以去借鉴我以前的文章,使用起来也是方便,当时涂方便,利用的是串口