STM32 HAL 硬件IIC驱动BNO085(附上源码)
做大创买的BNO085,可后来换了IMU,我就打算拿这个来做飞控得了,反正这么好的IMU不用白不用。
之前问过tb商家要资料,没有stm32的;也找过很多文章,没找到一篇很详细说怎么移植这个IMU的(详细的都要VIP,我就算了,就当作学习分享吧)。可能是这个IMU太贵了吧,不过贵也有它贵的原因,精度高嘛(用mpu6050实在绷不住了,自己用卡尔曼滤波做姿态解算但是缺个磁力计,计算不了Yaw)。
我试过用软件IIC,后来失败了。现在放假,还是不甘心,又想尝试用硬件IIC来做了。没想到这次一晚上就搞定了,果然还是HAL库的硬件IIC强。
本来也想用esp32来驱动的,但我的esp32一用串口打印就会报错(我也不知道为什么,希望看到的大佬可以帮我解释一下),干脆不用esp32了,就用stm32(我也经常用stm32,比较熟悉)。
源码在后面。
代码移植这里的,改一改就可以用了。开源BNO085陀螺仪读取数据 - 全国大学生智能汽车竞赛,清华卓老师 国芯技术交流网站 - AI32位8051交流社区
1. RCC,选外部晶振,时钟频率100MHz(我的是STM32F411CEU6)。
2. SYS里面打开Serial Wire,用于stlink烧录程序(不用管TIM11,我这是打开了FreeRTOS,所以要选择其它时钟)。
3. IIC配置,使用的是IIC1,PB6是SCL,PB7是SDA,选择Fast Mode(手册说支持100k和400k,都用硬件IIC了,用就用最快的)。
4. 打开串口1(调试看数据的)
5. 项目管理,选好存放项目的路径
(这里的IDE要注意一下,因为我用的是vscode而不是Keil,所以选的是Makefile,用Keil的要选MDK-ARM。也想用vscode的话,可以看这个视频,这里的重点不是这个。抛弃keil?VScode开发stm32完整教程_哔哩哔哩_bilibili)
勾上这些
然后生成项目。
6. 下载好开头的文件,将这2个文件复制到自己的项目里面
这个是我的项目。
7. 在main.h里面include一下”bno08x.h“,然后编译。
报错1
改为”#include \"main.h\"“,再编译。
报错2
删掉它,再编译。
报错3,一大堆,这个不慌。
删掉这个delay。
再划到IIC部分,这些typedef删掉。
保留void I2C_Init(void),把下面每个IIC的时序删掉,void WriteNbyte(u8 *p, u8 number)和void ReadNbyte(u8 *p, u8 number)里面的时序也删掉,再编译。
这次没报错,但是有个问题,就是delay被我删掉了,所以要把delay改成HAL_Delay()。ctrl+F查找delay,选上替换(replace),填入HAL_Delay。只有4个,全部替换,再编译。
换完之后再编译,没问题,继续改代码。
8. include一下“i2c.h”
9. 修改void I2C_Init(void) 、void WriteNbyte(u8 *p, u8 number)和void ReadNbyte(u8 *p, u8 number)
在头文件先添加这2个地址,这个是BNO085的读和写地址。
再回到c文件,将3个函数改成下面这样。
编译,没毛病。
10. 点开头文件,注释掉这2个有虚线的函数。
11. 回到main里面, 初始化一下IIC
12. 复位一下,然后这些enable全都用上一下,全部填100(这个是IMU发数据的时间间隔,以ms为单位),开一下校准
可以只选自己想要的数据,这里我懒得选了,全都用上。可以参考手册说的频率来设置。
13. 读一下加速度的数据,大循环写下面的代码,编译烧录。
(这里要先重定向一下串口
这个是Keil的
【STM32】HAL库三步实现串口重定向(代码复制可用)_stm32串口重定向hal库-CSDN博客
这个是vscode的
基于 VsCode + GCC + STM32 环境下的串口输入输出重定向_gcc libc 重定向-CSDN博客)
14. 打开VOFA+看一下数据
没有数据,这里也别慌,这个是用vscode打印浮点数的毛病,
打开”构建配置:GCC“的“构建器选型”,在“编译器附加选项”添加“-u_printf_float”
修改后(一定要点一下“全部保存”,不然不会自动保存)
之后再编译烧录。
可以打印了,但是数据好像有点问题。
有255的,这说明数据类型转换出了问题,跳到getAccelX()的定义
再跳到qToFloat的定义
这里看起来好像是qPoint的类型有问题,我改过之后,还是不行。后来我想到,int类型在不同的单片机或者不同的系统代表的数据类型不一样,可能是int16_t也可能是int32_t,所以我打印了一下fixedPointValue。先注释掉大循环里面的打印,在这里面打印一下fixedPointValue看看。
发现有65531这种接近65535的数据,说明确实是我的单片机的int代表的是int32_t类型,将fixedPointValue的类型改为int16_t,头文件的声明也要改一下,编译烧录。
这个看起来正常多了。去大循环打印一下加速度看看。
现在就正常了。
15. 读一下四元数,解算一下姿态角。第1个旋转向量就是四元数,只需要打开第1个enable,四元数转欧拉角的公式问一下GPT就可以了,挺简单的。这里要注意的是要单位转换一下,因为atan2和asin返回的数据是以rad为单位的,要乘一下57.3(就是180/pi)。编译烧录。
可以看到解算到的姿态角,这个姿态角的yaw可能是静止参考系的,每次复位都是有一个角度。
下面是源码(我一开始开了FreeRTOS,我把调度器给注释了才能到大循环的,这里要注意一下):
mian.c
/* USER CODE BEGIN Header *//** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** *//* USER CODE END Header *//* Includes ------------------------------------------------------------------