日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【51单片机快速入门指南】4.4.3:Madgwick AHRS 九轴姿态融合获取四元数、欧拉角

發布時間:2023/12/9 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【51单片机快速入门指南】4.4.3:Madgwick AHRS 九轴姿态融合获取四元数、欧拉角 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 傳感器的方向
  • 源碼
    • Madgwick_9.c
    • Madgwick_9.h
  • 使用方法
  • 測試
    • main.c
    • 效果

STC15F2K60S2 22.1184MHz
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0
上位機:Vofa+ 1.3.10


移植自AHRS —— LOXO,算法作者:SOH Madgwick

傳感器的方向

源碼

???????所用MCU為STC15F2K60S2 使用內部RC時鐘,22.1184MHz

???????stdint.h見【51單片機快速入門指南】1:基礎知識和工程創建
???????軟件I2C程序見【51單片機快速入門指南】4: 軟件 I2C
???????串口部分見【51單片機快速入門指南】3.3:USART 串口通信
???????MPU6050驅動程序見【51單片機快速入門指南】4.3: I2C讀取MPU6050陀螺儀的原始數據
???????HMC5883L/QMC5883L驅動程序見【51單片機快速入門指南】4.4:I2C 讀取HMC5883L / QMC5883L 磁力計
???????磁力計的橢球擬合校準見【51單片機快速入門指南】4.4.1:python串口接收磁力計數據并進行最小二乘法橢球擬合

???????beta要按需調整,我這里取1.0

Madgwick_9.c

//===================================================================================================== // // Implementation of Madgwick's IMU and AHRS algorithms. // See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms // // Date Author Notes // 29/09/2011 SOH Madgwick Initial release // 02/10/2011 SOH Madgwick Optimised for reduced CPU load // 19/02/2012 SOH Madgwick Magnetometer measurement is normalised // //=====================================================================================================//--------------------------------------------------------------------------------------------------- // Header files #include <math.h> #include "MPU6050.h"//--------------------------------------------------------------------------------------------------- // Definitions#define beta 1.0f // 2 * proportional gain (Kp)//--------------------------------------------------------------------------------------------------- // Variable definitionsfloat q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // quaternion of sensor frame relative to auxiliary frame float Pitch = 0.0f, Roll = 0.0f, Yaw = 0.0f;//==================================================================================================== // Functionsfloat sampleFreq = 1; float GYRO_K = 1;void MPU6050_Madgwick_Init(float loop_ms) {sampleFreq = 1000. / loop_ms; //sample frequency in Hzswitch((MPU_Read_Byte(MPU_GYRO_CFG_REG) >> 3) & 3){case 0:GYRO_K = 1./131/57.3;break;case 1:GYRO_K = 1./65.5/57.3;break;case 2:GYRO_K = 1./32.8/57.3;break;case 3:GYRO_K = 1./16.4/57.3;break;} }//--------------------------------------------------------------------------------------------------- // Fast inverse square-root // See: http://en.wikipedia.org/wiki/Fast_inverse_square_rootfloat invSqrt(float x) {float halfx = 0.5f * x;float y = x;long i = *(long*)&y;i = 0x5f3759df - (i>>1);y = *(float*)&i;y = y * (1.5f - (halfx * y * y));return y; }//--------------------------------------------------------------------------------------------------- // AHRS algorithm update //--------------------------------------------------------------------------------------------------- // IMU algorithm updatevoid MadgwickAHRSupdate_6(float gx, float gy, float gz, float ax, float ay, float az) {float recipNorm;float s0, s1, s2, s3;float qDot1, qDot2, qDot3, qDot4;float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2 ,_8q1, _8q2, q0q0, q1q1, q2q2, q3q3;//將陀螺儀AD值轉換為 弧度/sgx = gx * GYRO_K;gy = gy * GYRO_K;gz = gz * GYRO_K;// Rate of change of quaternion from gyroscopeqDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz);qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy);qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx);qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx);// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {// Normalise accelerometer measurementrecipNorm = invSqrt(ax * ax + ay * ay + az * az);ax *= recipNorm;ay *= recipNorm;az *= recipNorm; // Auxiliary variables to avoid repeated arithmetic_2q0 = 2.0f * q0;_2q1 = 2.0f * q1;_2q2 = 2.0f * q2;_2q3 = 2.0f * q3;_4q0 = 4.0f * q0;_4q1 = 4.0f * q1;_4q2 = 4.0f * q2;_8q1 = 8.0f * q1;_8q2 = 8.0f * q2;q0q0 = q0 * q0;q1q1 = q1 * q1;q2q2 = q2 * q2;q3q3 = q3 * q3;// Gradient decent algorithm corrective steps0 = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay;s1 = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q1 - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az;s2 = 4.0f * q0q0 * q2 + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az;s3 = 4.0f * q1q1 * q3 - _2q1 * ax + 4.0f * q2q2 * q3 - _2q2 * ay;recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitudes0 *= recipNorm;s1 *= recipNorm;s2 *= recipNorm;s3 *= recipNorm;// Apply feedback stepqDot1 -= beta * s0;qDot2 -= beta * s1;qDot3 -= beta * s2;qDot4 -= beta * s3;}// Integrate rate of change of quaternion to yield quaternionq0 += qDot1 * (1.0f / sampleFreq);q1 += qDot2 * (1.0f / sampleFreq);q2 += qDot3 * (1.0f / sampleFreq);q3 += qDot4 * (1.0f / sampleFreq);// Normalise quaternionrecipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);q0 *= recipNorm;q1 *= recipNorm;q2 *= recipNorm;q3 *= recipNorm;Pitch = asin(-2.0f * (q1*q3 - q0*q2))* 57.3f;Roll = atan2(q0*q1 + q2*q3, 0.5f - q1*q1 - q2*q2) * 57.3f;Yaw = atan2(q1*q2 + q0*q3, 0.5f - q2*q2 - q3*q3)* 57.3f; }void MadgwickAHRSupdate_9(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {float recipNorm;float s0, s1, s2, s3;float qDot1, qDot2, qDot3, qDot4;float hx, hy;float _2q0mx, _2q0my, _2q0mz, _2q1mx, _2bx, _2bz, _4bx, _4bz, _2q0, _2q1, _2q2, _2q3, _2q0q2, _2q2q3, q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation)if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {MadgwickAHRSupdate_6(gx, gy, gz, ax, ay, az);return;}//將陀螺儀AD值轉換為 弧度/sgx = gx * GYRO_K;gy = gy * GYRO_K;gz = gz * GYRO_K;// Rate of change of quaternion from gyroscopeqDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz);qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy);qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx);qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx);// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {// Normalise accelerometer measurementrecipNorm = invSqrt(ax * ax + ay * ay + az * az);ax *= recipNorm;ay *= recipNorm;az *= recipNorm; // Normalise magnetometer measurementrecipNorm = invSqrt(mx * mx + my * my + mz * mz);mx *= recipNorm;my *= recipNorm;mz *= recipNorm;// Auxiliary variables to avoid repeated arithmetic_2q0mx = 2.0f * q0 * mx;_2q0my = 2.0f * q0 * my;_2q0mz = 2.0f * q0 * mz;_2q1mx = 2.0f * q1 * mx;_2q0 = 2.0f * q0;_2q1 = 2.0f * q1;_2q2 = 2.0f * q2;_2q3 = 2.0f * q3;_2q0q2 = 2.0f * q0 * q2;_2q2q3 = 2.0f * q2 * q3;q0q0 = q0 * q0;q0q1 = q0 * q1;q0q2 = q0 * q2;q0q3 = q0 * q3;q1q1 = q1 * q1;q1q2 = q1 * q2;q1q3 = q1 * q3;q2q2 = q2 * q2;q2q3 = q2 * q3;q3q3 = q3 * q3;// Reference direction of Earth's magnetic fieldhx = mx * q0q0 - _2q0my * q3 + _2q0mz * q2 + mx * q1q1 + _2q1 * my * q2 + _2q1 * mz * q3 - mx * q2q2 - mx * q3q3;hy = _2q0mx * q3 + my * q0q0 - _2q0mz * q1 + _2q1mx * q2 - my * q1q1 + my * q2q2 + _2q2 * mz * q3 - my * q3q3;_2bx = sqrt(hx * hx + hy * hy);_2bz = -_2q0mx * q2 + _2q0my * q1 + mz * q0q0 + _2q1mx * q3 - mz * q1q1 + _2q2 * my * q3 - mz * q2q2 + mz * q3q3;_4bx = 2.0f * _2bx;_4bz = 2.0f * _2bz;// Gradient decent algorithm corrective steps0 = -_2q2 * (2.0f * q1q3 - _2q0q2 - ax) + _2q1 * (2.0f * q0q1 + _2q2q3 - ay) - _2bz * q2 * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q3 + _2bz * q1) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q2 * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);s1 = _2q3 * (2.0f * q1q3 - _2q0q2 - ax) + _2q0 * (2.0f * q0q1 + _2q2q3 - ay) - 4.0f * q1 * (1 - 2.0f * q1q1 - 2.0f * q2q2 - az) + _2bz * q3 * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q2 + _2bz * q0) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q3 - _4bz * q1) * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);s2 = -_2q0 * (2.0f * q1q3 - _2q0q2 - ax) + _2q3 * (2.0f * q0q1 + _2q2q3 - ay) - 4.0f * q2 * (1 - 2.0f * q1q1 - 2.0f * q2q2 - az) + (-_4bx * q2 - _2bz * q0) * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q1 + _2bz * q3) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q0 - _4bz * q2) * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);s3 = _2q1 * (2.0f * q1q3 - _2q0q2 - ax) + _2q2 * (2.0f * q0q1 + _2q2q3 - ay) + (-_4bx * q3 + _2bz * q1) * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q0 + _2bz * q2) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q1 * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitudes0 *= recipNorm;s1 *= recipNorm;s2 *= recipNorm;s3 *= recipNorm;// Apply feedback stepqDot1 -= beta * s0;qDot2 -= beta * s1;qDot3 -= beta * s2;qDot4 -= beta * s3;}// Integrate rate of change of quaternion to yield quaternionq0 += qDot1 * (1.0f / sampleFreq);q1 += qDot2 * (1.0f / sampleFreq);q2 += qDot3 * (1.0f / sampleFreq);q3 += qDot4 * (1.0f / sampleFreq);// Normalise quaternionrecipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);q0 *= recipNorm;q1 *= recipNorm;q2 *= recipNorm;q3 *= recipNorm;Pitch = asin(-2.0f * (q1*q3 - q0*q2))* 57.3f;Roll = atan2(q0*q1 + q2*q3, 0.5f - q1*q1 - q2*q2) * 57.3f;Yaw = atan2(q1*q2 + q0*q3, 0.5f - q2*q2 - q3*q3)* 57.3f; }//==================================================================================================== // END OF CODE //====================================================================================================

Madgwick_9.h

#ifndef Madgwick_9_H_ #define Madgwick_9_H_extern float Pitch, Roll, Yaw; extern float q0, q1, q2, q3;void MPU6050_Madgwick_Init(float loop_ms); void MadgwickAHRSupdate_6(float gx, float gy, float gz, float ax, float ay, float az); void MadgwickAHRSupdate_9(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);#endif

使用方法

先調用MPU6050_Madgwick_Init(dt),參數為一次循環的時間,單位為ms
再使用MadgwickAHRSupdate_9姿態融合函數。

測試

陀螺儀、磁力計的原始數據經校準后輸入MadgwickAHRSupdate_9函數

main.c

#include <STC15F2K60S2.H> #include "intrins.h" #include "stdint.h" #include "USART.h" #include "./Software_I2C/Software_I2C.h" #include "XMC5883L.h" #include "./MPU6050/MPU6050.h" #include "./MPU6050/Madgwick_9.h"void Delay1ms() //@22.1184MHz {unsigned char i, j;_nop_();_nop_();i = 22;j = 128;do{while (--j);} while (--i); }void delay_ms(uint32_t ms) {while(ms --)Delay1ms(); }#define LED_PORT P0void main(void) {int16_t mag_x, mag_y, mag_z;int16_t aacx,aacy,aacz; //加速度傳感器原始數據int16_t gyrox,gyroy,gyroz; //陀螺儀原始數據MPU_Init();xmc5883lInit();AUXR &= 0xBF; //定時器時鐘12T模式 1T的51使用12T的定時器程序時需要加入這兩句AUXR &= 0xFE; //串口1選擇定時器1為波特率發生器USART_Init(USART_MODE_1, Rx_ENABLE, STC_USART_Priority_Lowest, 22118400, 115200, DOUBLE_BAUD_ENABLE, USART_TIMER_1);MPU6050_Madgwick_Init(10.48);while(1){MPU_Get_Accelerometer(&aacx, &aacy, &aacz); //得到加速度傳感器數據MPU_Get_Gyroscope(&gyrox, &gyroy, &gyroz); //得到陀螺儀數據xmc5883lRead(&mag_x, &mag_y, &mag_z);MadgwickAHRSupdate_9(gyrox+7, gyroy+23, gyroz-1, aacx, aacy, aacz, 1.108270606866881 * (mag_x + 297.2882033958856), 0.9218994400020794 * (mag_y + 3088.0092054124193), 0.9871899380641738 * (mag_z + 782.925290575134));printf("%f, ", Pitch);printf("%f, ", Roll);printf("%f\r\n", Yaw);} }

效果

總結

以上是生活随笔為你收集整理的【51单片机快速入门指南】4.4.3:Madgwick AHRS 九轴姿态融合获取四元数、欧拉角的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。