PID制御の理論とチューニング方法を解説

PID制御は、産業界で最も広く使われている制御手法です。比例(P)・積分(I)・微分(D)の3つの要素を組み合わせて制御入力を生成し、速い応答と定常偏差ゼロを同時に実現します。

本記事では、PID制御の理論からチューニング方法、Pythonによるシミュレーションまでを解説します。

本記事の内容

  • PID制御の基本原理とP・I・D各要素の役割
  • PID制御の伝達関数表現
  • ジーグラ・ニコルス法によるチューニング
  • Pythonでのシミュレーション

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

PID制御とは

PID制御器は、偏差 $e(t) = r(t) – y(t)$ に対して次の制御入力を出力します。

$$ \begin{equation} u(t) = K_p e(t) + K_i \int_0^t e(\tau) d\tau + K_d \frac{de(t)}{dt} \end{equation} $$

各項の役割は以下の通りです。

要素 役割
P(比例) $K_p e(t)$ 現在の偏差に比例した制御。応答速度を決める
I(積分) $K_i \int_0^t e(\tau) d\tau$ 過去の偏差の蓄積。定常偏差を除去する
D(微分) $K_d \frac{de(t)}{dt}$ 偏差の変化率。オーバーシュートを抑制する

伝達関数表現

PID制御器のラプラス変換は

$$ C(s) = K_p + \frac{K_i}{s} + K_d s $$

これを整理すると

$$ \begin{equation} C(s) = K_p \left(1 + \frac{1}{T_i s} + T_d s\right) \end{equation} $$

ここで $T_i = \frac{K_p}{K_i}$(積分時間)、$T_d = \frac{K_d}{K_p}$(微分時間)です。

各要素の効果

P制御(比例制御)

$$ u(t) = K_p e(t) $$

$K_p$ を大きくすると応答が速くなりますが、定常偏差が残ります。1次遅れ系 $P(s) = \frac{1}{s+1}$ に対する定常偏差は

$$ e_{ss} = \frac{1}{1 + K_p} $$

PI制御(比例+積分制御)

$$ u(t) = K_p e(t) + K_i \int_0^t e(\tau) d\tau $$

積分項により定常偏差がゼロになります。ただし、積分項は応答を遅くし、オーバーシュートを大きくする傾向があります。

積分項が定常偏差を除去する理由を考えましょう。定常状態で $u(\infty) = \text{const}$ ならば $\frac{du}{dt} = 0$ です。積分項の時間微分は $K_i e(t)$ なので、定常状態では必ず $e(\infty) = 0$ となります。

PID制御

微分項を加えることで、偏差が大きくなりそうな傾向を事前に検知して制動をかけます。これにより、PI制御のオーバーシュートを抑制しつつ、定常偏差ゼロを維持できます。

ジーグラ・ニコルス法

PIDパラメータのチューニング方法として代表的なのがジーグラ・ニコルス法(Ziegler-Nichols法)です。

ステップ応答法

プラントのステップ応答から、むだ時間 $L$ と時定数 $T$ を読み取ります。プラントを次のモデルで近似します。

$$ P(s) \approx \frac{K}{Ts + 1} e^{-Ls} $$

制御器 $K_p$ $T_i$ $T_d$
P $\frac{T}{KL}$ $\infty$ 0
PI $\frac{0.9T}{KL}$ $\frac{L}{0.3}$ 0
PID $\frac{1.2T}{KL}$ $2L$ $0.5L$

限界感度法

  1. P制御のみで、$K_p$ を徐々に大きくする
  2. 出力が持続振動を始めたときのゲインを限界ゲイン $K_u$ とする
  3. 持続振動の周期を限界周期 $T_u$ とする
制御器 $K_p$ $T_i$ $T_d$
P $0.5 K_u$ $\infty$ 0
PI $0.45 K_u$ $\frac{T_u}{1.2}$ 0
PID $0.6 K_u$ $\frac{T_u}{2}$ $\frac{T_u}{8}$

Pythonでの実装

P・PI・PID制御の比較

import numpy as np
import matplotlib.pyplot as plt
import control as ctrl

# プラント: P(s) = 1 / (s^2 + s + 1)
P = ctrl.tf([1], [1, 1, 1])

# P制御: C(s) = Kp
Kp = 10
C_p = ctrl.tf([Kp], [1])

# PI制御: C(s) = Kp + Ki/s = (Kp*s + Ki) / s
Ki = 5
C_pi = ctrl.tf([Kp, Ki], [1, 0])

# PID制御: C(s) = Kp + Ki/s + Kd*s = (Kd*s^2 + Kp*s + Ki) / s
Kd = 3
C_pid = ctrl.tf([Kd, Kp, Ki], [1, 0])

controllers = [C_p, C_pi, C_pid]
labels = ['P Control', 'PI Control', 'PID Control']

plt.figure(figsize=(10, 6))
t = np.linspace(0, 15, 1000)

for C, label in zip(controllers, labels):
    G = ctrl.feedback(P * C, 1)
    t_out, y_out = ctrl.step_response(G, T=t)
    plt.plot(t_out, y_out, label=label, linewidth=2)

plt.axhline(y=1.0, color='k', linestyle='--', alpha=0.3, label='Target')
plt.xlabel('Time [s]')
plt.ylabel('Output y(t)')
plt.title('Comparison of P, PI, PID Control')
plt.legend()
plt.grid(True, alpha=0.3)
plt.xlim([0, 15])
plt.tight_layout()
plt.show()

P制御では定常偏差が残り、PI制御では定常偏差はゼロになりますがオーバーシュートが大きくなります。PID制御では微分項によりオーバーシュートが抑制されます。

ジーグラ・ニコルス法のシミュレーション

import numpy as np
import matplotlib.pyplot as plt
import control as ctrl

# プラント: 1次遅れ+むだ時間
# P(s) = exp(-Ls) / (Ts + 1) をPade近似で表現
K_plant = 1.0
T_plant = 1.0
L = 0.3

# むだ時間のPade近似(2次)
num_pade, den_pade = ctrl.pade(L, 2)
P_delay = ctrl.tf(num_pade, den_pade)
P_plant = ctrl.tf([K_plant], [T_plant, 1])
P = P_plant * P_delay

# ジーグラ・ニコルス法(ステップ応答法)
Kp_zn = 1.2 * T_plant / (K_plant * L)
Ti_zn = 2 * L
Td_zn = 0.5 * L
Ki_zn = Kp_zn / Ti_zn
Kd_zn = Kp_zn * Td_zn

print(f'Ziegler-Nichols PID: Kp={Kp_zn:.2f}, Ki={Ki_zn:.2f}, Kd={Kd_zn:.2f}')

# PIDコントローラ
C_zn = ctrl.tf([Kd_zn, Kp_zn, Ki_zn], [1, 0])
G_zn = ctrl.feedback(P * C_zn, 1)

# 手動チューニング(比較用)
Kp_man, Ki_man, Kd_man = 3.0, 3.0, 0.5
C_man = ctrl.tf([Kd_man, Kp_man, Ki_man], [1, 0])
G_man = ctrl.feedback(P * C_man, 1)

t = np.linspace(0, 10, 1000)
plt.figure(figsize=(10, 6))

t1, y1 = ctrl.step_response(G_zn, T=t)
t2, y2 = ctrl.step_response(G_man, T=t)

plt.plot(t1, y1, label='Ziegler-Nichols', linewidth=2)
plt.plot(t2, y2, label='Manual Tuning', linewidth=2)
plt.axhline(y=1.0, color='k', linestyle='--', alpha=0.3)
plt.xlabel('Time [s]')
plt.ylabel('Output y(t)')
plt.title('PID Tuning: Ziegler-Nichols vs Manual')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

まとめ

本記事では、PID制御の理論とチューニング方法について解説しました。

  • PID制御は比例(P)・積分(I)・微分(D)の3要素を組み合わせた制御手法
  • P制御は応答速度を向上させ、I制御は定常偏差を除去し、D制御はオーバーシュートを抑制する
  • 伝達関数表現は $C(s) = K_p + K_i/s + K_d s$
  • ジーグラ・ニコルス法はプラントのステップ応答や限界感度から系統的にパラメータを決定する

次のステップとして、以下の記事も参考にしてください。