0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

零知开源——ESP8266+MPU6050 实现运动姿态检测

PCB56242069 ? 来源:PCB56242069 ? 作者:PCB56242069 ? 2025-02-20 17:54 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

零知ESP8266I2C通信

在运动姿态检测、机器人平衡控制、VR头戴设备等应用中,MPU6050(三轴加速度计+三轴陀螺仪)是一个常见的姿态传感器。而ESP8266作为一款低功耗Wi-Fi模块,可以实现数据无线传输,将姿态数据上传至服务器或云端,便于实时监测。

然而,MPU6050没有磁力计,直接使用陀螺仪的角速度积分计算yaw角(航向角)会导致累积漂移。本次实验采用优化后的互补滤波,减少漂移,提高yaw角的计算精度。

一、硬件连接

MPU6050模块采用I2C通信连接到零知ESP8266开发板

1.所需材料:

零知ESP8266

MPU6050姿态检测传感器

跳线

2.硬件连接示意图:

零知ESP8266 MPU6050
3.3V VCC
GND GND
SCL SCL
SDA SDA

wKgZPGe2-82Ab_XGAALqhQI8gjQ094.png

二、代码实现

1.头文件及变量定义

通过MPU6050库与传感器交互

使用yaw_integral变量累积航向角
previousTime变量用于计算时间间隔dt

#include "MPU6050.h"

MPU6050 accelgyro;

int16_t ax, ay, az;
int16_t gx, gy, gz;

float nax, nay, naz;
float ngx, ngy, ngz;

float roll, pitch, yaw;
float yaw_integral = 0.0f;  // 累积 yaw 角
unsigned long previousTime = 0;  // 记录上一帧的时间

// 校准值
int16_t ax_offset = 0, ay_offset = 0, az_offset = 0;
int16_t gx_offset = 0, gy_offset = 0, gz_offset = 0;

#define LED_PIN LED_BUILTIN

2.初始化MPU6050

设置ESP8266I2C端口SDA、SCL
初始化MPU6050并进行连接测试
校准传感器,减少偏差
设置50Hz采样率和±2000°/s陀螺仪量程

void setup() {
    Serial.begin(9600);

    // MPU6050 初始化
    Serial.println("Initializing I2C devices...");
    accelgyro.initialize();

    // 检测 MPU6050 是否连接成功
    Serial.println("Testing device connections...");
    if (accelgyro.testConnection()) {
        Serial.println("MPU6050 connection successful");
    } else {
        Serial.println("MPU6050 connection failed");
    }

    // 传感器校准
    calibrateSensors();

    // 设置 MPU6050 的采样率和陀螺仪的量程
    accelgyro.setRate(50);  // 采样率 50Hz
    accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);  // 陀螺仪量程 ±2000°/s

    // LED 指示灯
    pinMode(LED_PIN, OUTPUT);

    // 记录起始时间
    previousTime = millis();
}

3.获取MPU6050数据

获取加速度计&陀螺仪原始数据
减去偏移量,提高数据精度
归一化数据,提高计算稳定性
调用complementaryFilter()计算姿态角
串口打印姿态角数据

void loop() {
    // 获取原始数据
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    // 减去偏移量
    ax -= ax_offset;
    ay -= ay_offset;
    az -= az_offset;
    gx -= gx_offset;
    gy -= gy_offset;
    gz -= gz_offset;

    // 读取归一化数据
    accelgyro.readNormalizeAccel(&nax, &nay, &naz);
    accelgyro.readNormalizeGyro(&ngx, &ngy, &ngz);

    // 计算姿态角
    complementaryFilter();

    // 打印姿态角
    Serial.print("Roll: ");
    Serial.print(roll);
    Serial.print(" Pitch: ");
    Serial.print(pitch);
    Serial.print(" Yaw: ");
    Serial.println(yaw);

    delay(10);
}

4.传感器校准

采集100组数据,计算平均值作为偏移量
过滤MPU6050启动时的零偏误差
减少环境噪声对传感器的影响

// 传感器校准
void calibrateSensors() {
    int num_readings = 100;
    for (int i = 0; i < num_readings; i++) {
        accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
        ax_offset += ax;
        ay_offset += ay;
        az_offset += az;
        gx_offset += gx;
        gy_offset += gy;
        gz_offset += gz;
        delay(50);
    }
    ax_offset /= num_readings;
    ay_offset /= num_readings;
    az_offset /= num_readings;
    gx_offset /= num_readings;
    gy_offset /= num_readings;
    gz_offset /= num_readings;
}

5.互补滤波计算姿态角

计算dt(时间间隔),用于陀螺仪积分计算yaw


roll和pitch采用加速度计计算:
yaw采用陀螺仪积分计算并限制范围[-180,180]
yaw=0.98*yaw_integral+0.02*yaw进行互补滤波,减少漂移

// 互补滤波计算姿态角
void complementaryFilter() {
    // 计算时间间隔 dt(单位:秒)
    unsigned long currentTime = millis();
    float dt = (currentTime - previousTime) / 1000.0;  // ms 转换为 s
    previousTime = currentTime;

    // 计算 Roll 和 Pitch
    roll = atan2(nay, naz) * 180 / M_PI;
    pitch = atan2(-nax, sqrt(nay * nay + naz * naz)) * 180 / M_PI;

    // 陀螺仪角速度转换
    float gyroYawRate = ngz;  // 直接使用归一化后的 ngz(角速度 deg/s)

    // 计算 Yaw (积分计算)
    yaw_integral += gyroYawRate * dt;  // 积分计算 yaw
    yaw_integral = fmod(yaw_integral + 180, 360) - 180;  // 限制 yaw 在 [-180, 180] 之间

    // 互补滤波减少漂移影响
    yaw = 0.98 * yaw_integral + 0.02 * yaw;  // 0.98 和 0.02 为滤波系数
}

6.完整代码

#include "MPU6050.h"

MPU6050 accelgyro;

int16_t ax, ay, az;
int16_t gx, gy, gz;

float nax, nay, naz;
float ngx, ngy, ngz;

float roll, pitch, yaw;
float yaw_integral = 0.0f;  // 累积 yaw 角
unsigned long previousTime = 0;  // 记录上一帧的时间

// 校准值
int16_t ax_offset = 0, ay_offset = 0, az_offset = 0;
int16_t gx_offset = 0, gy_offset = 0, gz_offset = 0;

#define LED_PIN LED_BUILTIN

void setup() {
    Serial.begin(9600);

    // MPU6050 初始化
    Serial.println("Initializing I2C devices...");
    accelgyro.initialize();

    // 检测 MPU6050 是否连接成功
    Serial.println("Testing device connections...");
    if (accelgyro.testConnection()) {
        Serial.println("MPU6050 connection successful");
    } else {
        Serial.println("MPU6050 connection failed");
    }

    // 传感器校准
    calibrateSensors();

    // 设置 MPU6050 的采样率和陀螺仪的量程
    accelgyro.setRate(50);  // 采样率 50Hz
    accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);  // 陀螺仪量程 ±2000°/s

    // LED 指示灯
    pinMode(LED_PIN, OUTPUT);

    // 记录起始时间
    previousTime = millis();
}

void loop() {
    // 获取原始数据
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    // 减去偏移量
    ax -= ax_offset;
    ay -= ay_offset;
    az -= az_offset;
    gx -= gx_offset;
    gy -= gy_offset;
    gz -= gz_offset;

    // 读取归一化数据
    accelgyro.readNormalizeAccel(&nax, &nay, &naz);
    accelgyro.readNormalizeGyro(&ngx, &ngy, &ngz);

    // 计算姿态角
    complementaryFilter();

    // 打印姿态角
    Serial.print("Roll: ");
    Serial.print(roll);
    Serial.print(" Pitch: ");
    Serial.print(pitch);
    Serial.print(" Yaw: ");
    Serial.println(yaw);

    delay(10);
}

// 传感器校准
void calibrateSensors() {
    int num_readings = 100;
    for (int i = 0; i < num_readings; i++) {
        accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
        ax_offset += ax;
        ay_offset += ay;
        az_offset += az;
        gx_offset += gx;
        gy_offset += gy;
        gz_offset += gz;
        delay(50);
    }
    ax_offset /= num_readings;
    ay_offset /= num_readings;
    az_offset /= num_readings;
    gx_offset /= num_readings;
    gy_offset /= num_readings;
    gz_offset /= num_readings;
}

// 互补滤波计算姿态角
void complementaryFilter() {
    // 计算时间间隔 dt(单位:秒)
    unsigned long currentTime = millis();
    float dt = (currentTime - previousTime) / 1000.0;  // ms 转换为 s
    previousTime = currentTime;

    // 计算 Roll 和 Pitch
    roll = atan2(nay, naz) * 180 / M_PI;
    pitch = atan2(-nax, sqrt(nay * nay + naz * naz)) * 180 / M_PI;

    // 陀螺仪角速度转换
    float gyroYawRate = ngz;  // 直接使用归一化后的 ngz(角速度 deg/s)

    // 计算 Yaw (积分计算)
    yaw_integral += gyroYawRate * dt;  // 积分计算 yaw
    yaw_integral = fmod(yaw_integral + 180, 360) - 180;  // 限制 yaw 在 [-180, 180] 之间

    // 互补滤波减少漂移影响
    yaw = 0.98 * yaw_integral + 0.02 * yaw;  // 0.98 和 0.02 为滤波系数
}
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

将上述代码移植到零知开源平台,选择连接的端口编译并上传到零知ESP8266。

wKgZPGe2-86AQdq3AAO33xrlU1k131.png

三、实验结果

点击零知开源平台调试按钮,打开零知开源平台的串口监视器,设置波特率为9600,观察串口打印测量到的MPU6050姿态角。

wKgZO2e2-86AdwmZAAAe41JPHjY603.png

使用vofa+上位机效果:

wKgZO2e2-8-AeO8SAAMYQoyweKk95.jpeg

VOFA+上位机获取MPU6050运动姿态

vofa+上位机获取姿态解算数据视频

https://www.bilibili.com/video/BV1HiAPe1Etj?share_source=copy_web

本人才疏学浅,有错误或遗漏的部分欢迎大家探讨学习!

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 检测
    +关注

    关注

    5

    文章

    4657

    浏览量

    93005
  • 开源
    +关注

    关注

    3

    文章

    3755

    浏览量

    43992
  • 姿态检测
    +关注

    关注

    0

    文章

    6

    浏览量

    7256
  • MPU6050
    +关注

    关注

    39

    文章

    310

    浏览量

    73282
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    开源——MPU6050六轴传感器模块实践教程,轻松实现运动检测

    观,便于进行后续的处理和分析。 通过本教程,您已经学会了如何使用增强板和MPU6050模块来读取运动数据。这些数据可以用于各种应用,如姿态
    发表于 02-20 15:53

    开源——ESP8266+MPU6050 实现运动姿态检测

    ?ESP8266学习教程 在运动姿态检测、机器人平衡控制、VR头戴设备等应用中,
    发表于 02-20 17:44

    开源——ESP8266结合ICM20948实现高精度姿态解算

    实验室发布新版ICM20948模块,可以非常方便的应用在各个系列开发板或其他类似MCU,它可以作为已经停产的MPU9250的替代品,
    发表于 03-07 15:46

    使用esp8266实现STM32联网(最简单USART方法)

    到电脑上的java程序 这一篇 esp8266与STM32连接,电脑通过STM32配置esp8266实现联网发送数据具体流程如下图 2= esp8266怎么和STM32连接(引脚连
    发表于 11-22 11:51 ?1.3w次阅读

    mpu6050姿态解算原理_mpu6050姿态解算程序

    mpu6050常用作提供飞控运行时的姿态测量和计算。本文首先介绍了MPU6050姿态解算的原理,其次详细的介绍了mpu6050
    的头像 发表于 03-09 09:15 ?4.4w次阅读

    Esp8266单机开源分享

    电子发烧友网站提供《Esp8266单机开源分享.zip》资料免费下载
    发表于 07-04 14:55 ?3次下载
    <b class='flag-5'>Esp8266</b>单机<b class='flag-5'>开源</b>分享

    ESP8266迷你系统开源分享

    电子发烧友网站提供《ESP8266迷你系统开源分享.zip》资料免费下载
    发表于 08-08 10:07 ?7次下载
    <b class='flag-5'>ESP8266</b>迷你系统<b class='flag-5'>开源</b>分享

    开发板ESP8266开源分享

    电子发烧友网站提供《开发板ESP8266开源分享.zip》资料免费下载
    发表于 08-10 14:49 ?17次下载
    开发板<b class='flag-5'>ESP8266</b><b class='flag-5'>开源</b>分享

    BIM时钟ESP8266开源项目

    电子发烧友网站提供《BIM时钟ESP8266开源项目.zip》资料免费下载
    发表于 08-16 11:18 ?2次下载
    BIM时钟<b class='flag-5'>ESP8266</b><b class='flag-5'>开源</b>项目

    使用MPU6050ESP8266和Qubitro进行ART分析

    电子发烧友网站提供《使用MPU6050ESP8266和Qubitro进行ART分析.zip》资料免费下载
    发表于 10-28 09:33 ?2次下载
    使用<b class='flag-5'>MPU6050</b>、<b class='flag-5'>ESP8266</b>和Qubitro进行ART分析

    ESP8266物联网开源分享

    电子发烧友网站提供《ESP8266物联网开源分享.zip》资料免费下载
    发表于 12-06 14:45 ?4次下载
    <b class='flag-5'>ESP8266</b>物联网<b class='flag-5'>开源</b>分享

    ESP8266无人机原理图+PCB合集

    现在作为廉价的配置就是ESP8266(树莓派Pico)+MPU6050+MOSx4(Si2302 )+LDO。然后原理图已经绘制完毕,接下来的问题就是PCB的布局,以及一些附件的添加。
    的头像 发表于 01-06 14:37 ?8096次阅读

    ESP8266编程盾开源

    电子发烧友网站提供《ESP8266编程盾开源.zip》资料免费下载
    发表于 02-02 14:25 ?1次下载
    <b class='flag-5'>ESP8266</b>编程盾<b class='flag-5'>开源</b>

    MPU6050运动跟踪设备开源分享

    电子发烧友网站提供《MPU6050运动跟踪设备开源分享.zip》资料免费下载
    发表于 06-29 14:57 ?8次下载
    <b class='flag-5'>MPU6050</b><b class='flag-5'>运动</b>跟踪设备<b class='flag-5'>开源</b>分享

    开源——MPU6050六轴传感器模块实践教程,轻松实现运动检测

    。 ? ? ? 通过本教程,您将学习如何读取并处理这些数据,为您的项目添加运动检测姿态控制功能。 一、硬件连接 ? ? ? ?在开始编程之前,首先需要正确连接MPU6050模块到
    的头像 发表于 02-20 16:17 ?1231次阅读
    <b class='flag-5'>零</b><b class='flag-5'>知</b><b class='flag-5'>开源</b>——<b class='flag-5'>MPU6050</b>六轴传感器模块实践教程,轻松<b class='flag-5'>实现</b><b class='flag-5'>运动检测</b>!