目录

  • 源码
    • Madgwick_6.c
    • Madgwick_6.h
  • 使用方法
  • 测试程序
    • main.c
    • 效果

STC89C516 32MHz
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0
上位机:Vofa+ 1.3.10


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

源码

为了避免所用RAM超标,部分变量设为idata类型,移植时需注意。
       所用MCU为STC89C516 晶振16MHz 6T模式

stdint.h见【51单片机快速入门指南】1:基础知识和工程创建
       软件I2C程序见【51单片机快速入门指南】4: 软件 I2C
       串口部分见【51单片机快速入门指南】3.3:USART 串口通信
       MPU6050.c、MPU6050.h见【51单片机快速入门指南】4.3: I2C读取MPU6050陀螺仪的原始数据

beta要按需调整,我这里取0.1

Madgwick_6.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  0.1f                                        // 2 * proportional gain (Kp)//---------------------------------------------------------------------------------------------------
// Variable definitionsidata volatile float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // quaternion of sensor frame relative to auxiliary frame
idata volatile float Pitch = 0.0f, Roll = 0.0f, Yaw = 0.0f;//====================================================================================================
// Functionsidata float sampleFreq = 1;
idata 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;
}//====================================================================================================
// END OF CODE
//====================================================================================================

Madgwick_6.h

#ifndef Madgwick_6_H_
#define Madgwick_6_H_extern idata float Pitch, Roll, Yaw;
extern idata 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);#endif

使用方法

先调用MPU6050_Madgwick_Init(dt),参数为一次循环的时间,单位为ms
再使用MadgwickAHRSupdate_6姿态融合函数。

测试程序

main.c

#include <STC89C5xRC.H>
#include "intrins.h"
#include "stdint.h"
#include "USART.h"
#include "./MPU6050/MPU6050.h"
#include "./MPU6050/Madgwick_6.h"void Delay1ms()      //@32MHz
{unsigned char i, j;i = 6;j = 44;do{while (--j);} while (--i);
}void Delay_ms(int i)
{while(i--)Delay1ms();
}void main(void)
{idata int16_t aacx,aacy,aacz;      //加速度传感器原始数据idata int16_t gyrox,gyroy,gyroz;    //陀螺仪原始数据USART_Init(USART_MODE_1, Rx_ENABLE, STC_USART_Priority_Lowest, 32000000, 4800, DOUBLE_BAUD_DISABLE, USART_TIMER_2);MPU_Init(); MPU6050_Madgwick_Init(95);while(1){ MPU_Get_Accelerometer(&aacx, &aacy, &aacz); //得到加速度传感器数据MPU_Get_Gyroscope(&gyrox, &gyroy, &gyroz);  //得到陀螺仪数据MadgwickAHRSupdate_6(gyrox, gyroy, gyroz, aacx, aacy, aacz);printf("%f, ", Pitch);printf("%f, ", Roll);printf("%f\r\n", Yaw);}
}

效果

【51单片机快速入门指南】4.3.4: MPU6050使用Madgwick AHRS算法实现六轴姿态融合获取四元数、欧拉角相关推荐

  1. 【51单片机快速入门指南】4.3.3: MPU6050使用Mahony AHRS算法实现六轴姿态融合获取四元数、欧拉角

    目录 源码 Mahony_6.c Mahony_6.h 使用方法 测试程序 main.c 效果 STC89C516 32MHz Keil uVision V5.29.0.0 PK51 Prof.Dev ...

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

    目录 传感器的方向 源码 Madgwick_9.c Madgwick_9.h 使用方法 测试 main.c 效果 STC15F2K60S2 22.1184MHz Keil uVision V5.29. ...

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

    目录 传感器的方向 源码 Mahony_9.c Mahony_9.h 使用方法 测试 main.c 效果 STC15F2K60S2 22.1184MHz Keil uVision V5.29.0.0 ...

  4. 【51单片机快速入门指南】6.4:DHT11、DHT22单总线温湿度传感器

    目录 硬知识 DHT11 DHT22 通信协议 读取步骤 数据解读 DHT11 DHT22 示例程序 DHT11_22.c DHT11_22.h 测试程序 main.c 实验现象 DHT11 DHT2 ...

  5. 【51单片机快速入门指南】4.6:I2C 与 PCF8563实时时钟日历芯片

    目录 硬知识 概述 特性 功能描述 报警功能模式 定时器模式 CLKOUT输出 复位低电压检测器和时钟监视器 低电压检测器和时钟监视器 寄存器结构 寄存器概述 BCD编码格式寄存器概述 Control ...

  6. 【51单片机快速入门指南】6.3:DS18B20 单总线数字温度计的多路读取

    目录 硬知识 DS18B20介绍 时序 初始化时序 写时序 读时序 命令 ROM 操作命令 ROM 搜索举例 存贮器操作命令 示例程序 DS18B20.c DS18B20.h 测试程序 定时器中断服务 ...

  7. 【51单片机快速入门指南】6.1:LCD1602的八线、四线控制及自定义符号,完美兼容Proteus仿真

    目录 硬知识 显示特性 接口定义 操作时序 写操作时序 读操作时序 寄存器 忙标志位BF 地址计数器(AC) 显示数据寄存器(DDRAM) CGROM CGRAM 指令 清屏指令 光标归位指令 进入模 ...

  8. 【51单片机快速入门指南】5.3:SPI控制晶联讯JLX12864G_08602 LCD屏幕

    目录 示例程序 JLX12864G_08602.c JLX12864G_08602.h JLX12864G_08602_Font.c JLX12864G_08602_Font.h 测试程序 main. ...

  9. 【51单片机快速入门指南】5.1:SPI与DS1302时钟芯片

    目录 硬知识 DS1302 简介 DS1302 使用 控制寄存器 日历/时钟寄存器 DS1302 的读写时序 电路设计 示例程序 DS1302.c DS1302.h 测试程序 main.c 实验现象 ...

最新文章

  1. Java 7代码层面上的更新
  2. python中字母大小写的转换,和一些字典的常规操作
  3. css background-position
  4. 阿里云天池 金融风控训练营Task1 广东工业站
  5. 【转】.NET试题总结二
  6. Java中Properties类的学习总结
  7. OPPO Reno6系列将推Bobbi Brown联名版
  8. firefox浏览器优化-速度超chrome
  9. 家居海报PSD模板,是否也是你理想的生活!
  10. vant表单点击提交没有触发验证_jquery.validate不用submit提交,用js提交的,怎么触发验证啊?...
  11. java json 修改字段_我们如何使用Java中的Jackson来更改JSON中的字段名称?
  12. ffmpeg系列-解复用流程解析
  13. Java微信表情包字符处理,数据库存储以及转义解决方式
  14. 昨晚,谷歌发布了一个可怕的人工智能!
  15. 赛诺菲巴斯德宣布建立专属mRNA疫苗卓越中心;​葛兰素史克单片双药艾滋病治疗药物多伟托在中国上市 | 医药健闻...
  16. 《Linux那些事儿之我是USB》我是U盘(7)狂欢是一群人的孤单
  17. JDK1.6“新“特性Instrumentation之JavaAgent
  18. Psins代码解析之线性误差模型精度验证(test_SINS_error_model_verify.m)
  19. 20220319编译OpenHarmony-v3.1-beta出错的解决方法
  20. 前端 · 深入理解 transform 函数的计算原理 ②

热门文章

  1. 爬山算法和模拟退火算法简介(转)
  2. ×××S 2012 交互式报表 -- 同步交互式排序
  3. Android 短信解析
  4. Java开发环境搭建详解
  5. 在Java中,如何使一个字符串的首字母变为大写
  6. 自学成才翁_仅因为您是自学成才,并不意味着您必须独自学习。
  7. ml dl el学习_DeepChem —在生命科学和化学信息学中使用ML和DL的框架
  8. 量子相干与量子纠缠_量子分类
  9. [BZOJ3203][SDOI2013]保护出题人(凸包+三分)
  10. Could not find a package,configuration file provided by G2O ,G2OConfig.cmake,g2o-config.cmake