This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
class PID:
|
||||
# Proportional-Integral-Derivative (PID) controller class
|
||||
# PID setup procedure:
|
||||
# 1. set integral and derivative gains ki, kd to 0
|
||||
# 2. set proportional gain kp to low, stable value
|
||||
# 3. increase kp and create a disturbance, e.g., by changing the setpoint
|
||||
# 4. increase kp until feedback parameter oscillates
|
||||
# 5. set kp to 40 % of the critical value triggering oscillation
|
||||
# 6. slowly increase ki to eliminate the steady state error
|
||||
# 7. adjust it until setpoint is reached accurately without overshoot
|
||||
# 8. tune kd to minimize oscillations and overshoots (caution: high kd can amplify noise)
|
||||
|
||||
def __init__(self, kp, ki, kd, setpoint):
|
||||
|
||||
# Proportional Gain >> The "present" term. It provides a response proportional to the current error. Increasing kp makes the system respond faster, but if pushed too high, it will cause violent overshoot and oscillation.
|
||||
self.kp = kp
|
||||
# Integral Gain >> The "past" term. It accumulates the errors over time to eliminate steady-state error. However, high ki values can cause sluggishness or instability (e.g., integral windup).
|
||||
self.ki = ki
|
||||
# Derivative Gain >> The "future" term. It measures the rate of change of the error, acting as a damping factor to reduce overshoot and smooth out rapid, unwanted movements
|
||||
self.kd = kd
|
||||
self.setpoint = setpoint
|
||||
self.integral = 0
|
||||
self.prev_error = 0
|
||||
|
||||
def update(self, measurement, dt):
|
||||
|
||||
error = self.setpoint - measurement
|
||||
self.integral += error * dt
|
||||
derivative = (error - self.prev_error) / dt if dt > 0 else 0
|
||||
|
||||
self.prev_error = error
|
||||
|
||||
# Calculate the final output using Kp, Ki, and Kd which is written to actuator
|
||||
output = (self.kp * error) + (self.ki * self.integral) + (self.kd * derivative)
|
||||
|
||||
return output
|
||||
@@ -3,6 +3,7 @@ from time import perf_counter
|
||||
import numpy as np
|
||||
from epics import dbr
|
||||
|
||||
from agebd.pid import PID
|
||||
from agebd.pv import get_pv_class, get_pv_external_class
|
||||
from agebd.service.base import BaseService
|
||||
from agebd.service.pvs import BasePVs
|
||||
@@ -59,44 +60,6 @@ class PVs(BasePVs):
|
||||
self.CallbackPV = PV_EXTERNAL("AGEBD-TUNEBUMP:QX.VAL", auto_monitor=dbr.DBE_VALUE)
|
||||
|
||||
|
||||
class PID:
|
||||
# Proportional-Integral-Derivative (PID) controller class
|
||||
# PID setup procedure:
|
||||
# 1. set integral and derivative gains ki, kd to 0
|
||||
# 2. set proportional gain kp to low, stable value
|
||||
# 3. increase kp and create a disturbance, e.g., by changing the setpoint
|
||||
# 4. increase kp until feedback parameter oscillates
|
||||
# 5. set kp to 40 % of the critical value triggering oscillation
|
||||
# 6. slowly increase ki to eliminate the steady state error
|
||||
# 7. adjust it until setpoint is reached accurately without overshoot
|
||||
# 8. tune kd to minimize oscillations and overshoots (caution: high kd can amplify noise)
|
||||
|
||||
def __init__(self, kp, ki, kd, setpoint):
|
||||
|
||||
# Proportional Gain >> The "present" term. It provides a response proportional to the current error. Increasing kp makes the system respond faster, but if pushed too high, it will cause violent overshoot and oscillation.
|
||||
self.kp = kp
|
||||
# Integral Gain >> The "past" term. It accumulates the errors over time to eliminate steady-state error. However, high ki values can cause sluggishness or instability (e.g., integral windup).
|
||||
self.ki = ki
|
||||
# Derivative Gain >> The "future" term. It measures the rate of change of the error, acting as a damping factor to reduce overshoot and smooth out rapid, unwanted movements
|
||||
self.kd = kd
|
||||
self.setpoint = setpoint
|
||||
self.integral = 0
|
||||
self.prev_error = 0
|
||||
|
||||
def update(self, measurement, dt):
|
||||
|
||||
error = self.setpoint - measurement
|
||||
self.integral += error * dt
|
||||
derivative = (error - self.prev_error) / dt if dt > 0 else 0
|
||||
|
||||
self.prev_error = error
|
||||
|
||||
# Calculate the final output using Kp, Ki, and Kd which is written to actuator
|
||||
output = (self.kp * error) + (self.ki * self.integral) + (self.kd * derivative)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
class Service(BaseService[PVs]):
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
@@ -3,6 +3,7 @@ from time import perf_counter
|
||||
import numpy as np
|
||||
from epics import dbr
|
||||
|
||||
from agebd.pid import PID
|
||||
from agebd.pv import get_pv_class, get_pv_external_class
|
||||
from agebd.service.base import BaseService
|
||||
from agebd.service.pvs import BasePVs
|
||||
@@ -59,44 +60,6 @@ class PVs(BasePVs):
|
||||
self.CallbackPV = PV_EXTERNAL("AGEBD-TUNEBUMP:QY.VAL", auto_monitor=dbr.DBE_VALUE)
|
||||
|
||||
|
||||
class PID:
|
||||
# Proportional-Integral-Derivative (PID) controller class
|
||||
# PID setup procedure:
|
||||
# 1. set integral and derivative gains ki, kd to 0
|
||||
# 2. set proportional gain kp to low, stable value
|
||||
# 3. increase kp and create a disturbance, e.g., by changing the setpoint
|
||||
# 4. increase kp until feedback parameter oscillates
|
||||
# 5. set kp to 40 % of the critical value triggering oscillation
|
||||
# 6. slowly increase ki to eliminate the steady state error
|
||||
# 7. adjust it until setpoint is reached accurately without overshoot
|
||||
# 8. tune kd to minimize oscillations and overshoots (caution: high kd can amplify noise)
|
||||
|
||||
def __init__(self, kp, ki, kd, setpoint):
|
||||
|
||||
# Proportional Gain >> The "present" term. It provides a response proportional to the current error. Increasing kp makes the system respond faster, but if pushed too high, it will cause violent overshoot and oscillation.
|
||||
self.kp = kp
|
||||
# Integral Gain >> The "past" term. It accumulates the errors over time to eliminate steady-state error. However, high ki values can cause sluggishness or instability (e.g., integral windup).
|
||||
self.ki = ki
|
||||
# Derivative Gain >> The "future" term. It measures the rate of change of the error, acting as a damping factor to reduce overshoot and smooth out rapid, unwanted movements
|
||||
self.kd = kd
|
||||
self.setpoint = setpoint
|
||||
self.integral = 0
|
||||
self.prev_error = 0
|
||||
|
||||
def update(self, measurement, dt):
|
||||
|
||||
error = self.setpoint - measurement
|
||||
self.integral += error * dt
|
||||
derivative = (error - self.prev_error) / dt if dt > 0 else 0
|
||||
|
||||
self.prev_error = error
|
||||
|
||||
# Calculate the final output using Kp, Ki, and Kd which is written to actuator
|
||||
output = (self.kp * error) + (self.ki * self.integral) + (self.kd * derivative)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
class Service(BaseService[PVs]):
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user