IMU模块BMI088加速度计陀螺仪的PCB硬件设计和PX4驱动配置
BMI088简介
BMI088是一种惯性测量单元(IMU),用于检测6自由度的运动和旋转。它将两个惯性传感器的功能结合在一个设备中:一个先进的三轴16位陀螺仪和一个通用的、前沿的三轴16bit加速度计。
硬件设计
封装
采用了标准的LGA封装,单位是毫米。
引脚序号。
引脚定义。
原理图
使用SPI总线进行连接时的原理图。
使用I2C总线进行连接时的原理图。
PCB设计
我这里使用的是SPI总线进行连接,连接到MCU主控的SPI2接口。
主控选择的是STM32H743VIH6,SPI2总线是使用的MOSI-PC1引脚、MISO-PC2引脚、SCK-PD3引脚,陀螺仪的片选信号Gyro_CS是使用PC13引脚,加速度计的片选信号Accel_CS是使用PC3引脚,陀螺仪的数据准备完毕信号Gyro_Data_Ready是使用PE3引脚,加速度计的数据准备完毕信号Accel_Data_Ready是使用PE4引脚,这些信息需要记录下来,之后在PX4配置中需要用到。
引脚选择问题
这里需要注意不是所有的引脚都可以作为BMI088的连接引脚,这个需要在给定的几种方案中选择。
对于主控STM32H743VIH6来说,有以下的引脚映射头文件。
其中有以下内容:
#define GPIO_SPI2_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN14)
#define GPIO_SPI2_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN2)
#define GPIO_SPI2_MISO_3 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTI|GPIO_PIN2)
#define GPIO_SPI2_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN15)
#define GPIO_SPI2_MOSI_2 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN1)
#define GPIO_SPI2_MOSI_3 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN3)
#define GPIO_SPI2_MOSI_4 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTI|GPIO_PIN3)
#define GPIO_SPI2_NSS_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTA|GPIO_PIN11)
#define GPIO_SPI2_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN12)
#define GPIO_SPI2_NSS_3 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN9)
#define GPIO_SPI2_NSS_4 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTI|GPIO_PIN0)
#define GPIO_SPI2_NSS_5 (GPIO_ALT|GPIO_AF7|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN4)
#define GPIO_SPI2_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTA|GPIO_PIN12)
#define GPIO_SPI2_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTA|GPIO_PIN9)
#define GPIO_SPI2_SCK_3 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN10)
#define GPIO_SPI2_SCK_4 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN13)
#define GPIO_SPI2_SCK_5 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTD|GPIO_PIN3)
#define GPIO_SPI2_SCK_6 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTI|GPIO_PIN1)
所以SPI2总线的MISO引脚只能从PB14、PC2、PI2中选择,MOSI引脚只能从PB15、PC1、PC3、PI3中选择,SCK引脚只能从PA12、PA9、PB10、PB13、PD3、PI1中选择。
对于片选信号的选择,可以选择任意空闲的GPIO口。
对于数据准备完毕信号的选择,由于该信号使用的是STM32的外部中断输入功能,所以它们的外部中断号不能重复,比如PE3的外部中断号是EXTI3、PE4的外部中断号是EXTI4,如果使用了外部中断号是EXTI3的PE3,那么在之后的其他数据准备完毕信号的选择中就不能选择外部中断号是EXTI3的PA3、PB3、PC3等引脚。
朝向问题
在进行PCB设计时需要注意该芯片的朝向问题。
芯片尽量放在PCB的顶面(重力沿Z轴负方向),且芯片的X轴正方向尽量与飞控的正前方向重合。
如果因为各种原因导致没有办法按上述规则进行放置,也尽量按沿Z轴旋转45°、90°等整数位置进行放置,并随后在PX4中传感器启动部分进行额外配置。
PX4驱动配置
飞控板的配置文件夹结构
飞控板的配置文件夹结构为下列所示。
YanQi
├─extras
| └─UCAS_YanQi_bootloader.bin
├─init
| ├─rc.board_defaults
| └─rc.board_sensors
├─nuttx-config
| ├─bootloader
| | └─defconfig
| ├─include
| | ├─board.h
| | └─board_dma_map.h
| ├─nsh
| | └─defconfig
| ├─scripts
| | ├─bootloader_script.ld
| | └─script.ld
| ├─src
| └─Kconfig
├─src
| ├─board_config.h
| ├─bootloader_main.c
| ├─CMakeLists.txt
| ├─hw_config.h
| ├─i2c.cpp
| ├─init.c
| ├─...
| └─usb.c
├─bootloader.px4board
├─default.px4board
└─firmware.prototype
default.px4board文件
default.px4board文件是最常使用的文件,它负责配置每个串口的映射,配置哪些源码被编译到飞控固件中。由于需要使用BMI088的驱动,所以需要添加一行代码。
CONFIG_DRIVERS_IMU_BOSCH_BMI088=y
nuttx-config/nsh/defconfig文件
nuttx-config/nsh/defconfig文件配置的是飞控固件中需要调用的底层资源,比如串口驱动、SPI驱动、I2C驱动等等。
这里使用的是SPI2总线,所以需要添加以下代码。
CONFIG_STM32H7_SPI2=y
如果需要使用DMA功能,则还需要添加以下代码。
CONFIG_STM32H7_DMA1=y
CONFIG_STM32H7_DMA2=y
CONFIG_STM32H7_SPI2_DMA=y
CONFIG_STM32H7_SPI2_DMA_BUFFER=2048
nuttx-config/include/board.h文件
board.h文件用于配置NuttX操作系统中的时钟和引脚,对于所有具有多功能引脚(比如STM32中的有些引脚既可以作为UART也可以作为普通GPIO)的外围设备,NuttX需要知道每个引脚的设定功能,它们在芯片特定的引脚映射头文件stm32h7x3xx_pinmap.h中定义。
需要按照之前的原理图设计对应引脚映射头文件进行修改。
SPI2的引脚定义设置的代码。
#define ADJ_SLEW_RATE(p) (((p) & ~GPIO_SPEED_MASK) | (GPIO_SPEED_2MHz))
#define GPIO_SPI2_MISO GPIO_SPI2_MISO_2 /* PC2 */
#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_2 /* PC1 */
#define GPIO_SPI2_SCK ADJ_SLEW_RATE(GPIO_SPI2_SCK_5) /* PD3 */
nuttx-config/include/board_dma_map.h文件
board_dma_map.h文件用于配置DMA。DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动,这就节省了CPU的资源来做其他操作。
注意:DMA1只支持8个通道!DMA2只支持8个通道!
需要按照DMA映射头文件进行配置,这里选择了SPI2的DMA1通道。
#define DMAMAP_SPI2_RX DMAMAP_DMA12_SPI2RX_0 /* DMA1:39 */
#define DMAMAP_SPI2_TX DMAMAP_DMA12_SPI2TX_0 /* DMA1:40 */
src/spi.cpp文件
需要按照之前的原理图设计的片选信号和数据准备完毕信号进行配置SPI::CS{GPIO::PortC, GPIO::Pin13}
和SPI::DRDY{GPIO::PortE, GPIO::Pin3}
。
constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = {
/* SPI 2通道 */
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(DRV_GYR_DEVTYPE_BMI088, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin3}),
initSPIDevice(DRV_ACC_DEVTYPE_BMI088, SPI::CS{GPIO::PortC, GPIO::Pin3}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
}),
};
init/rc.board_sensors文件
rc.board_sensors文件作用是启动连接到板上的传感器。
-A 是加速度计,-G 是陀螺仪。
-s 是 Internal SPI 启动,-S 是 External SPI 启动。
-R 后面是旋转角度。如果之前的芯片的X轴正方向不是沿着飞控的正前方向。这里就不能使用默认参数0了,这里的参数既不是角度制的角度也不是弧度制的角度,这里的数字需要根据旋转的角度进行选择。
uint8 orientation # Direction the sensor faces from MAV_SENSOR_ORIENTATION enum
uint8 ROTATION_YAW_0 = 0 # MAV_SENSOR_ROTATION_NONE
uint8 ROTATION_YAW_45 = 1 # MAV_SENSOR_ROTATION_YAW_45
uint8 ROTATION_YAW_90 = 2 # MAV_SENSOR_ROTATION_YAW_90
uint8 ROTATION_YAW_135 = 3 # MAV_SENSOR_ROTATION_YAW_135
uint8 ROTATION_YAW_180 = 4 # MAV_SENSOR_ROTATION_YAW_180
uint8 ROTATION_YAW_225 = 5 # MAV_SENSOR_ROTATION_YAW_225
uint8 ROTATION_YAW_270 = 6 # MAV_SENSOR_ROTATION_YAW_270
uint8 ROTATION_YAW_315 = 7 # MAV_SENSOR_ROTATION_YAW_315
比如如果芯片的X轴正方向指向飞控的右侧,那么就需要将坐标轴沿YAW轴旋转90度,则参数应该选择ROTATION_YAW_90,设为2。
-b 后面是SPI总线序号。
# 内部 SPI 总线 BMI088 加速度计、陀螺仪
bmi088 -b 2 -A -R 0 -s start
bmi088 -b 2 -G -R 0 -s start
编译BootLoader和Firmware并烧录进自己的飞控板
在Firmware文件夹中输入命令即可对BootLoader和固件进行编译。
make UCAS_YanQi_bootloader
make UCAS_YanQi_default
没有安装烧录工具的先安装dfu-util烧录工具包。
sudo apt install dfu-util
按住飞控板上的BOOT键同时将USB线插入飞控板,进入DFU模式,运行命令即可进行BootLoader烧录。
dfu-util -a 0 --dfuse-address 0x08000000 -D ./build/UCAS_YanQi_bootloader/UCAS_YanQi_bootloader.bin
之后使用QGC安装UCAS_YanQi_default.px4飞控固件即可。