PID Control
실행 준비
Python 경로는 python-control을 사용합니다. 모듈이 없으면 Colab·Jupyter의 코드 셀에서 %pip install control==0.10.2를 실행하세요.
학습 목표
빠른 응답만 보고 Gain을 고르면 Overshoot나 모델 변화에 취약할 수 있습니다. 서로 다른 성능 지표를 비교합니다.
P·PI·PID 기준 비교
시작 조건
Motor는 ,,,,. P=(500,0,0), PI=(500,300,0), PID=(500,300,30)입니다.
진행 방법
- 음의 단위 Feedback으로 세 Closed-loop 모델을 만드세요.
- s의 Unit Step을 같은 그림에 표시하고 Pole을 먼저 확인하세요.
- 안정한 모델에 대해 Overshoot·Settling Time·Steady-State Error를 기록하세요.
남길 결과
- 제어기 3행의 표와 응답 그림, 역할 비교 짧은 설명.
import numpy as np
import matplotlib.pyplot as plt
import control as ctl
s = ctl.tf('s')
G=.01/((.01*s+.1)*(.5*s+1)+.01**2)
configs={'P':(500,0,0),'PI':(500,300,0),'PID':(500,300,30)}
for name,(kp,ki,kd) in configs.items():
C=kp+ki/s+kd*s
T=ctl.feedback(C*G,1)
print(name,ctl.poles(T))
# TODO: 응답과 성능 지표를 기록하세요.
결과 기록·자가 점검
제어기:
Kp:
Ki:
Kd:
안정 여부:
Overshoot [%]:
Settling Time [s]:
Steady-State Error:
확인할 점
- 제어기 이외의 Plant·입력·시간축은 같은가?
- 불안정하거나 수렴이 끝나지 않은 경우 지표 대신 사유를 적었는가?
한 항씩 변화시키기
시작 조건
PID 기준 (500,300,30)에서 Kp만 250,500,750으로 바꿉니다. Ki·Kd는 고정합니다.
진행 방법
- 활동 1의 PID 결과를 기준으로 두고 만 250과 750으로 각각 바꾸세요. , , Plant와 시간축은 유지하세요.
- 두 설정의 Unit Step을 기준 곡선과 같은 그림에 표시하세요. 같은
ctl.step_info설정으로 구한 Overshoot·Settling Time·Steady-State Error를 활동 1과 같은 열로 기록하세요. - 두 추가 설정 중 하나를 선택하고, 기준값보다 개선하려는 지표와 허용하려는 변화를 표의 값으로 설명하세요.
남길 결과
- 두 설정의 응답 그림과 지표 표. 선택 이유 한 문장.
import numpy as np
import matplotlib.pyplot as plt
import control as ctl
s = ctl.tf('s')
G=.01/((.01*s+.1)*(.5*s+1)+.01**2)
for kp in [250,500,750]:
T=ctl.feedback((kp+300/s+30*s)*G,1)
print(kp,ctl.dcgain(T))
# TODO: 시간응답과 두 번째 Gain 비교를 완성하세요.
결과 기록·자가 점검
변경 항:
값:
Overshoot [%]:
Settling Time [s]:
Steady-State Error:
확인할 점
- 한 번에 한 Gain만 바꾸었는가?
- 빠르다는 평가를 구체적인 지표로 설명했는가?
입력 한계와 적분 누적
시작 조건
1차 Plant , 목표 2→.5(5초에 변경), , dt=.01 s입니다. , 입니다.
진행 방법
- 제공된 PI 시뮬레이션에서 실제 입력과 제한 전 입력을 함께 그리세요.
- conditional integration을 켠 경우와 끈 경우를 비교하세요.
- 목표를 낮춘 뒤 오차가 오래 남는 이유를 적분 상태와 연결해 설명하세요.
남길 결과
- 출력·입력·적분 상태의 세 그래프와 비교 표.
비교 표의 IAE는 목표 변경 시각부터 마지막 기록 시각까지의 입니다. 입력 포화 지속 시간은 전체 기록에서 제한된 가 0 또는 1인 표본 수에 dt를 곱해 구하세요.
두 적분 처리 방식에 같은 구간과 계산법을 사용합니다.
import numpy as np
import matplotlib.pyplot as plt
def simulate(antiwindup):
t=np.arange(0,12,.01);y=0.;integral=0.;rows=[]
for now in t:
ref=2. if now<5 else .5;e=ref-y;raw=2*e+integral;u=np.clip(raw,0,1)
if not antiwindup or (0<raw<1) or (raw>=1 and e<0) or (raw<=0 and e>0):integral+=e*.01
y+=(-y+u)*.01;rows.append((ref,y,raw,u,integral))
return t,np.array(rows)
for flag in [False,True]:
time,trace=simulate(flag);plt.plot(time,trace[:,1],label=str(flag))
plt.xlabel('Time [s]');plt.ylabel('Output');plt.legend()
# TODO: 입력·적분 상태와 5초 이후의 지표를 추가하세요.
결과 기록·자가 점검
적분 처리:
목표 변경 후 IAE:
최대 적분값:
입력 포화 지속 시간 [s]:
확인할 점
- 입력 제한을 적용하기 전후 값을 구분했는가?
- PI Gain까지 바꾸지 않고 적분 처리 방식만 비교했는가?