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 驱动进行交互,将硬件驱动提供的数据转换为上层可以使用的标准数据格式。

软件架构图:

software_architecture_diagram.png

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 函数,传入传感器句柄,该函数会调用相应的传感器抽象层释放函数,释放传感器占用的资源。

api_process

3.13.2. 编译部署

3.13.2.1. 编译

进入到 SDK 源码中。使用 Makefile 编译程序:

make

该命令会根据 Makefile 中的规则,将源代码编译成可执行文件 sample_imu。

3.13.2.2. 硬件环境搭建

可以参考如下连接方式 ( 使用的传感器是 BMI08x):

40pin_connect

确认硬件连接正确之后,我们还需要确认相应的驱动配置是否有打开。\

首先我们检查 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 去开启。
搜索位置可以参考如下截图
boot_menuconfig_search

打开方式可以参考如下截图
boot_menuconfig_config

最后编译整个镜像,刷机之后,检查一下该 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 开发应用程序。