闭环PID控制

闭环PID控制是一个常见的应用场景,尤其在电机控制、温度控制、位置伺服等系统中。以下是实现闭环PID控制的详细步骤和注意事项:

1. PID控制原理

PID(比例-积分-微分)控制器通过以下公式调节输出:
在这里插入图片描述

  • 比例项(P):快速响应误差,但可能导致稳态误差。
  • 积分项(I):消除稳态误差,但可能引起超调。
  • 微分项(D):预测未来误差变化,抑制振荡。

2. 硬件配置

2.1 外设需求
  • ADC:用于采集传感器反馈(如温度、位置、速度)。
  • PWM/TIMER:生成控制信号(如驱动电机或加热元件)。
  • GPIO:连接传感器和执行器。
  • 中断/DMA:实现实时数据采集。
2.2 配置步骤
  1. 初始化ADC:配置为连续扫描模式或定时触发模式。
  2. 配置PWM输出:使用定时器(如TIM1/TIM2)生成PWM信号。
  3. 设置定时器中断:用于周期性执行PID计算(如1kHz频率)。

3. PID算法实现

3.1 位置式PID
typedef struct {
    float Kp, Ki, Kd;
    float integral;
    float prev_error;
} PID_Controller;

float PID_Update(PID_Controller *pid, float setpoint, float measurement) {
    float error = setpoint - measurement;
    pid->integral += error * dt;          // dt为采样时间
    float derivative = (error - pid->prev_error) / dt;
    pid->prev_error = error;
    
    float output = pid->Kp * error 
                 + pid->Ki * pid->integral 
                 + pid->Kd * derivative;
    
    // 输出限幅(防止执行器饱和)
    output = fmaxf(fminf(output, MAX_OUTPUT), MIN_OUTPUT);
    return output;
}
3.2 增量式PID

适用于执行器需要增量控制的场景:

float PID_Incremental(PID_Controller *pid, float error) {
    float delta = pid->Kp * (error - pid->prev_error)
                + pid->Ki * error * dt
                + pid->Kd * (error - 2 * pid->prev_error + pid->prev_prev_error) / dt;
    pid->prev_prev_error = pid->prev_error;
    pid->prev_error = error;
    return delta;
}

4. STM32代码示例

4.1 主循环或中断服务程序
// 全局变量
PID_Controller motor_pid = {.Kp=2.0, .Ki=0.5, .Kd=0.1};
float setpoint = 100.0;  // 目标值(如转速、温度)

void TIM3_IRQHandler(void) {  // 定时器中断,1kHz频率
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
        float measurement = ADC_ReadMotorSpeed();  // 读取传感器值
        float output = PID_Update(&motor_pid, setpoint, measurement);
        PWM_SetDutyCycle(TIM1, output);  // 更新PWM输出
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    }
}
4.2 ADC读取函数
float ADC_ReadMotorSpeed(void) {
    ADC_SoftwareStartConv(ADC1);
    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    uint16_t raw = ADC_GetConversionValue(ADC1);
    return (raw / 4095.0f) * 3.3f;  // 假设12位ADC,量程0-3.3V
}

5. 参数整定方法

  1. 试凑法

    • 先设 ( Ki=0, Kd=0 ),增大 ( Kp ) 至系统出现振荡,取当前值的50%作为最终 ( Kp )。
    • 逐渐增加 ( Ki ) 以消除稳态误差。
    • 增加 ( Kd ) 抑制超调。
  2. Ziegler-Nichols法

    • 找到临界增益 ( Ku ) 和振荡周期 ( Tu )。
    • 根据下表设置参数:
      控制器类型( Kp )( Ki )( Kd )
      P0.5( Ku )--
      PI0.45( Ku )0.54( Ku/Tu )-
      PID0.6( Ku )1.2( Ku/Tu )0.075( Ku*Tu )

6. 常见问题与优化

  1. 积分饱和(Integral Windup)

    • 在误差较大时暂停积分(如 if (output < MAX) pid->integral += error * dt)。
  2. 噪声抑制

    • 对传感器信号进行低通滤波(如一阶RC滤波)。
    • 使用滑动平均滤波算法。
  3. 实时性要求

    • 使用硬件定时器触发ADC和PID计算。
    • 优化代码,减少中断服务程序中的计算量。
  4. 浮点运算优化

    • 对于低端STM32(无FPU),可使用定点数运算(Q格式)。

7. 调试工具

  • STM32CubeMonitor:实时监控变量(如设定值、反馈值、输出)。
  • 逻辑分析仪:观察PWM波形和传感器信号。
  • 串口打印:输出调试信息(需注意实时性影响)。

通过以上步骤,可以在STM32上实现高效的闭环PID控制。实际应用中需根据具体硬件和动态特性调整参数。

### 双闭环PID控制的工作原理 双闭环PID控制系统通常由外环和内环组成,其中外环负责处理高级目标变量(如位置、速度或压力),而内环则专注于低级物理量的精确控制(如电流或电压)。这种结构能够有效提高系统的动态性能和抗干扰能力。 #### 外环:位置环 PID 控制器 位置环的主要作用是对期望的位置信号进行跟踪并调整误差。其输入为目标位置与实际位置之间的偏差,输出作为内环的目标值。 假设目标位置为 \( r(t) \),实际位置为 \( y(t) \),那么位置误差为: \[ e_p(t) = r(t) - y(t) \] 位置环的 PID 输出可以通过以下公式计算得出[^1]: \[ u_p(t) = K_{pp} e_p(t) + K_{pi} \int_0^t e_p(\tau)d\tau + K_{pd} \frac{de_p(t)}{dt} \] 其中: - \( K_{pp}, K_{pi}, K_{pd} \) 分别表示比例增益、积分时间和微分时间系数。 #### 内环:电流环 PID 控制器 电流环的作用是根据外环提供的目标值调节电机的实际电流,从而达到快速响应的目的。它的输入为外环输出与实际电流之间的差值,输出用于驱动电机。 设目标电流为 \( i_d(t) \),实际电流为 \( i_a(t) \),则电流误差为: \[ e_i(t) = u_p(t) - i_a(t) \] 电流环的 PID 输出可通过以下公式得到: \[ u_i(t) = K_{ip} e_i(t) + K_{ii} \int_0^t e_i(\tau)d\tau + K_{id} \frac{de_i(t)}{dt} \] 最终,\( u_i(t) \) 被送入功率放大电路以驱动电机。 --- ### MATLAB/Simulink 中的实现方法 以下是基于 MATLAB 和 Simulink 的双闭环 PID 控制系统仿真示例代码和模型架构说明。 #### 示例代码 ```matlab % 定义参数 K_pp = 1; % 位置环比例增益 K_pi = 0.5; % 位置环比例积分增益 K_pd = 0.2; % 位置环微分增益 K_ip = 1; % 电流环比例增益 K_ii = 0.5; % 电流环比例积分增益 K_id = 0.2; % 电流环微分增益 % 创建位置环 PID 控制器 position_pid = pid(K_pp, K_pi, K_pd); % 创建电流环 PID 控制器 current_pid = pid(K_ip, K_ii, K_id); % 结合控制器与被控对象 (简化版) plant_position = tf([1], [1, 0]); % 假设位置传递函数 plant_current = tf([1], [1, 0.1, 0]); % 假设电流传递函数 closed_loop_position = feedback(position_pid * plant_position, 1); closed_loop_current = feedback(current_pid * plant_current, 1); % 总体闭环系统 total_system = closed_loop_position * closed_loop_current; step(total_system); % 绘制阶跃响应曲线 grid on; title('双闭环PID控制系统阶跃响应'); xlabel('时间(s)'); ylabel('输出'); ``` 上述代码定义了两个独立的 PID 控制器,并将它们串联起来形成总系统。`tf()` 函数用来描述被控对象的动力学特性,`feedback()` 则实现了闭环连接。 --- ### STM32 单片机上的实现方法 对于嵌入式平台(如 STM32F407),可以采用硬件 PWM 驱动电机并通过编码器反馈实现闭环控制。具体流程如下: 1. **初始化定时器**:配置 TIM2 和 TIM4 生成 PWM 波形。 2. **读取编码器脉冲**:通过外部中断捕获编码器信号,计算当前角度或转速。 3. **执行 PID 计算**:在主循环中调用 PID 算法更新占空比。 4. **发送数据至上位机**:通过 UART 接口传输实时状态信息以便监控。 下面是一段 C 语言伪代码片段展示核心逻辑[^4]: ```c #include "stm32f4xx_hal.h" // 参数声明 float kp_pos = 1.0, ki_pos = 0.5, kd_pos = 0.2; // 位置环 PID 参数 float kp_curr = 1.0, ki_curr = 0.5, kd_curr = 0.2; // 电流环 PID 参数 void PID_Position(float error_pos, float dt, float* output_pos) { static float integral_pos = 0.0, prev_error_pos = 0.0; integral_pos += error_pos * dt; *output_pos = kp_pos * error_pos + ki_pos * integral_pos + kd_pos * ((error_pos - prev_error_pos) / dt); prev_error_pos = error_pos; } void PID_Current(float error_curr, float dt, float* output_curr) { static float integral_curr = 0.0, prev_error_curr = 0.0; integral_curr += error_curr * dt; *output_curr = kp_curr * error_curr + ki_curr * integral_curr + kd_curr * ((error_curr - prev_error_curr) / dt); prev_error_curr = error_curr; } int main(void) { HAL_Init(); SystemClock_Config(); while (1) { float target_angle = ...; // 获取目标角度 float current_angle = ReadEncoder(); // 读取当前位置 float angle_error = target_angle - current_angle; float pos_output; PID_Position(angle_error, 0.01, &pos_output); // 更新位置环输出 float target_current = pos_output; // 使用位置环输出作为电流目标 float actual_current = MeasureCurrent(); // 测量实际电流 float curr_error = target_current - actual_current; float pwm_duty_cycle; PID_Current(curr_error, 0.01, &pwm_duty_cycle); // 更新电流环输出 SetPWM(pwm_duty_cycle); // 设置 PWM 占空比 SendDataToPC(target_angle, current_angle, pwm_duty_cycle); // 发送上位机 } } ``` 此代码框架展示了如何在一个嵌入式平台上实现双闭环 PID 控制。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值