Last active
October 14, 2024 13:13
-
-
Save damp11113/ba4ce2f147d9e405628988b69ccd3bd4 to your computer and use it in GitHub Desktop.
a PID control with simulation and output to plot (with animation)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import matplotlib.pyplot as plt | |
import time | |
class PIDController: | |
def __init__(self, kp, ki, kd, setpoint, output_limits=(None, None)): | |
self.kp = kp | |
self.ki = ki | |
self.kd = kd | |
self.setpoint = setpoint | |
self.output_limits = output_limits | |
self._prev_error = 0 | |
self._integral = 0 | |
self._last_time = None | |
def update(self, feedback_value, current_time): | |
error = self.setpoint - feedback_value | |
if self._last_time is None: | |
self._last_time = current_time | |
delta_time = 0 | |
else: | |
delta_time = current_time - self._last_time | |
self._last_time = current_time | |
p_term = self.kp * error | |
self._integral += error * delta_time | |
i_term = self.ki * self._integral | |
delta_error = error - self._prev_error | |
d_term = self.kd * (delta_error / delta_time) if delta_time > 0 else 0 | |
output = p_term + i_term + d_term | |
if self.output_limits[0] is not None: | |
output = max(self.output_limits[0], output) | |
if self.output_limits[1] is not None: | |
output = min(self.output_limits[1], output) | |
self._prev_error = error | |
return output | |
# PID controller settings | |
pid = PIDController(kp=1, ki=0, kd=0, setpoint=1000) | |
# Simulation settings | |
feedback = 0 | |
time_values = [] | |
feedback_values = [] | |
control_signals = [] | |
setpoint_values = [] | |
start_time = time.time() | |
# Initialize the plot | |
plt.ion() # Enable interactive mode | |
fig, ax = plt.subplots(figsize=(10, 6)) | |
for _ in range(200): | |
current_time = time.time() - start_time | |
control_signal = pid.update(feedback, current_time) | |
# Update feedback for next loop (simulate process) | |
feedback += control_signal * 0.1 | |
# Store data for plotting | |
time_values.append(current_time) | |
feedback_values.append(feedback) | |
control_signals.append(control_signal) | |
setpoint_values.append(pid.setpoint) | |
# Clear and update the plot in real-time | |
ax.clear() | |
ax.plot(time_values, setpoint_values, label="Setpoint", linestyle="--") | |
ax.plot(time_values, feedback_values, label="Feedback") | |
ax.plot(time_values, control_signals, label="Control Signal", linestyle=":") | |
ax.set_title("PID Controller Simulation (Real-Time)") | |
ax.set_xlabel("Time (s)") | |
ax.set_ylabel("Value") | |
ax.legend() | |
ax.grid(True) | |
# Pause to allow plot to update | |
plt.pause(0.01) | |
# Slow down the simulation for visualization purposes | |
#time.sleep(0.01) | |
plt.ioff() # Disable interactive mode when done | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment