- MahonyQuaternionUpdate(
- myIMU.ay, // 加速度Y→X
- myIMU.ax, // 加速度X→Y
- -myIMU.az, // 加速度Z反转
- myIMU.gy * DEG_TO_RAD, // 陀螺Y→X
- myIMU.gx * DEG_TO_RAD, // 陀螺X→Y
- -myIMU.gz * DEG_TO_RAD,// 陀螺Z反转
- myIMU.mx,
- myIMU.my,
- myIMU.mz,
- myIMU.deltat
- );
2.欧拉角转换
- myIMU.yaw = atan2(2.0f * (*(getQ()+1) * *(getQ()+2) + *getQ()
- * *(getQ()+3)), *getQ() * *getQ() + *(getQ()+1)
- * *(getQ()+1) - *(getQ()+2) * *(getQ()+2) - *(getQ()+3)
- * *(getQ()+3));
- myIMU.pitch = -asin(2.0f * (*(getQ()+1) * *(getQ()+3) - *getQ()
- * *(getQ()+2)));
- myIMU.roll = atan2(2.0f * (*getQ() * *(getQ()+1) + *(getQ()+2)
- * *(getQ()+3)), *getQ() * *getQ() - *(getQ()+1)
- * *(getQ()+1) - *(getQ()+2) * *(getQ()+2) + *(getQ()+3)
- * *(getQ()+3));
- myIMU.pitch *= RAD_TO_DEG;
- myIMU.yaw *= RAD_TO_DEG;
- // Declination of SparkFun Electronics (40°05'26.6"N 105°11'05.9"W) is
- // 8° 30' E ± 0° 21' (or 8.5°) on 2016-07-19
- // - http://www.ngdc.noaa.gov/geomag-web/#declination
- myIMU.yaw -= 8.5;
- myIMU.roll *= RAD_TO_DEG;
3.5数据输出
串口协议设计
- //打印格式与processing端格式一致
- Serial.print("Or: ");
- Serial.print(myIMU.yaw, 2);
- Serial.print(" ");
-
- Serial.print(myIMU.pitch, 2);
- Serial.print(" ");
- Serial.print(myIMU.roll, 2);
- Serial.println(" ");
3.6Processing 3D可视化验证
将代码库文件安装包解压到C:\Users\Administrator\Documents\Processing\libraries,然后在Processing中选择开发板对应的串口号,就可以看到我们的3D模型根据九轴的姿态进行变化啦:
- import processing.serial.*;
- // 传感器数据float roll, pitch, yaw;
- PVector accelerometer = new PVector();
- PVector gyroscope = new PVector();
- PVector magneticField = new PVector();
- // 3D模型
- PShape model;
- PImage bgImage;
- // 串口配置
- Serial port;
- String[] serialPorts;int selectedPort = 0;
- boolean printSerial = false;
- void setup() {
- size(1024, 800, P3D);
- frameRate(60);
-
- // 加载资源
- bgImage = loadImage("background.png");
- model = loadShape("biplane.obj"); // 确保使用标准OBJ格式
- model.scale(30);
-
- // 初始化串口
- serialPorts = Serial.list();
- if(serialPorts.length > 0) connectSerial(serialPorts[0]);
- }
- void draw() {
- background(bgImage);
-
- // 3D场景设置
- pushMatrix();
- translate(width/2, height/2, 0);
- lights();
-
- // 应用旋转
- rotateX(radians(pitch));
- rotateY(radians(yaw));
- rotateZ(radians(roll));
-
- // 绘制模型
- shape(model);
- popMatrix();
-
- // 显示数据
- displaySensorData();
- }
- void serialEvent(Serial p) {
- try {
- String rawData = p.readStringUntil('\n').trim();
- if(printSerial) println(rawData);
-
- String[] parts = split(rawData, ' ');
- if(parts.length >= 4) {
- switch(parts[0]) {
- case "Or:": // 欧拉角格式:Or: yaw pitch roll
- yaw = float(parts[1]);
- pitch = float(parts[2]);
- roll = float(parts[3]);
- break;
- case "Accel:":
- accelerometer.set(float(parts[1]), float(parts[2]), float(parts[3]));
- break;
- case "Gyro:":
- gyroscope.set(float(parts[1]), float(parts[2]), float(parts[3]));
- break;
- case "Mag:":
- magneticField.set(float(parts[1]), float(parts[2]), float(parts[3]));
- break;
- }
- }
- } catch(Exception e) {
- println("Serial Error: " + e.getMessage());
- }
- }
- void displaySensorData() {
- fill(0, 255, 0);
- textSize(16);
- textAlign(LEFT, TOP);
- String data = "Accelerometer(g): "
- + nfp(accelerometer.x,1,2) + ", "
- + nfp(accelerometer.y,1,2) + ", "
- + nfp(accelerometer.z,1,2) + "\n"
- + "Gyroscope(deg/s): "
- + nfp(gyroscope.x,1,2) + ", "
- + nfp(gyroscope.y,1,2) + ", "
- + nfp(gyroscope.z,1,2) + "\n"
- + "Orientation: \n"
- + "Yaw: " + nfp(yaw,1,1) + "°\n"
- + "Pitch: " + nfp(pitch,1,1) + "°\n"
- + "Roll: " + nfp(roll,1,1) + "°";
- text(data, 20, 20);
- }
- void connectSerial(String portName) {
- if(port != null) port.stop();
- try {
- port = new Serial(this, portName, 115200);
- port.bufferUntil('\n');
- println("Connected to: " + portName);
- } catch(Exception e) {
- println("Connection failed: " + e.getMessage());
- }
- }
- void keyPressed() {
- // 切换串口
- if(key == ' ') {
- selectedPort = (selectedPort + 1) % serialPorts.length;
- connectSerial(serialPorts[selectedPort]);
- }
- // 切换调试输出
- if(key == 'P' || key == 'p') printSerial = !printSerial;
- // 重置视角
- if(key == 'R' || key == 'r') {
- yaw = pitch = roll = 0;
- }
- }
四、实现结果分析
观察串口打印输出的DMP姿态解算数据如下:
Processing 3D可视化验证:
Processing 3D可视化验证
五、项目资源汇总
5.1 参考资料
ICM20948数据手册
ESP8266技术参考
5.2 源码获取
https://github.com/Leeri1y/ICM20948-ESP8266 参考Github仓库
64位Windows系统的Processing安装包:
通过网盘分享的文件:processing-4.3.3.7z链接: https://pan.baidu.com/s/12B4F33M1caRncVjSJiFPTg?pwd=9h5i 提取码: 9h5i
5.3 扩展学习
Mahony滤波器数学推导
欢迎各位道友相互讨论,一直在学习的路上!