|
近年来,智能可穿戴设备离普通人的生活越来越近,智能手环、智能手表、智能耳机等一系列的产品逐渐走进了人们的生活中。这些设备通过数据交互、云端交互等方式提供了强大的功能,对我们的生活、感知带来很大的转变。可穿戴设备中的MEMS传感器能够精确捕捉数据,并进行实时更新反馈。惯性测量单元作为一种MEMS传感器,可以用来测量方位、运动或者手势。
博世公司推出的低功耗智能传感器BMI323可以用于穿戴设备,该传感器基于博世的MEMS工艺技术,而且大大提升了加速度计的偏移和灵敏度性能。在本篇文章中,我们将介绍如何基于NUCLEO-G070开发板通过SPI接口读取BMI323的加速度计和陀螺仪数据。
所需的组件 ● NUCLEO-G070RB开发板 ● YBX-BMI323惯性测量单元传感器模块(淘宝链接) ● 连接跳线 ● USB线缆 ● 友善串口调试助手
YBX-BMI323传感器模块
YBX-BMI323模块采用博世传感器的超低功耗智能惯性测量单元BMI323。该IMU针对可穿戴设备进行了优化,提供精确的加速度、角速率测量和智能片上运动触发中断功能,同时该传感器集成了16位三轴陀螺仪和16位三轴加速度计。该模块支持SPI和I2C接口进行系统集成,可以快速实现与Arduino和STM32等控制器直接相连。该模块板载一颗电源芯片,支持3.3-5V供电。
BMI323包含直观的手势、情景和活动识别功能,并集成了针对腕戴式设备专门进行优化的即插即用计步器。该IMU也非常适合其他类型的可穿戴设备,如耳戴式设备、智能服装、智能鞋、智能眼镜和脚踝带。
Bosch的独特静止组件重新调整 (CRT) 功能可提供内置陀螺仪自校准功能,无需旋转激励,从而在测试和制造过程中为OEM节省宝贵的时间和成本。BMI323的嵌入式即插即用功能有助于缩短产品上市时间。
主要特性 ● 采用Bosch超低功耗智能惯性测量单元BMI323 ● 16位数字三轴加速度计 ● 16位数字三轴陀螺仪 ● 电流消耗:790µA(典型值) ● 灵敏度误差:± 0.4% ● 通过静止CRT功能实现自校准陀螺仪: ● 输出数据速率:12.5Hz至6.4kHz ● SPI和I2C接口 ● 2个独立的可编程I/O引脚,用于中断和同步事件 ● 板载一颗高精度DC-DC芯片 ● LED电源指示灯 ● 支持Arduino和STM32等微控制器 ● 外形尺寸:24mm x 24mm x 5mm
硬件连接 YBX-BMI323模块支持SPI和I2C连接,在本文中,我们将使用四线SPI方式进行连接。首先,将YBX-BMI323模块连接到NUCLEO-G070RB开发板的SPI1接口,对应的引脚分别是PA5(SCK)、PA6(MISO)和PA7(MOSI),片选引脚CSB连接到PB0。YBX-BMI323模块的VCC连接到3V3引脚,GND引脚连接到NUCLEO-G070RB的任意GND引脚。
驱动文件 Bosch博世传感器官方提供了基于BMI323的驱动文件BMI323_SensorAPI,该源码可以在GitHub进行下载。下载地址:BMI323_SensorAPI
代码 首先我们使用STM32CubeMX工具生成工程文件,根据硬件连接方式选择引脚的功能,然后启用SPI1通讯。SPI1选择全双工主机模式(Full-Duplex Master),硬件NSS信号选择Disable。在参数设置中,数据位大小选择8位,MSB优先。选择合适的分频系数。在无法进行通讯的情况下,可以适当降低SPI1外设的频率。
生成KEIL工程后,接下来我们需要将BOSCH官方提供的BMI323_SensorAPI驱动集成到工程里面。
首先,将下载的整个驱动文件复制到工程所在的目录,然后将bmi3.c、bmi323.c、common.c添加到工程中。在common.c中重载以下两个函数:bmi3_spi_read和bmi3_spi_write。
在主函数main中,首先初始化BMI323,然后对加速度计和陀螺仪的参数进行配置。在while循环中,读取寄存器的数据,并打印输出到串口。 - printf("\nBMI323 SPI Test\n");
- printf("Bolgen Studio\n");
- /* Sensor initialization configuration. */
- struct bmi3_dev dev = { 0 };
- /* Status of API are returned to this variable. */
- int8_t rslt;
- /* Variable to define limit to print accel data. */
- uint16_t limit = 300;
- /* Create an instance of sensor data structure. */
- struct bmi3_sensor_data sensor_data = { 0 };
- /* Initialize the interrupt status of accel. */
- uint16_t int_status = 0;
- uint8_t indx = 0;
- float x = 0, y = 0, z = 0;
- /* Structure to define accelerometer configuration. */
- struct bmi3_sens_config config = { 0 };
- /* Select accel sensor. */
- sensor_data.type = BMI323_ACCEL;
- /* Function to select interface between SPI and I2C, according to that the device structure gets updated.
- * Interface reference is given as a parameter
- * For I2C : BMI3_I2C_INTF
- * For SPI : BMI3_SPI_INTF
- */
- rslt = bmi3_interface_init(&dev, BMI3_SPI_INTF);
- bmi3_error_codes_print_result("bmi3_interface_init", rslt);
-
- while (1)
- {
- /* Initialize bmi323. */
- rslt = bmi323_init(&dev);
- bmi3_error_codes_print_result("bmi323_init", rslt);
- if (rslt == BMI323_OK) break;
-
- HAL_DelayMs(2000);
- }
- /* Accel configuration settings. */
- rslt = set_accel_config(&dev);
- if (rslt == BMI323_OK)
- {
- rslt = bmi323_get_sensor_config(&config, 1, &dev);
- bmi3_error_codes_print_result("bmi323_get_sensor_config", rslt);
- }
- /* Gyro configuration settings. */
- rslt = set_gyro_config(&dev);
- if (rslt == BMI323_OK)
- {
- rslt = bmi323_get_sensor_config(&config, 1, &dev);
- bmi3_error_codes_print_result("bmi323_get_sensor_config", rslt);
- }
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- while (indx <= limit)
- {
- /* Select accel sensor. */
- sensor_data.type = BMI323_ACCEL;
- printf("\nAccel Sensor");
- printf("\nData set, Range, Acc_Raw_X, Acc_Raw_Y, Acc_Raw_Z, Acc_ms2_X, Acc_ms2_Y, Acc_ms2_Z\n\n");
- /* Get accelerometer data for x, y and z axis. */
- rslt = bmi323_get_sensor_data(&sensor_data, 1, &dev);
- bmi3_error_codes_print_result("Get sensor data", rslt);
- /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */
- x = lsb_to_mps2(sensor_data.sens_data.acc.x, 2, dev.resolution);
- y = lsb_to_mps2(sensor_data.sens_data.acc.y, 2, dev.resolution);
- z = lsb_to_mps2(sensor_data.sens_data.acc.z, 2, dev.resolution);
- /* Print the data in m/s2. */
- printf("%d, %d, %d, %d, %d, %4.2f, %4.2f, %4.2f\n",
- indx,
- config.cfg.acc.range,
- sensor_data.sens_data.acc.x,
- sensor_data.sens_data.acc.y,
- sensor_data.sens_data.acc.z,
- x,
- y,
- z);
- /* Select gyro sensor. */
- sensor_data.type = BMI323_GYRO;
- printf("\nGyro Sensor");
- printf("\nData set, Range, Gyr_Raw_X, Gyr_Raw_Y, Gyr_Raw_Z, Gyr_dps_X, Gyr_dps_Y, Gyr_dps_Z\n\n");
- /* Get gyro data for x, y and z axis. */
- rslt = bmi323_get_sensor_data(&sensor_data, 1, &dev);
- bmi3_error_codes_print_result("Get sensor data", rslt);
- /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */
- x = lsb_to_dps(sensor_data.sens_data.gyr.x, (float)2000, dev.resolution);
- y = lsb_to_dps(sensor_data.sens_data.gyr.y, (float)2000, dev.resolution);
- z = lsb_to_dps(sensor_data.sens_data.gyr.z, (float)2000, dev.resolution);
- /* Print the data in dps. */
- printf("%d, %d, %d, %d, %d, %4.2f, %4.2f, %4.2f\n",
- indx,
- config.cfg.gyr.range,
- sensor_data.sens_data.gyr.x,
- sensor_data.sens_data.gyr.y,
- sensor_data.sens_data.gyr.z,
- x,
- y,
- z);
- indx++;
- HAL_DelayMs(2000);
- }
- }
复制代码
输出结果 将程序下载到NUCLEO-G070开发板中,运行程序,打开友善串口调试助手,选择正确的串口号,稍后将显示接收到的数据:
|