Contents

PID Controller

Contents

Proportional-integral-derivative controller is the classical control strategy. In this blog, I use python to write a primitive PID controller.

PID Control

import time
import matplotlib.pyplot as plt
from scipy.interpolate import make_interp_spline
import numpy as np

class PID:
    def __init__(self, P=0.2, I=0.0, D=0.0, current_time=None):
        self.Kp = P
        self.Ki = I
        self.Kd = D

        self.current_time = current_time if current_time is not None else time.time()
        self.last_time = self.current_time
        self.ControlPoint = 0.0
        self.last_error = 0.0
        self.PTerm = 0.0
        self.ITerm = 0.0
        self.DTerm = 0.0
        self.windup_guard = 20.0

    def step(self, feedback_value, current_time=None):
        error = self.ControlPoint - feedback_value
        delta_error = error - self.last_error
        self.current_time = current_time if current_time is not None else time.time()
        delta_time = self.current_time - self.last_time

        if (delta_time >= 0):
            self.PTerm = self.Kp * error
            self.ITerm += error * delta_time
            if delta_time > 0:
                self.DTerm = delta_error / delta_time
            self.last_time = self.current_time
            self.last_error = error
            self.output = self.PTerm + (self.Ki * self.ITerm) + (self.Kd * self.DTerm)
t0 = 9
t_end = 50
pid = PID(1.2, 1.0, 0.001)

feedback = 0
feedback_list = []
time_list = []
controlpoint_list = []

for t in range(1, t_end):
    pid.step(feedback)
    output = pid.output
    if pid.ControlPoint > 0:
        feedback += output
    if t > t0:
        pid.ControlPoint = 1/t
    time.sleep(0.02)
    feedback_list.append(feedback)
    controlpoint_list.append(pid.ControlPoint)
    time_list.append(t)

time_index = np.array(time_list)
time_smooth = np.linspace(time_index.min(), time_index.max(), 300)
spline = make_interp_spline(time_list, feedback_list)
feedback_smooth = spline(time_smooth)

plt.plot(time_smooth, feedback_smooth)
plt.plot(time_list, controlpoint_list)
plt.xlim((0, t_end))
plt.xlabel('time (s)')
plt.savefig('/Users/jiawei/Documents/roam/note/images/pid.png')