3.13. sample_imu 使用说明
3.13.1. 功能概述
sample_imu 是一个用于使用惯导传感器的命令行案例,主要实现了基于 IIO 接口对惯性测量单元( IMU)数据的读取、处理和显示功能。
通过该程序,用户可以方便地获取 IMU 传感器的加速度、陀螺仪和磁力计数据( IMU 具备的才行),并进行相应的分析和应用。
3.13.1.1. 软件架构说明
我们对 sample_imu 做了如下的软件设计
__ 应用层 __: sample_imu.c 作为程序的入口,负责解析命令行参数、初始化传感器、处理用户输入的命令以及读取和显示传感器数据。
__ 管理层 __: imu_manager.h 和 imu_manager.c 提供了传感器管理的接口和实现,包括列出可用传感器、初始化传感器、读取传感器数据、释放传感器资源等功能。
__ 适配层 __: imu_interface.h 定义了读取传感器接口的结构体,为具体传感器做好统一。
__ 传感器抽象层 __:这一层针对具体的传感器进行抽象实现,负责与底层的硬件 IIO 驱动进行交互,将硬件驱动提供的数据转换为上层可以使用的标准数据格式。
软件架构图:

3.13.1.2. 代码位置及目录结构
SDK 中的位置:/app/samples/platform_samples/sample_imu/
该目录包含 sample_imu 源码。编译后会生成名为 sample_imu 的可执行文件,以及中间产物。
.
├── bmi08x.c
├── imu_interface.h
├── imu_manager.c
├── imu_manager.h
├── Makefile
└── sample_imu.c
以下是各个文件的详细介绍:
Makefile:用于编译程序的 Makefile 文件,定义了编译规则和依赖关系。
sample_imu.c:程序的主要源代码文件,包含了程序的入口函数 main,负责整个程序的流程控制。
imu_manager.h 、 imu_manager.c:实现了传感器管理的功能,提供了统一的接口供应用层调用。
imu_interface.h:定义了传感器驱动的接口指针,包括初始化、读取数据和释放资源等 函数指针。
bmi08x.c:实现了 BMI08x 传感器抽象层,与 bmi08x 注册的 IIO 硬件驱动进行交付 具体实现了初始化、数据读取和资源释放等逻辑。 如果后续需要添加其他传感器,参考 bmi08x.c 的实现,和 imu_interface.h 接口。进行相应的实现即可。
3.13.1.3. 工具位置及目录结构
板端可执行程序位置:/app/platform_samples/sample_imu/sample_imu
该目录下包含编译后的可执行文件,使用的时候根据 程序运行方法 使用即可。
3.13.1.4. 背景知识
惯性测量单元( IMU)是一种用于测量物体的加速度、角速度和磁力等物理量的设备,通常由加速度计、陀螺仪和磁力计组成。加速度计用于测量物体在三个轴向上的加速度,陀螺仪用于测量物体的角速度,磁力计用于测量物体周围的磁场强度。通过对这些物理量的测量和分析,可以获取物体的姿态、运动状态等信息。需要注意的是,不是所有的 IMU 传感器都具备所有的传感器,行业中有单独售卖加速度计、陀螺仪和磁力计这三种传感器的,也有分六轴九轴等 IMU 进行售卖。
3.13.1.5. API 流程说明
sample_imu 没有用到特定的 API ,使用的都是 kernel 中标准的接口,来构建的整个应用程序。所以更多是结合 sample_imu 中的函数对 API 流程进行说明。
1 、列出可用传感器:调用 list_available_sensors 函数,该函数会遍历支持的传感器驱动列表,并打印出所有支持的传感器名称。
2 、初始化传感器:调用 init_sensor 函数,传入传感器类型和参数,该函数会查找并验证对应的 IIO 设备,然后调用相应的驱动初始化函数进行传感器的初始化。
3 、读取传感器数据:调用 read_sensor_data 函数,传入传感器句柄和数据结构体指针,该函数会调用相应的传感器抽象层读取函数,将传感器数据读取到数据结构体中并打印。
4 、释放传感器资源:调用 release_sensor 函数,传入传感器句柄,该函数会调用相应的传感器抽象层释放函数,释放传感器占用的资源。

3.13.2. 编译部署
3.13.2.1. 编译
进入到 SDK 源码中。使用 Makefile 编译程序:
make
该命令会根据 Makefile 中的规则,将源代码编译成可执行文件 sample_imu。
3.13.2.2. 硬件环境搭建
可以参考如下连接方式 ( 使用的传感器是 BMI08x):

确认硬件连接正确之后,我们还需要确认相应的驱动配置是否有打开。\
首先我们检查 dts, EVB 板子使用的是 x5-evb.dtsi 文件, 检查对应的 i2c5 节点是否有配置,如果没有,可以参考如下配置加上去
&i2c5 {
status = "okay";
......
bmi08a@19 {
compatible = "bmi08xa";
reg = <0x19>;
interrupt-parent = <&ls_gpio1_porta>;
interrupts = <4 IRQ_TYPE_EDGE_RISING>;
status = "okay";
};
bmi08g@69 {
compatible = "bmi08xg";
reg = <0x69>;
interrupt-parent = <&ls_gpio1_porta>;
interrupts = <6 IRQ_TYPE_EDGE_RISING>;
status = "okay";
};
};
该 IMU 也支持 SPI 接口,如果要使用,也可以参考设备树的配置:
&spi1 {
/*When dual chip select is used, the number of SPI chip selects must be set to 2.*/
/*num-cs = <2>;*/
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1 &pinctrl_spi1_ssn1>;
dma-names = "tx", "rx";
dmas = <&axi_dmac 23>, <&axi_dmac 22>;
bmi08g@0 {
compatible = "bmi088_gyro";
reg = <0>;
spi-max-frequency = <5000000>;
interrupt-parent = <&ls_gpio1_porta>;
interrupts = <6 IRQ_TYPE_EDGE_RISING>;
status = "okay";
};
bmi08a@1 {
compatible = "bmi08a";
reg = <1>;
spi-max-frequency = <5000000>;
interrupt-parent = <&ls_gpio1_porta>;
interrupts = <4 IRQ_TYPE_EDGE_RISING>;
status = "okay";
};
};
注意,这里只能选择一个接口进行使用,所以设备树配置的时候,没有使用的接口,可以设置成 disabled 状态。
然后检查对应 deconfig ( 比如 EVB 默认使用的是 hobot_x5_soc_defconfig) 是否有开启
CONFIG_BMI08X_SUPPORT_I2C_BUS=m
CONFIG_BMI08X_SUPPORT_SPI_BUS=m
可以通过 menuconfig 去开启。
搜索位置可以参考如下截图 
打开方式可以参考如下截图 
最后编译整个镜像,刷机之后,检查一下该 IMU 是否有成功注册,可以通过如下两种办法检查: ( 1 )通过 LOG 检查
root@buildroot:~# dmesg | grep BS
[ 0.084965] CPU features: detected: Speculative Store Bypassing Safe (SSBS)
[I]\x016<BS_LOG><bmi08_i2c_probe><187>client->name:bmi08xa / addr: 0x19
[I]\x016<BS_LOG><bmi08_i2c_probe><187>client->name:bmi08xg / addr: 0x69
[I]\x016<BS_LOG><sensor_init><1057>accel initilized
[I]\x016<BS_LOG><sensor_init><1064>gyro initilized
[I]\x016<BS_LOG><sensor_init><1065>sensor initilized
[I]\x016<BS_LOG><sensor_init><1072>soft reset done
[I]\x016<BS_LOG><sensor_init><1080>config stream loaded successfully
[I]\x016<BS_LOG><sensor_init><1090>Accel power mode set to NORMAL
[I]\x016<BS_LOG><sensor_init><1099>Gyro power mode set to NORMAL
[I]\x016<BS_LOG><bmi08_probe><2216>Acc chip ID : 0x1e, Gyro chip ID : 0xf
[I]\x016<BS_LOG><bmi08_request_irq><544>ACC IRQ requested for pin : 56
[I]\x016<BS_LOG><bmi08_probe><2227>ACC IRQ requested
[I]\x016<BS_LOG><bmi08_gyr_request_irq><563>GYR IRQ requested for pin : 57
[I]\x016<BS_LOG><bmi08_probe><2234>GYR IRQ requested
[I]\x016<BS_LOG><bmi08_probe><2236>sensor bmi088 probed successfully
[ 4.687140] CAM_SUBSYS soc:cam:cam_sys@0: [FRT:D] camsys_probe(0)
root@buildroot:~#
可以看到可以读到 sensor 的 id 了:\
[I]\x016<BS_LOG><bmi08_probe><2216>Acc chip ID : 0x1e, Gyro chip ID : 0xf
( 2 )通过检查 IIO 子系统中是否有成功注册上 IMU,例如我们可以到 iio 子系统中检查 name 节点:\
root@buildroot:~# cd /sys/bus/iio/devices/iio\:device1/
root@buildroot:/sys/bus/iio/devices/iio:device1# cat name
bmi08x
root@buildroot:/sys/bus/iio/devices/iio:device1#
3.13.2.3. 程序部署
编译后可执行文件一般在源码同级目录下,即 /app/samples/platform_samples/sample_imu/ 目录下。
.
├── bmi08x.c
├── bmi08x.o
├── imu_interface.h
├── imu_manager.c
├── imu_manager.h
├── imu_manager.o
├── Makefile
├── sample_imu
├── sample_imu.c
└── sample_imu.o
本 sample 的可执行文件已经默认部署在板端 /app/platform_samples/sample_imu/sample_imu 位置。
当然也可以将编译好的可执行文件复制到开发板的任意目录下,以便运行。
3.13.3. 运行
3.13.3.1. 程序运行方法
直接运行可执行文件:
./sample_imu
或者使用命令行参数指定配置:
./sample_imu -n bmi08x
其中,-n 参数用于指定要使用的 IMU 传感器名称,默认值为 bmi08x。
3.13.3.2. 程序参数选项说明
Usage: sample_imu [OPTIONS]
Options:
-n <imu_name> Specify IMU name (default: bmi08x)
-h Show this help message
-n <imu_name>:指定要使用的 IMU 传感器名称,例如 bmi08x。
-h:显示帮助信息,列出所有可用的命令行参数和其说明。
3.13.3.3. 运行效果
程序运行后,会显示一个命令菜单,用户可以输入相应的命令来获取传感器数据:
root@buildroot:/app/platform_samples/sample_imu# ./sample_imu
No IMU specified, using default: bmi08x
Using IMU: bmi08x
=== Detected IIO Devices ===
Device: iio:device1 | Name: bmi08x
Device: iio:device0 | Name: 34190000.adc
============================
Device validation passed at: /sys/bus/iio/devices/iio:device1
BMI08x: Initializing with params:
*************** Command Lists ***************
g -- Get a single frame of imu data
l -- Get multiple frames of imu data
q -- Quit the program
h -- Print this help message
Enter command:
不带参数执行的时候,会默认选择 bmi08x 这颗 IMU,然后列举出所有 iio 下的 device name。
如果正常初始化,则会来到读取数据的选项列表,中文说明如下:
g:获取一帧 IMU 数据。
l:获取多帧 IMU 数据,需要输入要获取的帧数。
q:退出程序。
h:显示帮助信息。
获取一帧 IMU 数据运行效果:
*************** Command Lists ***************
g -- Get a single frame of imu data
l -- Get multiple frames of imu data
q -- Quit the program
h -- Print this help message
Enter command: g
Data received (Frame 1):
Accelerometer: [-117.836021, -118.283142, 9.569026] m/s ²
Gyroscope: [0.006392, -69.885605, 0.049002] rad/s
Timestamp: 00:01:38.917.929
获取多帧 IMU 数据运行效果(这里以 3 帧为例):
*************** Command Lists ***************
g -- Get a single frame of imu data
l -- Get multiple frames of imu data
q -- Quit the program
h -- Print this help message
Enter command: l
Enter number of frames to read: 100
Data received (Frame 1):
Accelerometer: [-117.870140, -118.261597, 9.597756] m/s ²
Gyroscope: [0.019175, 0.010653, -69.857903] rad/s
Timestamp: 00:01:50.861.640
Data received (Frame 2):
Accelerometer: [-117.825249, -118.283142, 9.574412] m/s ²
Gyroscope: [0.014914, -69.857903, -69.887733] rad/s
Timestamp: 00:01:50.867.500
Data received (Frame 3):
Accelerometer: [-117.825249, -118.283142, 9.597756] m/s ²
Gyroscope: [-69.898384, 0.055394, -69.879211] rad/s
Timestamp: 00:01:50.873.320
Data received (Frame 4):
Accelerometer: [-117.818069, -118.283142, 9.597756] m/s ²
Gyroscope: [0.046872, -69.919693, -69.851517] rad/s
Timestamp: 00:01:50.879.140
......
3.13.4. 常见问题
已经接上设备,但是没有识别到设备
我们首先要保证硬件连接是正确的,检查 IMU 传感器与开发板之间的连线是否松动、短路或接错。
可以参考开发板使用指南中的 40PIN 连接举例部分 进行检查。其次,我们要检查驱动是否有向 iio 框架正常注册。 sample_imu 在运行的时候会列举 iio 下面
的所有设备,如果没有发现期望的设备,那么就需要检查驱动注册情况。需要特别注意,该 sample_imu 暂时只包含了 bmi08x ,如果需要其他 IMU 的 sample,请先参考
驱动开发说明,基于 iio 框架下注册 IMU 之后,再结合 sample_imu 开发应用程序。