此博客是一份完整的STM32 F103C8T6入门PID控制算法的指南,以平衡小车为例。
内容包括:
- PID算法的基本原理(比例、积分、微分的数学公式及作用)
- PID在平衡小车中的应用(姿态控制、速度控制的具体实现方式)
- STM32 F103C8T6的硬件配置(PWM、ADC、陀螺仪、编码器的使用)
- STM32的PID算法代码实现(C语言代码示例,涵盖姿态控制和速度控制)
- PID参数调试方法(如何有效调整Kp、Ki、Kd参数以优化控制效果)
1. PID算法的基本原理
PID控制器通过比例(P)、积分(I)和微分(D)三个部分对误差进行运算,生成控制输出。其连续时间数学表达式为:
u(t)=Kp⋅e(t)+Ki⋅∫e(t) dt+Kd⋅de(t)dtu(t) = K_p \cdot e(t) + K_i \cdot \int e(t)\,dt + K_d \cdot \frac{de(t)}{dt}
其中,$e(t)$是系统期望值与实际输出之间的偏差,$K_p$、$K_i$、$K_d$分别为比例、积分、微分系数 (〖 PID 算法 〗PID 算法基础_pid公式-优快云博客)。通过将输出反馈给输入形成闭环控制,当输出出现偏差时,根据偏差调整控制输入,使系统趋于稳定 (〖 PID 算法 〗PID 算法基础_pid公式-优快云博客)。
PID各部分的作用如下:
- 比例控制(P):按当前误差的比例输出控制量。较大的比例系数$K_p$能提高响应速度和减小稳态误差,但过大会导致系统振荡或超调。P控制相当于“看到误差就立刻纠正”。
- 积分控制(I):根据误差随时间的累积输出控制量,用于消除稳态误差。当系统长期存在小偏差时,积分项会不断积累并加大控制输出,直到误差为零。但积分项过强会引起超调和振荡(积分饱和),使系统响应变慢。I控制相当于“长期偏差累积起来一起纠正”。
- 微分控制(D):根据误差变化率输出控制量,预测误差的趋势并提前施加校正,能提高系统稳定性、减少超调。微分项相当于对误差变化“刹车”或阻尼作用。如果$K_d$太大,会对噪声非常敏感,引起输出抖动。D控制就像“根据变化趋势提前纠正”。
综合而言,PID控制通过比例迅速响应误差,积分消除残余稳态误差,微分抑制误差的快速变化,三者叠加共同作用 (〖 PID 算法 〗PID 算法基础_pid公式-优快云博客)。采用适当的$K_p$、$K_i$、$K_d$参数,可以让闭环系统在无模型精确数学模型的情况下获得良好的控制效果和稳定性 (〖 PID 算法 〗PID 算法基础_pid公式-优快云博客)。对于大多数线性系统,正确调整PID参数可以使输出快速跟随目标且误差趋于零,从而稳定系统。
2. PID在平衡小车中的应用
两轮自平衡小车是PID控制的经典应用案例之一。小车直立需要实时调整车轮运动来平衡车身角度,同时根据需要控制前进后退的速度。典型做法是采用双闭环控制:里层控制小车的倾斜角(姿态),外层控制小车的移动速度,从而实现既能自我平衡又能保持期望速度 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。下面分别介绍姿态环和速度环的控制方式,并说明双环如何协同工作。
姿态控制(基于陀螺仪和加速度计的角度控制)
姿态控制是平衡小车最核心的部分,目标是将小车车身的倾斜角控制在0度(即垂直直立)或很小的范围内。通过陀螺仪和加速度计获取小车的倾斜角度和角速度作为反馈,将其与目标角度(通常为0度,或校准后的机械中值角度)比较得到角度误差 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。然后利用PID(常简化为PD)算法计算电机控制输出,使车轮转动纠正倾斜。
在姿态环中,通常采用比例-微分控制(PD):比例项根据当前倾斜角误差产生校正力矩,微分项利用陀螺仪测得的角速度提供阻尼以防止过冲 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客) (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。例如,当小车向前倾斜时,角度误差为正,控制器会驱动车轮向前转动以产生一个反向力矩把车扶正;当倾斜角变化很快时,微分项(陀螺仪角速度)会抑制过快的调整以防振荡 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客) (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。通过快速、频繁地调整电机转速,姿态PID控制器可以在小车偏离平衡位置时立即产生纠正动作,从而在动态上保持小车直立。
实现要点:姿态控制需要高频率更新(通常几十到上百Hz),以便及时响应倾斜变化。同时需要融合陀螺仪和加速度计数据计算出准确的倾角。常用方法是在STM32中对MPU6050等IMU传感器读取角速度和加速度,采用互补滤波或卡尔曼滤波融合,获取平稳的车身倾角反馈用于PID控制。
速度控制(基于编码器的速度反馈)
仅靠姿态环,平衡小车虽然可以短时间直立,但常会出现缓慢漂移:小车会逐渐朝某个方向移动并加速倒下 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。为了解决这一问题,引入速度环控制小车的前进/后退速度。速度控制的目标是将小车的平移速度控制在期望值(通常为0,即不前进)或由用户设定的速度。
通过安装在车轮上的编码器获取实时速度反馈,将其与目标速度比较得到速度误差。速度环一般采用比例-积分控制(PI):比例项根据速度误差调整电机输出,积分项累积长期速度误差以消除持续的速度偏差 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客) (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。对于平衡小车而言,速度环的作用不是直接维持直立,而是纠正姿态环导致的位移偏差:当小车在姿态环作用下前后来回摆动时,速度环通过细微调整平衡点来抑制净位移,使小车在原地附近维持平衡 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。
例如,当小车在直立但向前缓慢滚动时(实际速度为正),速度环检测到正的速度误差(实际大于目标0)。PI控制器会输出一个控制量,使小车稍微后倾以减小前移速度。这通常通过让电机产生一个与前移方向相反的力来实现,从而逐步将速度误差拉回零 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。相反,如果小车缓慢后退,速度环会让小车稍微前倾,推动其向前纠正后退速度。因为速度环的响应可以相对慢一些,它常在较低更新频率下工作,输出作为对姿态环的偏差修正。
实现要点:速度反馈可由光电编码器提供。STM32的定时器可以配置为编码器接口模式,直接读取轮子的转速和转向。速度环控制输出通常作用于改变姿态环的目标值或直接累加到姿态控制输出上(见下节),以调整小车的平衡位置。需要注意对编码器信号的滤波(例如低通滤波)以避免速度反馈噪声引入抖动 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客) (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。此外,应限制积分项最大值以防止积分饱和引起失控 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。
双闭环控制策略(角度环 + 速度环)
平衡小车的控制通常采用角度环和速度环双闭环串级控制。两者协调工作:内环姿态控制小车直立,外环速度控制消除累计位移。常见的控制策略有两种思路:
-
姿态内环、速度外环:这是很多开源方案使用的方法。角度环作为快速内环,以0度为目标使小车保持直立;速度环作为外环较慢地调整,使小车平均速度趋向目标(如0)。外环根据速度误差输出一个小的角度偏移或直接附加的电机控制量,作用到内环上,防止小车长时间漂移 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。简单来说,速度环在保证不干扰小车即时平衡的前提下,缓慢纠正姿态环导致的位置偏移。例如,将速度PI控制器的输出看作期望倾斜角的微小调整:当检测到前移,令期望角度稍微后倾;当检测到后退,期望角度稍微前倾。姿态环则努力跟随这个调节后的期望角,实现既平衡又不乱跑。
-
角度外环、速度内环:有些理论分析中,会将角度作为外环,产生期望轮速,速度作为内环实现该轮速 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。这种框图下,角度控制器根据倾斜角误差输出一个“纠正速度”指令,然后速度控制器驱动电机达到该速度,从而带动小车移动以恢复平衡。这种描述在控制原理上等价于上述方法,只是从倒立摆原理出发来理解。对于初学者,实现上更直观的方法仍是将角度作为快速控制,速度作为补偿修正。
无论描述如何,双环控制的本质是在单纯角度控制的基础上增加了对位移/速度的校正,从而长期保持在原地平衡 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。实践中如果没有速度环,小车往往会在纠正倾斜的过程中逐渐加速朝一侧跑开,最终失去平衡 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car );没有角度环则小车根本无法直立 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。只有双环配合并调试好PID参数,小车才能既直立又不持续跑偏 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。
在实现时,常将姿态环输出的PWM控制量和速度环输出的控制量相加(或按适当比例组合),共同作为电机驱动输入。例如:
PWMfinal=PWMangle+PWMspeedPWM_{\text{final}} = PWM_{\text{angle}} + PWM_{\text{speed}}
这样,当小车倾斜时,$PWM_{\text{angle}}$会产生主要的平衡力矩;如果存在速度漂移,$PWM_{\text{speed}}$会略微增加或减少整体PWM,促使小车反向加速抵消漂移。双闭环控制框图如图4所示 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car ):角度环使倾角趋零,其输出作为速度环的输入与实际速度比较,速度环输出最终驱动电机校正运动。
3. STM32 F103C8T6的硬件配置
STM32F103C8T6是一款常用的ARM Cortex-M3内核的32位单片机,具有丰富的外围接口,非常适合用于制作两轮平衡小车。本节介绍在平衡小车项目中涉及的STM32硬件配置,包括PWM、电机驱动,ADC采样,姿态传感器陀螺仪,以及编码器测速等。
PWM控制电机速度
电机速度控制通过PWM(脉宽调制)来实现。STM32F103C8T6内置多路定时器,可将其通道配置成PWM输出模式。通过调整PWM占空比,控制电机驱动器输出给电机的平均电压,从而调节电机转速。对于平衡小车的两轮驱动,一般使用两个PWM通道分别控制左、右电机。例如,可使用TIM3定时器的通道1和通道2输出PWM信号:TIM3_CH1(映射在PA6引脚)和 TIM3_CH2(PA7引脚)可连接到双路H桥电机驱动芯片(如TB6612FNG)的PWM输入端 (IO引脚分配 · 给新手的两轮自平衡小车开发实战指南)。STM32通过设置定时器的预分频和重装载值来确定PWM频率(常用几kHz以上,使电机驱动平稳无啸叫),通过设置捕获比较寄存器(CCR)值来改变占空比。
除了PWM信号,电机驱动还需要方向控制。以TB6612FNG为例,每个电机有两个方向控制引脚(例如AIN1/AIN2或BIN1/BIN2)决定电流方向,以及一个PWM引脚控制速度。方向引脚可连接到STM32的GPIO输出,通过设置高低电平控制电机正转或反转。PWM引脚则接定时器通道输出。配置时,应将相关GPIO引脚模式设为复用输出(AF_PP)以使定时器功能生效。注意:对于不同的电机驱动器,如L298N或DRV8833,接线和控制逻辑类似,只需确保PWM和方向信号正确连接。
ADC采集传感器数据
STM32F103C8T6集成了多通道的10位ADC模块,可以用于采集各种模拟传感器数据。在平衡小车中,ADC常用于监测电源电压、电流,或者读取模拟传感器(如果有)。例如,可以将电池通过分压电路接入ADC通道,定期采样电池电压以防止过放电;或者如果使用模拟陀螺仪/加速度计,也可以通过ADC读取其输出电压对应的角速度/角度。配置ADC时,需要启用相应通道的GPIO为模拟输入,并配置ADC采样时间。STM32的ADC可以通过扫描模式或定时器触发定期采样。由于F103C8T6的ADC精度10位,在0~3.3V范围内能分辨约3.2mV,对于监测电压已足够。如果要读取倾角传感器的模拟量(如某些陀螺仪模块带模拟输出),需注意传感器的满量程电压并选择合适参考电压。采样得到的数值可参与PID控制(例如电压补偿)或者作为保护策略依据。在本平衡小车例子中,主要传感器(MPU6050陀螺仪模块)是数字接口,因此ADC并非必需环节,但仍可用来获取环境信息或电源数据。
陀螺仪获取小车姿态角
陀螺仪和加速度计是平衡小车姿态感知的关键。常用的是MPU6050六轴传感器(3轴陀螺仪+3轴加速度计)。STM32F103C8T6通过I2C接口与MPU6050通信,读取其加速度和角速度数据。F103C8T6有两路I2C,其中I2C1的引脚映射为PB6(SCL时钟线)和 PB7/PB9(SDA数据线,具体取决于复用映射) (IO引脚分配 · 给新手的两轮自平衡小车开发实战指南)。实际硬件中,MPU6050模块的SCL和SDA应分别连接到STM32的PB6和PB7/PB9,并上拉电阻保持总线空闲电平。初始化时,在STM32中配置I2C1工作在标准模式(100kHz)或高速模式,与MPU6050的地址通信,配置MPU6050进入测量模式(关闭休眠,设置满量程范围等)。然后定时读取陀螺仪的角速度(三轴Gyro数据)和加速度计数据。
为了得到可靠的倾斜角度(俯仰角,即小车前后倾角),需要将陀螺仪的角速度和加速度计的重力方向数据融合。简单有效的方法是互补滤波:例如以 200Hz 频率读取传感器,使用陀螺仪角速度对上次角度积分更新,加速度计计算当前倾角,按照一定比例融合:
θ=α×(θprev+ωyΔt)+(1−α)×θacc\theta = \alpha \times (\theta_{\text{prev}} + \omega_y \Delta t) + (1-\alpha) \times \theta_{\text{acc}}
其中$\omega_y$为陀螺仪测得的旋转角速度,$\theta_{\text{acc}}$为根据加速度计Z、Y轴算出的倾角。$\alpha$在0~1之间(如0.98) (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。经过滤波,可以获得平稳且准确的姿态角度。也可以使用卡尔曼滤波,效果更好但实现复杂 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。将计算得到的倾角(例如前后倾角Pitch)作为姿态环PID的反馈输入,角速度$\omega_y$可直接用作微分项反馈 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客) (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。
小贴士:在读取陀螺仪数据时,注意对零偏进行校准(静止时读取一段时间取平均作为零偏值),加速度计也需要确定静止时的倾角零点。如果使用互补滤波,需要选择合适的融合系数和采样周期,才能兼顾动态和稳态性能。
编码器测量轮速
编码器用于测量车轮的转速和方向,是速度环反馈的来源。常用的是光电编码器或霍尔编码器,安装在直流电机轴上,每转输出多周期脉冲。STM32F103C8T6的通用定时器(TIM)可配置为编码器接口模式读取这些脉冲信号。以两路电机为例,可利用TIM2和TIM4分别连接左右轮编码器信号:将编码器的A相和B相信号接到STM32的两个定时器通道输入。如左轮编码器接PA0 (TIM2_CH1) 和 PA1 (TIM2_CH2) (IO引脚分配 · 给新手的两轮自平衡小车开发实战指南);右轮编码器接PB6 (TIM4_CH1) 和 PB7 (TIM4_CH2) (IO引脚分配 · 给新手的两轮自平衡小车开发实战指南)。在软件上,配置TIM2和TIM4的编码器模式,这样定时器计数值会根据编码器脉冲自动增减。每经过一定时间(例如每5ms在定时中断读取一次),定时器计数的增量即可用于计算轮速 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。如果需要绝对位移,还可使用定时器溢出作为计数,但平衡小车主要关心速度而非行走距离。
值得注意的是,编码器的计数需要转换为实际速度单位(如转每分钟RPM或线速度m/s)。一般做法是已知编码器每转脉冲数和轮子周长,通过在固定周期内计算脉冲数来得到速度。例如,小车控制程序每5ms读取一次编码器增量$\Delta n$,如果编码器每转$N$个脉冲,轮径$D$,则当前速度约为 $(\Delta n / N) \times \frac{D\pi}{\Delta t}$。不过在PID控制中无需精确物理单位,只需相对速度即可。也可以对编码器读数做数字滤波或平均,以减少机械抖动的影响 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。STM32的定时器还有滤波器可以对输入脉冲消抖,这在接线较长或信号有毛刺时很有用。
通过编码器获取的速度反馈送入速度PI控制器,控制器输出再作用于电机PWM。编码器反馈回路较慢,但对长期误差(位置漂移)进行纠正,使小车保持在原地附近摇摆而不会越走越远。
4. STM32的PID算法代码实现
下面给出一个C语言代码示例,展示如何在STM32F103C8T6上实现平衡小车的双环PID控制。代码包括PID控制器的数据结构定义、角度环和速度环控制算法,以及主循环中传感器读取和PWM输出的流程。此示例为演示性质,具体数值和函数需根据硬件条件调整。
#include "stm32f10x.h" // STM32寄存器和外设库头文件
// PID参数(根据需要调整)
float Kp_angle = 50.0f; // 姿态环比例系数
float Ki_angle = 0.0f; // 姿态环积分系数(一般不使用或很小)
float Kd_angle = 1.0f; // 姿态环微分系数
float Kp_speed = 0.5f; // 速度环比例系数
float Ki_speed = 0.1f; // 速度环积分系数
float Kd_speed = 0.0f; // 速度环微分系数(速度环一般不需要D项)
// 全局变量保存误差积分/上次误差等(初始化为0)
float angle_err_integral = 0.0f;
float angle_err_last = 0.0f;
float speed_err_integral = 0.0f;
float speed_err_last = 0.0f;
// 读取传感器的函数(需根据具体硬件实现)
float GetAngle(void) {
// 从陀螺仪/加速度计计算倾斜角度(度)
// 例如通过互补滤波融合MPU6050数据
return 0.0f; // 示例返回0,应替换为实际传感器读数
}
float GetGyroRate(void) {
// 获取陀螺仪角速度(度/秒)
return 0.0f;
}
float GetSpeed(void) {
// 读取编码器计算小车速度(例如编码器脉冲数/周期)
return 0.0f;
}
// 设置电机PWM的函数(需根据具体驱动实现)
void SetMotorPWM(float pwm_left, float pwm_right) {
// 将计算出的PWM值输出到电机
// 例如设置TIM3->CCR1 = pwm_left, TIM3->CCR2 = pwm_right(占空比)
}
// 姿态环PID控制计算(PD控制)
float PID_Angle(float target_angle, float current_angle, float gyro_rate) {
// 计算误差:期望角度 - 当前角度
float error = target_angle - current_angle;
// 积分项(如需I控制可启用)
angle_err_integral += error;
// 微分项:使用陀螺仪角速度作为角度变化率的反馈
float derivative = -gyro_rate;
// 计算PD输出
float output = Kp_angle * error + Kd_angle * derivative;
// 保存上次误差(如果需要D项基于误差差分,可以用error-error_last)
angle_err_last = error;
return output;
}
// 速度环PID控制计算(PI控制)
float PID_Speed(float target_speed, float current_speed) {
float error = target_speed - current_speed;
// 积分误差累加
speed_err_integral += error;
// 积分防饱和,限制积分项大小,防止长期误差过大
if(speed_err_integral > 1000.0f) speed_err_integral = 1000.0f;
if(speed_err_integral < -1000.0f) speed_err_integral = -1000.0f;
// 微分项一般不用于速度环,此处忽略Kd_speed
float output = Kp_speed * error + Ki_speed * speed_err_integral;
speed_err_last = error;
return output;
}
int main(void) {
// 硬件初始化(时钟、GPIO、PWM定时器、I2C陀螺仪、编码器定时器等)
SystemInit();
// ... 初始化代码,如InitPWM(), InitIMU(), InitEncoder()等
float target_angle = 0.0f; // 目标角度(机械中值),例如设为0度直立
float target_speed = 0.0f; // 目标速度,0表示保持原地
// 主控制循环(可由定时器中断每5ms调用)
while(1) {
// 1. 获取传感器数据
float angle = GetAngle(); // 当前倾斜角度
float gyro = GetGyroRate(); // 当前角速度
float speed = GetSpeed(); // 当前小车速度
// 2. 计算PID控制输出
float angle_output = PID_Angle(target_angle, angle, gyro);
float speed_output = PID_Speed(target_speed, speed);
// 3. 合成两个控制环的输出
float control = angle_output + speed_output;
// 如有需要,可根据控制值确定左右轮PWM(例如差速转向时略有不同)
// 4. 将控制输出应用到电机
SetMotorPWM(control, control);
// 5. 略作延时或等待下次循环(如果不是定时中断环境)
}
}
上述代码展示了基本的控制流程:读取传感器→计算姿态PID输出→计算速度PID输出→叠加控制量→输出PWM驱动电机 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。其中PID_Angle
函数实现了直立环的PD控制,使用角度误差和角速度(相当于误差微分)计算输出 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客);PID_Speed
函数实现速度环PI控制,积累速度误差并计算校正输出 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。在主循环中,将两者输出相加后通过SetMotorPWM
函数控制电机转速。为简明起见,代码中传感器读取和硬件初始化用占位表示,实际应用中应使用STM32外设库函数(如HAL库或标准库)完成I2C读取MPU6050数据、配置TIM_PWM输出、启用编码器接口等工作。
重要提示:实际控制中通常不会在while(1)
的空转中直接延时,而是利用定时中断保证固定的控制周期。例如设置SysTick或TIM中断每5ms触发,在中断服务程序ISR中执行一次上述控制算法(读取传感器和计算输出)。这样可以确保PID控制的采样周期恒定,提高控制稳定性和参数可调性 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。在中断驱动方案下,主循环可以空闲或处理其他非实时任务,如通信、显示等。
5. PID参数调试方法
正确调整PID参数对平衡小车的性能至关重要。以下是调试Kp、Ki、Kd的一般步骤和方法,以及常见问题的诊断与解决。
调参步骤概览 (〖平衡小车制作〗(七)串级PID调参及平衡成果展示(超详解)_平衡车pid参数怎么调-优快云博客):
-
确定机械中值:机械中值是小车真正平衡时的倾斜角度偏置。将小车放在地面,分别向前和向后慢慢倾斜找到即将要倒下的临界角度,然后取两者的平均值作为机械中值角度 (〖平衡小车制作〗(七)串级PID调参及平衡成果展示(超详解)_平衡车pid参数怎么调-优快云博客)。在代码中将此角度作为目标角度。例如,若小车向前倒在 -3°、向后倒在 2°,则机械中值约为 -0.5°(可近似取 -1°) (〖平衡小车制作〗(七)串级PID调参及平衡成果展示(超详解)_平衡车pid参数怎么调-优快云博客)。校准机械中值能确保PID控制以正确的目标角度平衡小车。
-
调整姿态环(内环)参数:首先调整Kp(比例)。将速度环关闭(或设Ki_speed=0,Kp_speed很小),仅靠角度环让小车初步直立。轻扶小车离地,测试Kp极性是否正确:若小车倒向一侧,电机应朝倒下方向转动,使小车有向反方向扶正的趋势 (〖平衡小车制作〗(七)串级PID调参及平衡成果展示(超详解)_平衡车pid参数怎么调-优快云博客)。若电机转向反了(即正反馈),需反转Kp符号或交换电机线以实现负反馈 (〖平衡小车制作〗(七)串级PID调参及平衡成果展示(超详解)_平衡车pid参数怎么调-优快云博客)。极性正确后,从较小的Kp开始逐渐增大。观察小车反应:Kp过小,小车反应迟钝,无法及时纠正倾斜;Kp增大,小车变得“挺直”但可能开始出现来回小幅振荡。找到使小车刚好出现振荡的Kp临界值,然后略微减小约20%左右。接着**增加Kd(微分)**来消除振荡。Kd提供阻尼,通常从0开始增加,直到振荡减弱,站立变稳。若Kd过高,会让反应变慢甚至引入抖动,应适当降低。一般直立环PD调好后,小车可短暂平衡几秒但可能缓慢移动。如果需要,引入一个很小的Ki_angle帮助消除极微小的角度偏差,但多数情况下角度环不加积分以免引入飘移。
-
调整速度环(外环)参数:在角度环稳定工作的基础上,开启速度环校正位移漂移。首先确定速度环Kp_speed的符号/极性:对于保持平衡,速度环实际上是正反馈性质——如果小车有向前的速度,速度环应该产生让小车继续微向前倾的控制来追赶,这样才能减缓其倒下趋势(本质上是通过前进来“追上”重心)。因此,常采用实际速度-目标速度的误差来计算速度环输出(如代码中的
error = (当前速度 - 期望速度)
),并用正的Kp_speed,使得前倾时(当前速度正)输出为正,叠加到姿态环使车进一步前倾,从而实现向前追赶重心,避免前倒 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。如果采用相反的误差计算方式,则需用负的Kp_speed确保这种关系。确认极性后,从很小的Kp_speed开始增加。速度环Kp过小,效果不明显,小车会缓慢移动一段后倒下;Kp过大,则小车在原地前后快速来回跑,甚至发生低频的大幅前后摆动。选取一个让小车缓慢前后晃动且不会越跑越远的Kp_speed。然后逐步增加Ki_speed(积分),积分项会在长时间有微小速度偏差时产生修正力。例如,小车始终缓慢前移意味着存在恒定偏差,积分项累积后会让其逐渐往后拉。Ki_speed一般取比Kp_speed小一个数量级以上。调整Ki时要防止引入明显的周期性前后摆动——如果出现持续的来回摇摆,说明Ki可能过大导致超调,需要减小 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )。调好后,小车应能基本在原地前后轻微来回摆动保持平衡。 -
综合测试与优化:将双环协同工作观察小车表现。如果平衡时间变长、在外力扰动后能自行恢复,说明参数基本合适。可进一步做小幅优化:比如在保证响应足够快前提下,尽量降低角度环Kp以减少电机噪音和振动;或者略增大速度环Ki以消除最后的缓慢漂移。注意每次只调一个参数,观察变化再决定增减。调参是一个反复试验的过程,耐心调节才能找到最佳组合。
常见问题及解决方案:
- 小车突然剧烈振荡或加速倒下:极有可能是控制方向(极性)错误。请立即停止,检查姿态环Kp或速度环Kp符号是否取反。正负反馈判断方法:扶着小车前后倾,若电机朝倾倒方向转为负反馈(正确) (〖平衡小车制作〗(七)串级PID调参及平衡成果展示(超详解)_平衡车pid参数怎么调-优快云博客),朝相反方向转则是正反馈(错误)。
- 持续小幅振荡:如果频率高且快,一般是角度环Kp稍大或Kd不足,尝试减小Kp_angle或增大Kd_angle来增加阻尼。如果振荡频率低且幅度大,多半是速度环引起,尝试减小Kp_speed或Ki_speed。适当增加陀螺仪/速度反馈滤波也能平滑振荡 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)。
- 响应缓慢:表现为小车倾斜后纠正不及时,容易倒下。可考虑逐步提高Kp_angle,使控制更“挺”,或者减少Kd_angle(Kd过大会减弱响应速度)。另外检查陀螺仪滤波延迟是否过大。
- 积分饱和:如果Ki设得过大,小车在一个方向倒下时积分项迅速累积,等扶正时电机会突然高速运转反方向过冲。解决办法是限制积分累积范围(如代码中的
speed_err_integral
限幅) (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客),以及在小车倾角过大或扶起时重置积分(抗饱和)。调试时可先将Ki设为0,只在接近最终调优时再逐步引入积分。 - 传感器零飘和噪声:陀螺仪零偏会导致小车有微小持续旋转感觉,引起慢漂;加速度计噪声会导致角度抖动,引发电机细微抖动。可以在静止时校准陀螺仪零点,或者实现简单零偏漂移校正(长期平均值滤除)。对角度信号和速度信号应用低通滤波 (〖平衡小车制作〗(六)位置式PID、直立环与速度环编程(超详解)_平衡车直立代码-优快云博客)也很重要。
- 电机死区:直流电机存在一个驱动死区电压,小PWM下电机不转。调参过程中如果发现小车在微小倾斜时电机不动作、大倾斜时突然动作过猛,可以考虑在控制输出中加入前馈补偿或死区补偿。例如,当控制输出在一定阈值内时,强制输出零,以避免抖动;超过阈值时,加上一固定偏移克服静摩擦。
总之,PID参数调试需要结合理论和实验调衡。良好的参数能让STM32平衡小车在受到推挤等扰动后迅速恢复直立,并且长时间保持仅有微小的前后摆动。通过本指南对PID原理、双环控制、硬件配置和代码实现的讲解,以及调参方法的介绍,希望读者能够成功实现基于STM32 F103C8T6的两轮平衡小车项目,并从中深入理解PID控制算法的应用。 ( 两轮自平衡小车控制系统设计 Design of Control System for Two-Wheeled Self-Balancing Car )