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

 零知ESP8266学习教程

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

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

目录

 零知ESP8266学习教程

一、硬件连接

1.所需材料:

2.硬件连接示意图:

二、代码实现 

 1.头文件及变量定义

 2.初始化MPU6050

 3.获取MPU6050数据

 4.传感器校准

 5.互补滤波计算姿态角

 6.完整代码

三、实验结果


一、硬件连接

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

1.所需材料:

零知ESP8266

MPU6050姿态检测传感器

跳线

2.硬件连接示意图:

零知ESP8266

MPU6050

3.3V

VCC

GND

GND

SCL

SCL

SDA

SDA

 

二、代码实现 

 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

设置ESP8266 I2C端口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 为滤波系数
}

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


三、实验结果

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

 

使用vofa+上位机效果:
 

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

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

 
🔗参考:https://pan.baidu.com/s/14-XlMNujF-XYY97R5u6MfA?pwd=c46m 提取码: c46mhttps://pan.baidu.com/s/14-XlMNujF-XYY97R5u6MfA?pwd=c46m

✅觉得有帮助的话,欢迎点赞、收藏!

<think>嗯,用户现在在找关于陀螺仪视频防抖的开源算法,特别是GitHub上的实现。首先,我需要理解用户的需求。他们可能已经尝试过一些基于视觉的防抖方法,比如OpenCV里的点特征匹配,但可能效果不够好,或者客户反馈不行,所以想结合陀螺仪数据来提升稳定性。 接下来,我得回忆一下相关的开源项目。之前用户提供的引用里提到了GitHub上的video_stabilization项目,但那是基于视觉的,用户可能需要的是结合陀螺仪传感器的数据。陀螺仪防抖通常利用设备记录的旋转和运动数据来补偿相机的抖动,这种方法在手机拍摄中比较常见。 首先,我应该检查是否有名的开源库或项目专门处理陀螺仪视频防抖。比如,Google的GyroStabilizer可能是一个选项,不过不确定是否开源。另外,GitHub上可能有社区开发的项目,比如Gyroflow,这个项目我记得是开源的,用陀螺仪数据进行视频稳定,支持多种相机型号,可能符合用户需求。 然后,需要考虑用户的技术背景。用户提到了Python和OpenCV,所以可能需要Python实现的库,但陀螺仪处理可能更多用C++或其它语言,不过接口可能有Python绑定。或者用户可能需要自己处理传感器数据,结合现有的视觉方法。 另外,用户提供的引用中有提到被客户反应效果不行,说明他们可能在实际应用中遇到了问题,需要更可靠的解决方案。陀螺仪数据可以提供更精确的运动信息,尤其是在快速运动或低光环境下,视觉方法可能失效的情况。 可能还需要考虑如何将陀螺仪数据与视频帧对齐,时间同步是个关键点。有些项目可能已经解决了这个问题,比如使用传感器的时间戳和视频帧的时间戳进行同步处理。 然后,我应该列出几个可能的GitHub项目,比如Gyroflow、video-stabilization-with-IMU-data,或者其它结合IMU的开源库。同时,提供一些实现思路,比如使用卡尔曼滤波或互补滤波来融合陀螺仪数据,或者利用OpenCV的Warper进行帧变换。 还需要注意用户是否希望有具体的代码示例,比如Python或C++,但问题中用户主要是在寻找开源实现,所以可能需要提供项目链接和简要说明。 最后,确保回答中提到的项目确实存在,并且是活跃维护的,避免推荐过时或不再维护的库。可能需要快速浏览GitHub确认项目状态,比如Star数、最近提交时间等,以增加推荐的可靠性。</think>关于陀螺仪视频防抖的开源算法,以下是相关资源和实现思路的整理: ### 开源项目推荐 1. **Gyroflow** GitHub地址:https://github.com/gyroflow/gyroflow - 基于陀螺仪数据实现视频防抖,支持GoPro、大疆等设备的传感器数据解析 - 使用卡尔曼滤波融合陀螺仪与视觉特征点数据 - 提供Python/C++混合实现和GUI界面 2. **OpenCV+IMU Stabilization** GitHub示例:https://github.com/ISHITADG/Video-Stabilization-using-IMU-Data - 结合手机陀螺仪(IMU)数据与OpenCV的特征点匹配 - 实现步骤: ```python # 伪代码示例:陀螺仪数据与视频帧对齐 def align_gyro_data(frame_timestamp, gyro_data): return interpolated_rotation ``` 3. **Google的MediaPipe防抖模块** 文档:https://google.github.io/mediapipe/solutions/stabilization.html - 整合传感器数据与计算机视觉 - 使用滑动窗口优化和运动滤波算法 ### 算法核心思路 1. **运动解耦** 通过陀螺仪数据分离相机旋转运动和平移运动,公式: $$R_{comp} = R_{gyro}^{-1} \cdot R_{optical}$$ 其中$R_{gyro}$为陀螺仪计算的旋转矩阵,$R_{optical}$为光流法估计的旋转[^2] 2. **时间同步** 需对齐陀螺仪采样时间戳与视频帧时间戳,常用线性插值法 3. **运动补偿** 使用仿射变换或透视变换矩阵进行帧校正: ```python warp_matrix = cv2.estimateAffine2D(prev_pts, curr_pts) stabilized_frame = cv2.warpAffine(frame, warp_matrix, (width, height)) ``` ### 注意事项 1. 需要原始视频包含陀螺仪元数据(如手机/运动相机的MP4文件) 2. 部分项目需自行实现传感器数据解析(如大疆的DAT文件) 3. 实际应用中建议结合视觉特征点验证防抖效果[^3] 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值