PID小白自学笔记(1)理论基础

        PID是“比例-积分-微分控制器”(Proportional-Integral-Derivative Controller)的缩写,是一种广泛应用于工业控制系统的反馈控制技术。PID控制器通过计算当前误差(目标值与实际值之间的差异)来调整控制输出,以使系统达到并保持在设定的目标值。下面我将详细解释PID的三个组成部分及其工作原理。

1. 比例(P)控制

        定义:比例控制是根据当前误差的大小来调整控制输出的部分。
        工作原理:当误差(目标值与实际值之间的差)增大时,比例控制会提供一个与误差成正比例的输出。这意味着,误差越大,控制输出的调整就越大。

        公式:P_{\text{output}} = K_p \times e(t)

  其中:
   K_p是比例增益(一个常数,用于调节比例控制的强弱)。
   e(t)是当前的误差。

 优点:快速响应。
 缺点:可能会导致稳态误差(即系统在稳定状态时仍然与目标值存在差异)。

2. 积分(I)控制

        定义:积分控制是根据过去的误差累积来调整控制输出的部分。
        工作原理:积分作用使得控制器关注系统长时间的误差。通过对误差的累积(积分),可以消除稳态误差。这意味着即使是小的持续误差,积分控制也会逐步增加控制输出,直到误差消失。

        公式:I_{\text{output}} = K_i \times \int e(t) \, dt

  其中:
   K_i是积分增益。
  \int e(t) \, dt是误差随时间的积分(累积)。

        优点:消除稳态误差。
        缺点:可能导致系统过冲(超过目标值)和振荡,尤其在增益设置不当时。

        在离散系统中,积分被替换为离散时间步长的累加,用矩形法(或梯形法)近似:           I(k) \approx K_i \sum_{i=0}^{k} e(i) \cdot T_s。为了避免每次都计算整个历史累加(计算量大),通常采用递推形式,即只基于上一次的结果更新: I(k) = I(k-1) + K_i \cdot e(k) \cdot T_s

3. 微分(D)控制

        定义:微分控制是根据误差变化率来调整控制输出的部分。
        工作原理:微分作用预测误差的未来趋势。它通过观察误差的变化速度来提供一个快速的反应,以减小系统的过冲和振荡。

       公式:D_{\text{output}} = K_d \times \frac{de(t)}{dt}

  其中:
          K_d是微分增益。
         \frac{de(t)}{dt}是误差的变化率。

        优点:提高系统的稳定性,减少振荡。
        缺点:对噪声敏感,可能导致控制不稳定。

        在离散系统中,时间以采样点k表示,导数通过前后两个采样点的误差差值近似:\frac{de(t)}{dt} \approx \frac{e(k) - e(k-1)}{T_s} 。因此,离散微分项D(k)可表示为: D(k) = K_d \cdot \frac{e(k) - e(k-1)}{T_s},当前时刻的误差。 e(k-1):前一时刻的误差。 T_s:采样周期。K_d:微分增益,控制微分项的强度。 这是一种向后差分法(Backward Difference),是最简单的离散微分近似。

4. PID 控制器的综合输出

        将三部分结合在一起,PID控制器的输出可以表示为:

        u(t) = P_{\text{output}} + I_{\text{output}} + D_{\text{output}}

        其中,u(t) 是控制器的最终输出。通过调整K_pK_i 和K_d 的值,可以优化控制器的性能,以适应特定的系统需求。

        唉,实际上人生也可以看作一个动态调节的过程,通过实时反馈(P)、经验积累(I)和趋势预测(D)来调整自己的行为,以实现目标。就比如考研,模拟考英语只有40分(目标70分),偏差30分。应该立刻调整策略,每天多背50个单词、做两篇阅读理解,而不是盲目增加其他科目时间。P项的特点是快速反应,但若过于依赖“当下”(比如只顾眼前的分数而忽略长期规划),可能导致复习不全面。而我当时没有这个简单的觉悟。

       示例代码:

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.size'] = 12
plt.rcParams['axes.linewidth'] = 1.5
plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['ytick.direction'] = 'in'
plt.rcParams['lines.linewidth'] = 2.0

class PIDController:
    def __init__(self, Kp, Ki, Kd, setpoint):
        self.Kp = Kp
        self.Ki = Ki
        self.Kd = Kd
        self.setpoint = setpoint
        self.integral = 0
        self.prev_error = 0

    def compute(self, pv, dt):
        error = self.setpoint - pv
        P = self.Kp * error
        self.integral += error * dt
        I = self.Ki * self.integral
        derivative = (error - self.prev_error) / dt
        D = self.Kd * derivative
        output = P + I + D
        self.prev_error = error
        return output

def system_model(pv, control_signal, dt, tau=1.0):
    dpv_dt = (-pv + control_signal) / tau
    pv_next = pv + dpv_dt * dt
    return pv_next

dt = 0.1
time = np.arange(0, 100, dt)
setpoint = 10.0
pv = 0.0
control_signals = []
pvs = []

Kp = 1.0
Ki = 0.1
Kd = 0.05
pid = PIDController(Kp, Ki, Kd, setpoint)

for t in time:
    control_signal = pid.compute(pv, dt)
    pv = system_model(pv, control_signal, dt)
    control_signals.append(control_signal)
    pvs.append(pv)

fig = plt.figure(figsize=(10, 8), facecolor='#F5F5F5')
fig.suptitle('PID 控制器仿真', fontsize=16, fontweight='bold', y=0.95)

ax1 = plt.subplot(2, 1, 1)
ax1.plot(time, pvs, label='过程值 (PV)', color='#1F77B4', linewidth=2.5)
ax1.plot(time, [setpoint] * len(time), '--', label='设定值 (SP)', color='#FF7F0E', linewidth=2)
ax1.set_ylabel('值', fontsize=12)
ax1.set_title('过程值与设定值', fontsize=14, pad=10)
ax1.grid(True, linestyle='--', alpha=0.6, color='gray')
ax1.set_facecolor('#FFFFFF')
ax1.legend(loc='upper right', fontsize=10, frameon=True, edgecolor='black')
ax1.spines['top'].set_visible(False)
ax1.spines['right'].set_visible(False)

ax2 = plt.subplot(2, 1, 2)
ax2.plot(time, control_signals, label='控制信号', color='#2CA02C', linewidth=2.5)
ax2.set_xlabel('时间 (秒)', fontsize=12)
ax2.set_ylabel('控制信号', fontsize=12)
ax2.set_title('控制信号输出', fontsize=14, pad=10)
ax2.grid(True, linestyle='--', alpha=0.6, color='gray')
ax2.set_facecolor('#FFFFFF')
ax2.legend(loc='upper right', fontsize=10, frameon=True, edgecolor='black')
ax2.spines['top'].set_visible(False)
ax2.spines['right'].set_visible(False)

plt.tight_layout(rect=[0, 0, 1, 0.92])
plt.show()

    

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值