当前位置: 首页 > news >正文

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1

        本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA+上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增滤波参数优化,重点解决yaw值漂移问题,提供完整的参数调优方案和效果对比。

目录

STM32F1

一、硬件准备

二、软件环境搭建

三、核心代码实现

四、VOFA+上位机配置

五、滤波参数优化与动态效果对比

六、效果演示

七、 效果验证与结论


一、硬件准备

1.硬件清单

  • 零知标准板(主控STM32F103RBT6)

  • ICM20948九轴传感器模块

  • USB转串口模块(用于调试和数据传输)

  • 杜邦线若干

2.接线方式

ICM20948引脚零知开发板引脚
VCC3.3V
GNDGND
SDAA4
SCLA5
硬件连接图

连接实物图 

注意:确保I2C引脚正确,避免接反导致芯片损坏。

二、软件环境搭建

开发环境

  • 零知 IDE + 零知开发板支持包

  • 所需库文件:

      AHRSAlgorithms.cpp(姿态解算库)

      ICM20948.cpp(传感器驱动库)

库文件关键功能

  • AHRSAlgorithms.cpp

                Madgwick/Mahony滤波算法

                四元数实时输出 getQ()

                参数可调:KpKibeta

  • ICM20948.cpp

                I2C通信底层驱动

                自动量程配置(加速度计±2/4/8/16g,陀螺仪±250/500/1000/2000dps)

                磁力计初始化 initAK09916()

                校准函数 calibrateICM20948()

三、核心代码实现

主程序框架 

(ICM20948_VOFA.ino)

/* ICM20948完整优化代码 */
#include "AHRSAlgorithms.h"
#include "ICM20948.h"#define AHRS true
#define SerialDebug true int myLed = LED_BUILTIN;  
ICM20948 myIMU;void setup() {pinMode(myLed, OUTPUT);digitalWrite(myLed, HIGH);Serial.begin(115200);Wire.begin();// 初始化与自检if(myIMU.begin()) {Serial.println("ICM20948初始化成功");// 执行两级校准myIMU.calibrateICM20948(myIMU.gyroBias, myIMU.accelBias);float magBias[3], magScale[3];myIMU.magCalICM20948(magBias, magScale);// 设置优化分辨率myIMU.getAres(); myIMU.getGres();myIMU.getMres();} else {Serial.println("传感器初始化失败!");while(1);}
}void loop() {// 数据读取if (myIMU.readByte(ICM20948_ADDRESS, INT_STATUS_1) & 0x01) {myIMU.readAccelData(myIMU.accelCount);myIMU.readGyroData(myIMU.gyroCount);myIMU.readMagData(myIMU.magCount);// 单位转换myIMU.ax = (float)myIMU.accelCount[0] * myIMU.aRes;myIMU.ay = (float)myIMU.accelCount[1] * myIMU.aRes;myIMU.az = (float)myIMU.accelCount[2] * myIMU.aRes;myIMU.gx = (float)myIMU.gyroCount[0] * myIMU.gRes;myIMU.gy = (float)myIMU.gyroCount[1] * myIMU.gRes;myIMU.gz = (float)myIMU.gyroCount[2] * myIMU.gRes;myIMU.mx = (float)myIMU.magCount[0] * myIMU.mRes - myIMU.magBias[0];myIMU.my = (float)myIMU.magCount[1] * myIMU.mRes - myIMU.magBias[1];myIMU.mz = (float)myIMU.magCount[2] * myIMU.mRes - myIMU.magBias[2];}// 更新时间基准myIMU.updateTime();// 姿态解算(使用优化参数)MahonyQuaternionUpdate(myIMU.ax, myIMU.ay, myIMU.az,myIMU.gx * DEG_TO_RAD, myIMU.gy * DEG_TO_RAD,myIMU.gz * DEG_TO_RAD,myIMU.my, myIMU.mx, myIMU.mz, // 轴序修正myIMU.deltat);// 转换为欧拉角const float* q = getQ();myIMU.yaw   = atan2(2.0f*(q[1]*q[2] + q[0]*q[3]), q[0]*q[0] + q[1]*q[1] - q[2]*q[2] - q[3]*q[3]) * RAD_TO_DEG;myIMU.pitch = -asin(2.0f*(q[1]*q[3] - q[0]*q[2])) * RAD_TO_DEG;myIMU.roll  = atan2(2.0f*(q[0]*q[1] + q[2]*q[3]),q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]) * RAD_TO_DEG;// 发送到VOFA+Serial.print(myIMU.yaw, 1);   // yawSerial.print(",");Serial.print(myIMU.pitch, 1); // pitchSerial.print(",");Serial.println(myIMU.roll, 1);// rolldelay(10); // 100Hz输出
}

 关键配置修改

 在 ICM20948.cpp 中调整量程(根据应用需求):


// 加速度计量程 (AFS_2G/AFS_4G/AFS_8G/AFS_16G)
void ICM20948::getAres()
{switch (Ascale){// Possible accelerometer scales (and their register bit settings) are:// 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs  (11).// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that// 2-bit value:case AFS_2G:aRes = 2.0f / 32768.0f;break;case AFS_4G:aRes = 4.0f / 32768.0f;break;case AFS_8G:aRes = 8.0f / 32768.0f;break;case AFS_16G:aRes = 16.0f / 32768.0f;break;}
}// 陀螺仪量程 (GFS_250DPS/GFS_500DPS/GFS_1000DPS/GFS_2000DPS)
void ICM20948::getGres()
{switch (Gscale){// Possible gyro scales (and their register bit settings) are:// 250 DPS (00), 500 DPS (01), 1000 DPS (10), and 2000 DPS (11).// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that// 2-bit value:case GFS_250DPS:gRes = 250.0f / 32768.0f;break;case GFS_500DPS:gRes = 500.0f / 32768.0f;break;case GFS_1000DPS:gRes = 1000.0f / 32768.0f;break;case GFS_2000DPS:gRes = 2000.0f / 32768.0f;break;}
}

四、VOFA+上位机配置

数据协议设置

  • 选择 FireWater 协议

  • 格式:q0, q1, q2(逗号分隔+换行符)

  • 波特率:115200

控件添加

  • 3D立方体:显示实时姿态

                绑定四元数数据通道

                设置模型缩放比例

  • 波形图:各轴角速度/加速度

  • 仪表盘:显示偏航角(Yaw)

界面效果

实时显示传感器3D姿态及运动波形

五、滤波参数优化与动态效果对比

1.传感器校准

float gyroBias[3], accelBias[3];
IMU.calibrateICM20948(gyroBias, accelBias); // 上电时执行一次

2.问题现象

使用默认参数(Kp=5.0, Ki=0.1)时,VOFA+显示yaw值持续漂移(约2-5°/s),动态运动时零漂明显

3.优化方案

 在AHRSAlgorithms.h中调整Mahony滤波参数:

// 原参数(漂移明显)
// #define Kp 2.0f * 5.0f
// #define Ki 0.0f// 优化参数(大幅改善漂移)
#define Kp 3.0f    // 降低比例增益,减少高频噪声响应
#define Ki 0.1f   // 降低积分增益,抑制累积误差

效果对比

参数状态Yaw漂移率VOFA+动态表现
默认(Kp=10f,Ki=0.0f)2-5°/s静止时缓慢旋转,运动后复位慢
优化(Kp=3.0f,Ki=0.1f)<0.5°/s静止稳定,运动后快速收敛

4.优化后效果

参数调整原理

Kp过高:对加速度计噪声敏感,导致高频抖动

Ki过高:积分累积误差引起零漂

黄金比例Kp/Ki ≈ 20-30 时平衡动态响应与稳定性

六、效果演示

静态测试

  • 传感器平放时,VOFA+显示俯仰角/横滚角接近0°

  • Z轴加速度≈9.8 m/s²

动态测试

  • 旋转开发板,3D模型同步跟随

  • 快速晃动时波形图显示各轴加速度变化

ICM20948九轴传感器动态测试

输出速率调优

  • ICM20948原始数据输出率约100Hz(10ms/次)

  • delt_t=60ms时,姿态解算循环(16.7Hz)与传感器更新周期不同步

  • 导致部分数据帧被重复使用或跳过

完整工程代码

百度网盘获取完整工程文件,链接如下:

零知标准板驱动ICM20948项目工程https://pan.baidu.com/s/11tr8XJvNrNernqwK1zA9Mw?pwd=pbxd 

七、 效果验证与结论

测试结果

指标优化前优化后
静态yaw漂移2-5°/s<0.5°/s
动态收敛时间>3s<1s
高温稳定性漂移增加300%漂移增加<50%

结论

  • 通过调整Kp/Ki比例可有效抑制yaw漂移
  • 磁力计轴序修正提升方位角精度
  • VOFA+可视化提供直观参数调优依据
  • 三阶段校准确保全温度范围稳定性

 ✔(●'◡'●)

零知开源是一个真正属于国人自己的开源软硬件平台,在开发效率以及上手难度上超越了Arduino平台。
零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧! 

零知实验室--模块商城 专注前沿技术研发

http://www.xdnf.cn/news/899947.html

相关文章:

  • AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
  • 【AUTOSAR COM CAN】CanSM模块的实现与应用解析
  • 对象存储Ozone EC应用和优化
  • 大语言模型提示词(LLM Prompt)工程系统性学习指南:从理论基础到实战应用的完整体系
  • 装饰模式(Decorator Pattern)重构java邮件发奖系统实战
  • leetcode_206 反转链表
  • PDF转Markdown/JSON软件MinerU最新1.3.12版整合包下载
  • 元图CAD:一键解锁PDF转CAD,OCR技术赋能高效转换
  • 网络安全逆向分析之rust逆向技巧
  • 不到 2 个月,OpenAI 火速用 Rust 重写 AI 编程工具。尤雨溪也觉得 Rust 香!
  • 三十四、面向对象底层逻辑-SpringMVC九大组件之FlashMapManager接口设计哲学
  • C#学习第28天:内存缓存和对象池化
  • vscode使用系列之快速生成html模板
  • CANFD 数据记录仪在汽车售后解决偶发问题故障的应用
  • 浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
  • Python使用clickhouse-local和MySQL表函数实现从MySQL到ClickHouse数据同步
  • 全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
  • Spring Cloud 2025.0.0 Gateway迁移全过程详解
  • Unreal从入门到精通之 UE4 vs UE5 VR性能优化实战
  • 开源 vGPU 方案:HAMi,实现细粒度 GPU 切分
  • 华为云Flexus+DeepSeek征文|基于华为云Flexus X和DeepSeek-R1打造个人知识库问答系统
  • 学习笔记(25):线性代数,矩阵-矩阵乘法原理
  • NoSQL子Redis哨兵
  • Android Test3 获取的ANDROID_ID值不同
  • logstash拉取redisStream的流数据,并存储ES
  • uni-app 项目支持 vue 3.0 详解及版本升级方案?
  • LangChain【8】之工具包深度解析:从基础使用到高级实践
  • Vue3 + UniApp 蓝牙连接与数据发送(稳定版)
  • FFmpeg 低延迟同屏方案
  • LeetCode 热题 100 74. 搜索二维矩阵