Annotated PID Controller in SWMM5 and InfoSWMM

How does a PID controller work in  InfoSWMM  and SWMMM 5 - this also applies to H2OMap SWMM??
double getPIDSetting(struct TAction* a, double dt)   //  at each time  step find  the PID control  changes for the  current  time step dt
// Input: a = an action object
// dt = current time step (days)
// Output: returns a new link setting
// Purpose: computes a new setting for a link subject to a PID controller.
pid1
// Note: a->kp = gain coefficient,
// a->ki = integral time (minutes)
// a->k2 = derivative time (minutes)
// a->e1 = error from previous time step
// a->e2 = error from two time steps ago
{
double e0, setting;
double p, i, d, update;
double tolerance = 0.0001;
// --- convert time step from days to minutes
dt *= 1440.0;
// --- determine relative error in achieving controller set point
// Or how close are we to the set point?
PID2
e0 = SetPoint - ControlValue;
if ( fabs(e0) > TINY )
{
if ( SetPoint != 0.0 ) e0 = e0/SetPoint;
// now alter the  value of e0
PID3
else e0 = e0/ControlValue;
}
// --- reset previous errors to 0 if controller gets stuck
if (fabs(e0 - a->e1) < tolerance)
{
a->e2 = 0.0;
a->e1 = 0.0;
}
// --- use the recursive form of the PID controller equation to
// determine the new setting for the controlled link
Here is a view of the p, i and d PID internal  parameters https://www.wikiwand.com/en/PID_controller
A block diagram of a PID controller in a feedback loop
A block diagram of a PID controller in a feedback loop
p = (e0 - a->e1);
pid5
ki, id,  kp are  user  inputs  in InfoSWMM and SWMM5 or from the  EPA SWMM  5 Help  File2016-05-16_0548.png
if ( a->ki == 0.0 ) i = 0.0;
else i = e0 * dt / a->ki;
pd8.png
d = a->kd * (e0 - 2.0*a->e1 + a->e2) / dt;
pid9
update = a->kp * (p + i + d);
if ( fabs(update) < tolerance ) update = 0.0;
setting = Link[a->link].targetSetting + update;
pid7
// --- update previous errors
a->e2 = a->e1;
a->e1 = e0;
// --- check that new setting lies within feasible limits
// If  the link  is not a pump then the  setting must be between 0 and 1
if ( setting < 0.0 ) setting = 0.0;
if (Link[a->link].type != PUMP && setting > 1.0 ) setting = 1.0;
return setting;}

Comments

Popular posts from this blog

Orifice and Weir flow calculations

SWMM 5 Error Messages

EMC Washoff in SWMM5