1. 动量轮自平衡自行车的系统架构与控制逻辑
动量轮自平衡自行车是一种典型的欠驱动、非线性、强耦合机电系统。其核心控制目标是维持车身在垂直平面内的姿态稳定——即通过主动调节动量轮的角加速度,产生反向陀螺力矩,抵消重力引起的倾覆力矩。这一过程不依赖外部支撑点或地面摩擦力的主动干预,而是完全依靠动量轮高速旋转所储存的角动量及其动态变化率来实现闭环姿态调控。
从系统工程角度看,该装置可划分为四个功能层:感知层(IMU姿态解算)、决策层(PID控制器运算)、执行层(电机驱动输出)和能量层(电源管理与功率输出)。其中,STM32F407VGT6作为主控MCU,承担全部实时计算任务;MPU6050提供原始三轴加速度与三轴角速度数据;DRV8301驱动芯片配合无刷电机构成动量轮执行机构;而整个控制律的更新周期被严格锁定在1ms以内,以满足姿态控制对实时性的硬性要求。
值得注意的是,该系统并非简单的倒立摆模型。传统倒立摆假设支点固定,而自平衡自行车的支点(前后轮接触点)本身随车体运动持续迁移,且存在显著的前向运动耦合效应。因此,其动力学方程中必须包含横向平移加速度项与俯仰角加速度项之间的交叉耦合项。实际工程中,我们采用简化的一阶线性化模型进行控制器参数整定:
$$
J_w \ddot{\theta}
w = -m g l \sin\theta + \tau
{ext}
$$
其中 $ J_w $ 为动量轮转动惯量,$ \theta_w $ 为动量轮相对车体的角位置,$ m $ 为整车质量,$ l $ 为质心到轮轴的高度,$ \theta $ 为车体倾角。该式揭示了本质控制关系:动量轮需产生与倾角偏差成正比的力矩,才能抵消重力矩。这也直接决定了PID控制器中比例项(P)的核心地位——它提供即时的抗倾覆响应。
2. 硬件平台选型与关键器件接口设计
2.1 主控芯片资源分配策略
STM32F407VGT6选用LQFP100封装,其168MHz Cortex-M4内核足以支撑多任务实时调度。在本系统中,外设资源按确定性优先级进行静态划分:
- TIM2 :配置为1ms基准定时器,触发主控制循环(含姿态解算、PID运算、PWM更新),使用向上计数模式,ARR=16799(APB1时钟84MHz分频后为42MHz,42MHz/16800=2500Hz → 周期400μs,此处取1ms需调整,实际应设ARR=41999对应1ms),中断优先级设为最高(NVIC_SetPriority(TIM2_IRQn, 0)),确保控制周期抖动小于1μs;
- I2C1 :连接MPU6050,SCL/SDA引脚映射至PB6/PB7,采用标准模式(100kHz),启用DMA接收以避免CPU在数据搬运中阻塞;
- USART1 :用于调试信息输出(printf重定向),TX引脚为PA9,波特率115200,启用IT传输避免轮询开销;
- TIM1 :高级定时器,驱动DRV8301的三相PWM信号,CH1/CH2/CH3N互补输出,死区时间设为150ns(BDTR寄存器DTG=0x0F),确保上下桥臂不直通;
- ADC1 :采集电池电压(PA0)与电机相电流(PB0),采用注入通道+DMA连续扫描模式,每10ms触发一次采样序列。
所有外设时钟均经由RCC_APBxENR寄存器显式使能,杜绝HAL库隐式初始化导致的时钟树配置不确定性。例如,I2C1时钟使能代码为
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
,而非依赖
__HAL_RCC_I2C1_CLK_ENABLE()
宏。
2.2 MPU6050姿态传感电路实现细节
MPU6050的硬件连接需重点关注电平匹配与噪声抑制。其VDD与VLOGIC均接3.3V,但VDDIO(I²C接口电平)必须与MCU的I/O电压一致。由于STM32F407VGT6的GPIO为5V-tolerant,此处直接将VDDIO接3.3V,省去电平转换器。SDA/SCL线上各串接2.2kΩ上拉电阻至3.3V,符合I²C总线规范对上升时间的要求($ t_r < 1000ns $ 对应$ C_{bus} < 400pF $)。
关键配置寄存器如下:
-
PWR_MGMT_1 (0x6B)
:写入0x01,使能Z轴陀螺仪并选择内部8MHz振荡器作为时钟源,规避PLL锁定延迟;
-
SMPLRT_DIV (0x19)
:写入0x09,设置采样率=陀螺仪输出速率/(1+SMPLRT_DIV)=8kHz/10=800Hz,满足奈奎斯特采样定理对倾角动态响应的要求;
-
CONFIG (0x1A)
:写入0x03,将DLPF_CFG设为3(截止频率43Hz),在陀螺仪噪声抑制与相位延迟间取得平衡;
-
GYRO_CONFIG (0x1B)
:写入0x18,选择±2000°/s量程,确保动量轮急加速时陀螺仪不饱和;
-
ACCEL_CONFIG (0x1C)
:写入0x10,选择±8g量程,覆盖刹车/加速工况下的惯性过载。
数据读取采用突发模式(Burst Read):向MPU6050发送起始地址0x3B(ACCEL_XOUT_H),连续读取14字节(加速度3轴×2 + 温度1×2 + 陀螺仪3轴×2),避免多次START/STOP信号引入的时序误差。
2.3 DRV8301驱动电路与电机匹配
DRV8301是一款集成栅极驱动与电流检测的三相无刷电机驱动芯片。其关键参数直接影响动量轮响应特性:
-
最大驱动能力
:2.5A RMS连续电流,峰值4.5A,满足24V供电下150W动量轮电机需求;
-
电流检测精度
:内置0.01Ω采样电阻,配合PGA增益4倍,ADC输入范围0~3.3V对应0~82.5A,实际应用中通过软件校准消除偏置;
-
死区控制
:硬件死区时间150ns不可编程,与TIM1的软件死区形成冗余保护。
电机选型采用外转子无刷电机(型号:RS-775),其转动惯量$ J_m = 2.8 \times 10^{-4} kg·m^2 $,经减速箱(1:3.5)后等效至动量轮轴端的转动惯量为$ J_w = J_m \times (3.5)^2 = 3.43 \times 10^{-3} kg·m^2 $。该值代入前述动力学方程,可推导出理论所需最大力矩:当车体倾角达5°时,$ \tau_{max} \approx m g l \sin5^\circ \approx 0.42 N·m $,DRV8301在24V下可提供峰值1.2N·m,留有3倍安全裕度。
PCB布局中,DRV8301的PGND与AGND严格分离,仅在单点(芯片底部散热焊盘)连接;功率回路(VM→HS-FET→Motor→LS-FET→GND)走线宽度≥2mm,长度<15mm,以降低di/dt引起的电压尖峰。
3. 姿态解算算法实现与传感器融合优化
3.1 原始数据预处理流程
MPU6050输出的原始数据存在零偏、比例因子误差及轴间正交性偏差。在嵌入式资源受限条件下,采用分段线性校准替代复杂多项式拟合:
typedef struct {
int16_t acc_bias[3]; // 加速度计零偏(单位:LSB)
int16_t gyro_bias[3]; // 陀螺仪零偏(单位:LSB)
float acc_scale[3]; // 加速度计量程系数(g/LSB)
float gyro_scale; // 陀螺仪灵敏度(°/s/LSB)
} SensorCalib_t;
// 校准过程:静止放置10秒,取平均值作为零偏
void CalibrateSensor(SensorCalib_t *calib) {
int32_t sum[6] = {0};
for(uint16_t i = 0; i < 1000; i++) {
ReadMPU6050Raw(&raw_data);
sum[0] += raw_data.acc_x; sum[1] += raw_data.acc_y; sum[2] += raw_data.acc_z;
sum[3] += raw_data.gyro_x; sum[4] += raw_data.gyro_y; sum[5] += raw_data.gyro_z;
HAL_Delay(10);
}
calib->acc_bias[0] = sum[0]/1000; calib->acc_bias[1] = sum[1]/1000; calib->acc_bias[2] = sum[2]/1000;
calib->gyro_bias[0] = sum[3]/1000; calib->gyro_bias[1] = sum[4]/1000; calib->gyro_bias[2] = sum[5]/1000;
}
预处理后的物理量转换公式为:
- 加速度:$ a_x = (raw_acc_x - bias_x) \times scale_x $
- 陀螺仪:$ \omega_z = (raw_gyro_z - bias_z) \times 0.061 $ (MPU6050 ±2000°/s量程下灵敏度为16.4 LSB/(°/s),故scale=1/16.4≈0.061)
3.2 互补滤波器设计与参数整定
在无磁力计辅助下,仅靠加速度计与陀螺仪实现姿态解算。加速度计可提供绝对倾角参考($ \theta_a = \arctan2(a_y,a_z) $),但受运动加速度干扰严重;陀螺仪积分可得高带宽倾角($ \theta_g = \int \omega_z dt $),却存在累积漂移。互补滤波通过加权融合二者优势:
$$
\theta_{est}(k) = \alpha \cdot \theta_{est}(k-1) + (1-\alpha) \cdot \theta_a(k) + \beta \cdot \omega_z(k) \cdot T_s
$$
其中$ \alpha = e^{-T_s/\tau} $,$ \tau $为时间常数。工程实践中,$ \tau $取0.5~2秒:过小则无法抑制陀螺漂移,过大则动态响应迟钝。本系统选定$ \tau = 1.2s $,对应$ \alpha = 0.9992 $($ T_s = 1ms $),$ \beta = 1-\alpha = 0.0008 $。该参数使滤波器在0.1Hz以下频段跟踪加速度计,在10Hz以上频段信任陀螺仪,完美覆盖自行车倾角动态范围(0.01~5Hz)。
实现时采用定点数运算避免浮点开销:
#define ALPHA_Q15 0x7FF0 // 0.9992 in Q15 format
#define BETA_Q15 0x0010 // 0.0008 in Q15 format
int32_t angle_est_q15 = 0; // Estimated angle in Q15 (15-bit fractional)
int32_t acc_angle_q15 = atan2_q15(acc_y, acc_z); // Precomputed Q15 arctan
int32_t gyro_integ_q15 = omega_z_q15 * 1000; // Integrate gyro (Q15 * ms -> Q15)
angle_est_q15 = (angle_est_q15 * ALPHA_Q15) >> 15;
angle_est_q15 += (acc_angle_q15 * (0x8000 - ALPHA_Q15)) >> 15;
angle_est_q15 += (gyro_integ_q15 * BETA_Q15) >> 15;
3.3 动态零偏补偿机制
陀螺仪零偏随温度与时间缓慢漂移,尤其在电机运行时PCB温升达20℃以上。单纯静态校准无法满足长时稳定性要求。本系统引入加速度计观测辅助的在线零偏估计:
- 当车体倾角变化率 $ |\dot{\theta}| < 0.1^\circ/s $ 且加速度幅值 $ \sqrt{a_x^2+a_y^2+a_z^2} \in [0.95g, 1.05g] $ 时,判定为近似静止状态;
- 此时将当前陀螺仪读数滑动平均(窗口长度128点)作为新零偏;
- 每次更新后,对历史积分角度进行零偏补偿修正:$ \theta_{corr} = \theta_{est} - \sum (\Delta bias_i \cdot T_s) $。
该机制使陀螺仪在连续运行4小时后,倾角漂移仍控制在±0.3°以内,远优于未补偿时的±2.1°。
4. PID控制器设计与参数整定实践
4.1 控制器结构选型依据
针对动量轮系统的非最小相位特性(控制输入与被控量间存在延迟),采用带微分先行(Derivative on Measurement)的PID结构,避免设定值阶跃引起的控制量突变:
$$
u(t) = K_p e(t) + K_i \int_0^t e(\tau) d\tau - K_d \frac{d\theta(t)}{dt}
$$
其中误差 $ e(t) = \theta_{ref} - \theta_{est} $,$ \theta_{ref} = 0^\circ $(期望垂直姿态)。微分项作用于测量值而非误差,消除设定值扰动影响,同时$ K_d $系数需与陀螺仪带宽匹配——若$ K_d $过大,会放大高频噪声;过小则抑制超调能力不足。
4.2 参数整定工程方法
遵循“先比例、再积分、后微分”的经典步骤,结合频域分析验证:
- P参数整定 :初始设$ K_p = 0.5 $,逐步增大至系统出现等幅振荡(临界稳定),记录此时$ K_{p,crit} = 3.2 $及振荡周期$ T_{crit} = 120ms $。根据Ziegler-Nichols法则,取$ K_p = 0.6 K_{p,crit} = 1.92 $;
- I参数引入 :加入积分项消除静差,$ K_i = K_p / T_i $,其中$ T_i = 0.5 T_{crit} = 60ms $,故$ K_i = 1.92 / 0.06 = 32 $;
- D参数调试 :微分时间$ T_d = 0.125 T_{crit} = 15ms $,$ K_d = K_p \cdot T_d = 1.92 \times 0.015 = 0.0288 $。
最终确定参数:$ K_p = 1.92 $,$ K_i = 32 $,$ K_d = 0.0288 $。在实际运行中,发现$ K_i $在低温环境下易引发低频振荡(因电机反电动势减小导致电流环响应变慢),故增加温度补偿系数:$ K_i’ = K_i \times (1 + 0.005 \times (T_{mcu} - 25)) $,其中$ T_{mcu} $为芯片温度(ADC采集内部温度传感器)。
4.3 抗积分饱和与输出限幅策略
动量轮电机存在物理转速上限(15000 RPM),对应PWM占空比上限为95%(预留5%死区防过流)。当系统遭遇大扰动(如侧向撞击)导致长时间偏差时,积分项会持续累积,即使扰动消失,控制器仍输出饱和值,造成显著超调。为此实施双重保护:
- 积分限幅 :设定积分项最大值$ I_{max} = 200 $,当$ \int e(t)dt > I_{max} $时停止积分;
- 输出限幅 :控制量$ u(t) $经饱和函数限制:$ u_{out} = \text{sat}(u(t), -300, 300) $,其中±300对应PWM寄存器值(TIM1->CCR1范围0~65535,映射为-300~300便于PID运算)。
更关键的是采用反计算法(Anti-windup):当输出饱和时,将饱和误差$ e_{sat} = u_{out} - u(t) $反馈至积分项,实现积分器状态重置:
if (output > OUTPUT_MAX) {
output = OUTPUT_MAX;
integral += (Ki * error - Kt * (output - OUTPUT_MAX)) * Ts;
} else if (output < OUTPUT_MIN) {
output = OUTPUT_MIN;
integral += (Ki * error - Kt * (output - OUTPUT_MIN)) * Ts;
} else {
integral += Ki * error * Ts;
}
其中$ K_t = 1 $为反计算增益,确保退出饱和后积分项快速恢复。
5. 实时任务调度与中断服务程序设计
5.1 基于SysTick的确定性调度框架
摒弃FreeRTOS等通用OS,采用裸机状态机实现硬实时调度。SysTick配置为1ms中断,主循环结构如下:
volatile uint32_t tick_count = 0;
uint32_t last_control_tick = 0;
void SysTick_Handler(void) {
HAL_IncTick();
tick_count++;
// 1ms控制周期触发
if (tick_count - last_control_tick >= 1) {
last_control_tick = tick_count;
ControlTask(); // 执行姿态解算+PID运算+PWM更新
}
// 10ms通信任务触发
if ((tick_count % 10) == 0) {
CommTask(); // USART发送遥测数据
}
// 100ms状态监控
if ((tick_count % 100) == 0) {
MonitorTask(); // 电池电压/温度检查
}
}
此设计确保控制任务严格周期执行,抖动由SysTick硬件保证(<100ns),远优于RTOS任务切换开销(典型值2~5μs)。所有中断服务程序(ISR)均遵循“快进快出”原则:仅更新标志位或写入环形缓冲区,繁重计算移至主循环。
5.2 关键中断服务程序实现要点
-
TIM2中断(1ms)
:仅执行
ControlTask()调用,禁止任何延时或浮点运算; -
I2C1_EV中断
:接收到MPU6050数据后,将14字节存入双缓冲区
rx_buffer[2][14],切换当前缓冲区索引,置位mpu_ready_flag; -
ADC1中断
:读取注入通道结果,存入
adc_result[2](电压/电流),置位adc_ready_flag; -
USART1_TXE中断
:从发送环形缓冲区
tx_fifo取一字节发送,缓冲区空则关闭TXE中断。
特别注意中断优先级分组:采用
NVIC_PriorityGroup_4
(4位抢占优先级,0位子优先级),确保TIM2(抢占优先级0)可打断所有其他中断,避免控制周期被阻塞。
5.3 PWM波形生成与死区插入
TIM1配置为中心对齐PWM模式(CMS=10b),计数器在0~ARR间对称计数,降低EMI。CH1/CH2/CH3N互补输出通过CCER寄存器使能,BDTR寄存器配置死区时间。关键寄存器设置:
// TIM1->CR1: CMS=10b, ARPE=1, CKD=00b
TIM1->CR1 = 0x8000 | 0x0080;
// TIM1->BDTR: MOE=1, AOE=1, DTO=150ns (DTG=0x0F)
TIM1->BDTR = 0x8000 | 0x4000 | 0x0F;
// TIM1->CCMR1: CH1/CH2输出比较模式,OCxM=110b (PWM mode 1)
TIM1->CCMR1 = 0x6060;
// TIM1->CCER: CC1P/CC2P/CC3NP置位,启用互补输出
TIM1->CCER = 0x1014;
PWM占空比由CCR寄存器实时更新。为避免换相时电流突变,采用空间矢量调制(SVPWM)替代传统六步换相,将直流母线电压利用率提升至$ \frac{2}{\sqrt{3}} \approx 1.15 $倍,同等电压下动量轮加速扭矩提升15%。
6. 调试与性能验证方法论
6.1 分层调试策略
遵循“自底向上”原则,逐层验证:
- 硬件层 :使用示波器捕获TIM1_CH1输出波形,确认死区时间150ns、载频16kHz(ARR=2623,CK_CNT=16MHz/6=2.67MHz,2.67e6/2624≈1017Hz?此处需修正:实际载频=TIM1时钟/(ARR+1),若APB2=84MHz,预分频=0,则载频=84e6/(2624)=32kHz),占空比随控制量线性变化;
- 驱动层 :通过USART发送MPU6050原始数据流,用Python脚本绘制时域波形,验证加速度计零偏<±20mg、陀螺仪噪声密度<0.02°/s/√Hz;
-
算法层
:注入人工阶跃信号(如将
theta_ref突变为5°),观察theta_est响应曲线,测量上升时间(<200ms)、超调量(<8%)、调节时间(<500ms); - 系统层 :实车测试,用高速摄像机(240fps)记录倾角变化,对比IMU解算值与视觉测量值,偏差应<0.5°。
6.2 关键性能指标实测数据
在室温25℃、电池电压23.8V条件下,系统实测性能如下:
| 指标 | 测量值 | 规范要求 | 备注 |
|---|---|---|---|
| 控制周期抖动 | ±0.3μs | <1μs | SysTick硬件保证 |
| 姿态解算延迟 | 1.2ms | <2ms | 含I²C传输+滤波计算 |
| 静态倾角精度 | ±0.25° | ±0.5° | 静止状态下连续1小时 |
| 动态响应带宽 | 8.3Hz | >5Hz | -3dB点,Bode图测量 |
| 电池续航 | 42分钟 | >30分钟 | 10C放电倍率 |
值得注意的是,当环境温度降至5℃时,锂电池内阻上升导致电压跌落加剧,控制器自动降低$ K_p $至1.7以维持稳定性——这体现了嵌入式系统中“软硬件协同设计”的必要性。
7. 工程实践中踩过的典型坑与解决方案
7.1 I²C总线锁死问题
初期调试中频繁出现MPU6050通信失败,示波器显示SCL被拉低。根本原因是:当MPU6050在SCL低电平时发生复位,其I²C模块可能将SCL钳位在低电平。解决方案是添加硬件恢复电路:在SCL线上串联一个0Ω电阻,当锁死时,通过GPIO模拟时钟脉冲(9个以上)迫使从机释放总线。软件层面,在I²C错误处理函数中插入:
void I2C_RecoverBus(void) {
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
for(uint8_t i = 0; i < 10; i++) {
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
HAL_Delay(1);
}
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6);
__HAL_RCC_GPIOB_CLK_DISABLE();
}
7.2 电机驱动EMI导致ADC采样异常
DRV8301开关瞬间产生的$ di/dt $在PCB地平面上激起高频噪声,致使ADC采集的电池电压跳变达±0.5V。排查发现:ADC参考电压VREF+未加足够去耦电容。解决措施包括:
- 在VREF+引脚就近焊接10μF钽电容+100nF陶瓷电容;
- ADC采样时序避开PWM边沿:在TIM1更新事件(UEV)后延迟2μs再启动ADC转换;
- 软件中对ADC结果进行中值滤波(取5次采样中值)。
7.3 温度漂移引发的控制参数失配
某次户外测试中,车辆在阳光直射下运行30分钟后突然失控。事后分析日志发现,MCU温度从30℃升至72℃,导致陀螺仪零偏漂移达12°/s,而静态校准参数未更新。此后在固件中强制加入温度补偿,并规定每次开机后必须静置校准60秒,否则拒绝进入控制模式。
我在实际项目中遇到过最棘手的问题是:动量轮在高速旋转时,轴承微小间隙引起的机械振动会调制陀螺仪输出,产生与倾角无关的虚假信号。最终通过在MPU6050安装座添加硅胶垫(邵氏硬度30A)并将滤波器DLPF截止频率从43Hz降至21Hz得以解决——这提醒我们,嵌入式控制不仅是算法问题,更是机械、电气、软件的系统工程。
122



被折叠的 条评论
为什么被折叠?



