基于MPU6050与三环控制的平衡小车实战详解

本文详细解析了如何利用MPU6050进行精准姿态采集,结合快速卡尔曼滤波算法和直流无刷电机的三环控制技术,从零构建一套高性能的自平衡控制系统。


一、平衡小车核心原理:倒立摆的稳定艺术

平衡小车的本质是一个移动的倒立摆系统。其核心控制目标是通过实时检测车身倾角(俯仰角 θ 和角速度 ω),计算出合适的电机控制量,驱动车轮产生加速度,抵消重力矩,使小车在竖直位置保持动态平衡。

核心物理模型:

  I * α = m * g * h * sin(θ) - F * d
  • I:小车绕轮轴的转动惯量

  • α:角加速度 (dω/dt)

  • m:小车质量

  • g:重力加速度 (9.8 m/s²)

  • h:重心高度

  • θ:车身偏离垂直方向的角度

  • F:电机作用在轮子上的水平力

  • d:轮子半径

控制目标:θ 增大时,电机需产生一个足够大的力 F,使角加速度 α 为负值(即减小 θ),将小车“拉”回平衡位置。


二、硬件系统架构与关键器件选型

平衡小车硬件系统由感知、决策、执行、供能四大模块构成。

1. 核心硬件模块功能表
模块核心组件关键功能典型选型
感知模块姿态传感器 (IMU)实时测量小车三维姿态角 (俯仰/横滚/偏航) 和角速度/加速度MPU6050 (集成陀螺仪+加速度计)
电机位置/速度传感器反馈电机转子位置、转速信息 (用于闭环控制)霍尔传感器 / 编码器
决策模块主控制器 (MCU)运行姿态解算、滤波算法、控制算法,生成电机驱动信号STM32F4xx (Cortex-M4, FPU)
执行模块直流无刷电机 (BLDC)将电信号转换为精确的转矩和转速输出Nidec 24V 3000RPM
电机驱动器将MCU的弱电控制信号转换为驱动电机的强电功率信号DRV8305 + MOSFET三相桥
供能模块电池为整个系统提供能量18650锂电池组 (7.4V/11.1V)
电压转换模块将电池电压转换为系统各部件所需的工作电压 (如5V, 3.3V)DC-DC降压模块
2. MPU6050 传感器关键特性
参数规格说明
陀螺仪量程±250, ±500, ±1000, ±2000°/s测量角速度范围,平衡车常用±500°/s
加速度计量程±2g, ±4g, ±8g, ±16g测量加速度范围,平衡车常用±4g
通信接口I²C (标准模式 100kHz)与MCU通信的主要方式
数字输出接口16-bit ADC提供高精度原始数据
集成功能DMP (可选)内置运动处理器,可分担部分姿态解算任务
工作电压3.3V需电平匹配或LDO供电

三、软件系统架构与工程流程

采用分层、模块化的软件设计思想,确保系统实时性、可靠性和可维护性。

1. 软件架构层次图 (UML组件图)
+-----------------------+
|     **应用层**        |
| (平衡控制策略)        |
+-----------------------+
           |
           v
+-----------------------+
|    **算法层**         |
| - 快速卡尔曼滤波      |
| - PID控制器(三环)     |
| - 姿态解算(互补滤波)  |
+-----------------------+
           |
           v
+-----------------------+
|    **驱动层**         |
| - MPU6050传感器驱动   |
| - BLDC电机驱动(FOC)   |
| - 编码器/霍尔驱动     |
| - 定时器/PWM配置      |
| - ADC配置(电流采样)   |
+-----------------------+
           |
           v
+-----------------------+
|    **硬件抽象层**     |
| (HAL库 / 寄存器操作)  |
+-----------------------+
           |
           v
+-----------------------+
|    **MCU硬件层**      |
| (STM32F4xx 外设)      |
+-----------------------+
2. 系统主程序流程图


四、姿态解算核心:快速卡尔曼滤波算法详解

MPU6050提供的是噪声污染的原始数据,需融合陀螺仪动态特性和加速度计静态特性,通过卡尔曼滤波得到高精度姿态角。

1. 卡尔曼滤波五大核心方程

2. 应用于姿态估计的快速实现

针对嵌入式系统资源限制,采用一维简化模型(仅考虑俯仰角θ),大幅降低计算量:

  • 状态变量: x = [θ, gyro_bias]^T(角度 + 陀螺仪零偏)

  • 状态转移矩阵 A:

    text

  • A = [[1, -Δt],
         [0,  1]]
  • 控制输入 B: u = gyro_raw (原始角速度读数)

  • 观测矩阵 H: H = [1, 0] (仅观测角度)

  • 过程噪声协方差 Q: 建模系统动态不确定性

  • 测量噪声协方差 R: 加速度计测量噪声方差

3. C语言实现代码片段

c

// 定义卡尔曼滤波器结构体
typedef struct {
    float angle;        // 最优估计角度 (rad)
    float bias;         // 陀螺仪零偏估计 (rad/s)
    float P[2][2];     // 协方差矩阵
    float Q_angle;     // 过程噪声 - 角度
    float Q_bias;      // 过程噪声 - 零偏
    float R_measure;   // 测量噪声 (加速度计)
} KalmanFilter;

// 卡尔曼滤波更新函数
float kalmanUpdate(KalmanFilter *kf, float accel_angle, float gyro_rate, float dt) {
    // 1. 预测步骤
    kf->angle += dt * (gyro_rate - kf->bias);
    kf->P[0][0] += dt * (dt * kf->P[1][1] - kf->P[0][1] - kf->P[1][0] + kf->Q_angle);
    kf->P[0][1] -= dt * kf->P[1][1];
    kf->P[1][0] -= dt * kf->P[1][1];
    kf->P[1][1] += kf->Q_bias * dt;

    // 2. 计算卡尔曼增益
    float S = kf->P[0][0] + kf->R_measure;
    float K[2] = {kf->P[0][0] / S, kf->P[1][0] / S}; // Kalman Gain

    // 3. 更新状态估计
    float y = accel_angle - kf->angle; // 测量残差
    kf->angle += K[0] * y;
    kf->bias  += K[1] * y;

    // 4. 更新协方差矩阵
    float P00_temp = kf->P[0][0];
    float P01_temp = kf->P[0][1];
    kf->P[0][0] -= K[0] * P00_temp;
    kf->P[0][1] -= K[0] * P01_temp;
    kf->P[1][0] -= K[1] * P00_temp;
    kf->P[1][1] -= K[1] * P01_temp;

    return kf->angle; // 返回最优估计角度
}

五、直流无刷电机(BLDC)三环控制详解

为实现高精度、快速响应的电机控制,采用位置-速度-电流三闭环控制结构。

1. 三环控制系统结构图

plaintext

+-------------+      +-------------+      +-------------+      +-------------+
|  位置环PID  | ---> |  速度环PID  | ---> |  电流环PID  | ---> |    FOC      |
| (外环)      |      | (中环)      |      | (内环)      |      | 算法 & PWM  |
+-------------+      +-------------+      +-------------+      +-------------+
      ^                    ^                    ^                    |
      |                    |                    |                    |
+-----+-----+        +-----+-----+        +-----+-----+        +-----+-----+
| 编码器    |        | 速度估计  |        | 相电流    |        |   BLDC     |
| 位置反馈  |        | (M法/T法) |        | 采样反馈  |        |   电机     |
+-----------+        +-----------+        +-----------+        +-----------+
2. 各控制环功能与参数整定
控制环输入量输出量核心功能关键参数整定
电流环Iq_ref (期望电流)Vq (q轴电压)控制电机转矩,响应最快KP_curr: 快速响应电流变化
KI_curr: 消除静差
速度环ω_ref (期望转速)Iq_ref (q轴电流)稳定电机转速,抑制负载扰动KP_speed: 决定动态响应速度
KI_speed: 消除转速静差
位置环θ_ref (目标位置)ω_ref (期望转速)精确控制电机转动角度KP_pos: 影响定位刚度
KD_pos: 抑制超调
3. 三环PID控制器C语言实现

c

// PID控制器结构体 (通用)
typedef struct {
    float Kp, Ki, Kd;  // PID参数
    float integral;     // 积分项
    float prev_error;   // 上一次误差 (用于微分)
    float out_max;      // 输出限幅
    float out_min;
} PIDController;

// PID计算函数
float pidCompute(PIDController *pid, float setpoint, float measurement) {
    float error = setpoint - measurement;
    
    // 比例项
    float P_out = pid->Kp * error;
    
    // 积分项 (抗饱和)
    pid->integral += error;
    if (pid->integral > pid->out_max) pid->integral = pid->out_max;
    else if (pid->integral < pid->out_min) pid->integral = pid->out_min;
    float I_out = pid->Ki * pid->integral;
    
    // 微分项 (防止设定值突变)
    float derivative = error - pid->prev_error;
    float D_out = pid->Kd * derivative;
    pid->prev_error = error;
    
    // 计算总输出并限幅
    float output = P_out + I_out + D_out;
    if (output > pid->out_max) output = pid->out_max;
    if (output < pid->out_min) output = pid->out_min;
    
    return output;
}

// 三环控制示例 (在定时中断中调用)
void motorControlLoop() {
    // 1. 读取实际位置 (编码器计数)
    int32_t actual_pos = readEncoder();
    
    // 2. 位置环PID计算 -> 输出目标速度
    float target_speed = pidCompute(&pid_pos, target_position, actual_pos);
    
    // 3. 读取实际速度 (编码器差分/定时器计数)
    float actual_speed = estimateSpeed();
    
    // 4. 速度环PID计算 -> 输出目标q轴电流Iq_ref
    float target_iq = pidCompute(&pid_speed, target_speed, actual_speed);
    
    // 5. 读取实际相电流 (ADC采样 + Clarke/Park变换后得到Iq)
    float actual_iq = getActualIq(); 
    
    // 6. 电流环PID计算 -> 输出q轴电压Vq
    float vq = pidCompute(&pid_current, target_iq, actual_iq);
    
    // 7. 执行FOC算法 (SVPWM生成)
    focSvpwm(vq, 0); // 假设Id_ref=0 (磁场定向控制)
}

六、系统调试与性能优化关键技巧

1. 姿态传感器标定流程
  1. 陀螺仪零偏标定: 静止放置 >10秒,计算各轴平均值作为零偏补偿值。

  2. 加速度计标定: 六面法旋转传感器,记录各面输出,计算标度因子和零偏。

  3. 安装误差补偿: 确保传感器坐标系与小车本体坐标系对齐。

2. PID参数整定口诀表
现象问题环节调整方向物理意义
响应慢,收敛时间长所有环↑ Kp提高系统响应速度
静态误差大速度/位置环↑ Ki增强积分作用消除稳态误差
超调大,振荡剧烈速度/位置环↑ Kd增加阻尼抑制超调和振荡
高频抖动电流环↓ Kp, ↑ 滤波减小高频增益,抑制噪声影响
启动时“冲”一下位置环↑ Kd 或 ↓ Kp抑制初始阶跃响应过冲
3. 关键性能指标对比
控制方案稳态精度动态响应计算复杂度抗干扰性
纯互补滤波 + 单环PID
卡尔曼滤波 + 三环PID
非线性控制 (如滑模)极快极强

七、完整平衡控制策略实现

将姿态解算与电机控制结合,形成闭环平衡控制:

c

void balanceControlLoop() {
    // 1. 读取MPU6050原始数据 (gyro, accel)
    readMpu6050(&gyro, &accel);
    
    // 2. 快速卡尔曼滤波计算车身俯仰角pitch
    float pitch = kalmanUpdate(&kf, calculateAccelPitch(accel), gyro.y, dt);
    
    // 3. 计算平衡控制量 (角度环PD控制)
    float balance_output = Kp_balance * pitch + Kd_balance * gyro.y;
    
    // 4. 叠加速度控制 (防止小车跑飞)
    float speed_feedback = pidCompute(&pid_speed, 0, getWheelSpeed());
    float motor_output = balance_output - speed_feedback;
    
    // 5. 将控制量映射为左右电机目标转速
    setMotorSpeed(MOTOR_LEFT, motor_output);
    setMotorSpeed(MOTOR_RIGHT, motor_output);
}

八、工程挑战与解决方案

挑战现象解决方案
传感器噪声干扰车身高频抖动卡尔曼滤波优化Q/R参数,增加ADC采样滤波
电机响应滞后平衡反应迟钝,易倒提高电流环带宽,优化PWM频率,选用低电感电机
电池电压波动不同电量下性能不一致加入电压前馈补偿,或使用电流闭环而非电压开环
机械振动耦合电机振动影响姿态读数机械隔离IMU,软件低通滤波,提高传感器安装刚度
启动/停止冲击上电瞬间猛转软启动策略,缓增目标值;加入死区控制

附录:关键参数参考表

参数符号典型值范围单位说明
卡尔曼 Q_angleQ_angle0.001 - 0.003-角度过程噪声
卡尔曼 Q_biasQ_bias0.001 - 0.006-陀螺零偏过程噪声
卡尔曼 RR_measure0.01 - 0.05-加速度计测量噪声
位置环 KpKp_pos5.0 - 20.0-比例增益
速度环 KpKp_speed0.05 - 0.2-比例增益
电流环 KpKp_curr0.5 - 2.0A/V比例增益
平衡角度环 KpKp_balance20.0 - 50.0-比例增益
平衡角度环 KdKd_balance0.5 - 2.0-微分增益
PWM 频率f_pwm16k - 20kHz电机驱动开关频率
控制周期T_control1 - 5ms算法执行间隔

通过本文详实的理论分析、代码实现和工程图表,读者可系统性掌握平衡小车核心技术。实际开发中需结合硬件平台特性反复调试,方能实现稳定、灵活的平衡效果。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值