diff --git a/packages/agebd/src/agebd/pid.py b/packages/agebd/src/agebd/pid.py new file mode 100644 index 0000000..cb07d14 --- /dev/null +++ b/packages/agebd/src/agebd/pid.py @@ -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 diff --git a/services/tunefbx/current/app/src/agebd_tunefbx/service.py b/services/tunefbx/current/app/src/agebd_tunefbx/service.py index f0a64a7..5a46445 100644 --- a/services/tunefbx/current/app/src/agebd_tunefbx/service.py +++ b/services/tunefbx/current/app/src/agebd_tunefbx/service.py @@ -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, diff --git a/services/tunefby/current/app/src/agebd_tunefby/service.py b/services/tunefby/current/app/src/agebd_tunefby/service.py index 24650b0..23de03d 100644 --- a/services/tunefby/current/app/src/agebd_tunefby/service.py +++ b/services/tunefby/current/app/src/agebd_tunefby/service.py @@ -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,