#*------------------------------------------------------------------- * EMSO Model Library (EML) Copyright (C) 2004 - 2007 ALSOC. * * This LIBRARY is free software; you can distribute it and/or modify * it under the therms of the ALSOC FREE LICENSE as available at * http://www.enq.ufrgs.br/alsoc. * * EMSO Copyright (C) 2004 - 2007 ALSOC, original code * from http://www.rps.eng.br Copyright (C) 2002-2004. * All rights reserved. * * EMSO is distributed under the therms of the ALSOC LICENSE as * available at http://www.enq.ufrgs.br/alsoc. *-------------------------------------------------------------------- * Author: Tiago Osório * $Id: PIDIncr.mso 909 2010-02-19 21:08:11Z arge $ *-------------------------------------------------------------------*# using "types"; Model PIDIncr ATTRIBUTES Pallete = true; Icon = "icon/PIDincr"; Brief = "Model of incremental PIDs."; Info = "== Inputs == * scaled processs variable. * scaled bias. * scaled setpoint. == Outputs == * a scaled output. "; PARAMETERS PID_Select as Switcher (Brief="Type of PID Incremental", Valid=["Ideal","Parallel","Series","Ideal_AWBT","Parallel_AWBT","Series_AWBT","Ideal_AW","Parallel_AW","Series_AW"], Default = "Ideal"); Action as Switcher (Brief="Controller action", Valid=["Direct","Reverse"], Default = "Reverse"); Mode as Switcher (Brief="Controller mode", Valid=["Automatic","Manual"], Default = "Automatic"); Clip as Switcher (Brief="Controller mode", Valid=["Clipped","Unclipped"], Default = "Clipped"); alpha as positive (Brief="Derivative term filter constant", Default=1); beta as positive (Brief="Proportional term setPoint change filter"); bias as control_signal (Brief="Previous scaled bias", Default=0.5); derivTime as time_sec (Brief="Derivative time constant"); intTime as time_sec (Brief="Integral time constant"); gain as positive (Brief="Controller gain", Default=0.5); gamma as positive (Brief="Derivative term SP change filter"); tau as time_sec (Brief="Input filter time constant"); tauSet as time_sec (Brief="Input filter time constant"); MinInput as control_signal (Default=0); MaxInput as control_signal (Default=1000); MinOutput as control_signal (Default=0); MaxOutput as control_signal (Default=1); VARIABLES in Input as control_signal (Protected=true, PosX=0, PosY=0.5); out Output as control_signal (Protected=true, PosX=0.54, PosY=1); SetPoint as control_signal; #++++++++++++++++++++ PID Internal Variables ++++++++++++++++++++++++++++++++ PID_dderivTerm as control_signal (Brief="Derivative term",Unit='1/s', Default=0, Hidden=true); PID_dFilt as control_signal (Brief="Derivative term filtered", Default=0.5,Unit='1/s', Hidden=true); PID_error as control_signal (Brief="Error definition for proportional term",Unit='1/s', Hidden=true); PID_errorD as control_signal (Brief="Error definition for derivative term",Unit='1/s', Hidden=true); PID_errorI as control_signal (Brief="Error definition for integral term", Hidden=true); PID_inputFilt as control_signal (Brief="Filtered input", Hidden=true); PID_dintTerm as control_signal (Brief="Integral term", Default=0,Unit='1/s', Hidden=true); PID_doutp as control_signal (Brief="Sum of proportional, integral and derivative terms",Unit='1/s', Hidden=true); PID_outps as control_signal (Brief="Variable outp scaled between -1 and 1", Hidden=true, Default=0.5); PID_outp as control_signal (Brief="Variable outp", Hidden=true); PID_dpropTerm as control_signal (Brief="Proportional term", Default=0,Unit='1/s', Hidden=true); PID_setPointFilt as control_signal (Brief="Filtered setPoint", Default=0, Hidden=true); PID_input as control_signal (Brief="Previous scaled input signal", Default=0.5, Hidden=true); PID_output as control_signal (Brief="Scaled output signal", Default=0.5, Hidden=true); PID_setPoint as control_signal (Brief="Scaled setPoint",Default=0.5, Hidden=true); PID_AWFactor as Real (Brief="Integral term multiplier used in anti-reset windup", Hidden=true); PID_action as Real (Hidden=true); #++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++ EQUATIONS "Input " PID_input*(MaxInput - MinInput) = Input - MinInput; "Output " Output = PID_output*(MaxOutput - MinOutput) + MinOutput; "Set Point " PID_setPoint*(MaxInput - MinInput) = SetPoint - MinInput; if (tau < 1e-3*'s') then "Input first order filter" (tau + 1e-3*'s')*diff(PID_inputFilt)= PID_input - PID_inputFilt; else "Input first order filter" tau*diff(PID_inputFilt)= PID_input - PID_inputFilt; end if (tauSet < 1e-3*'s') then "setPoint first order filter" (tauSet + 1e-3*'s')*diff(PID_setPointFilt)= PID_setPoint - PID_setPointFilt; else "setPoint first order filter" tauSet*diff(PID_setPointFilt)= PID_setPoint - PID_setPointFilt; end switch Mode case "Manual": "Error definition for proportional term" PID_error*'s' = PID_inputFilt*(beta-1.0); "Error definition for derivative term" PID_errorD*'s'= PID_inputFilt*(gamma-1.0); "Error definition for integral term" PID_errorI= 0; case "Automatic": "Error definition for proportional term" PID_error = beta*diff(PID_setPointFilt) - diff(PID_inputFilt); "Error definition for derivative term" PID_errorD = gamma*diff(PID_setPointFilt) - diff(PID_inputFilt); "Error definition for integral term" PID_errorI = PID_setPointFilt-PID_inputFilt; end "Calculate proportional term" PID_dpropTerm=PID_error; if (derivTime < 1e-3*'s') then "Derivative term filter" alpha*(derivTime + 1e-3*'s')*diff(PID_dFilt) = PID_errorD - PID_dFilt; else "Derivative term filter" alpha*(derivTime)*diff(PID_dFilt) = PID_errorD - PID_dFilt; end "Calculate derivative term" PID_dderivTerm = derivTime*diff(PID_dFilt); "Unscaled output" diff(PID_outp)=PID_doutp; "Scale outp" PID_outps=2*PID_outp-1; switch Clip case "Clipped": if abs(PID_outps)>1 then "Calculate clipped output when saturated" PID_output=(sign(PID_outps)+1)/2; else "Calculate clipped output when not saturated" PID_output=PID_outp; end #PID_output = max([0, PID_outp]); case "Unclipped": "Calculate unclipped output" PID_output=PID_outp; end switch Action case "Direct": PID_action = -1.0; case "Reverse": PID_action = 1.0; end switch PID_Select case "Ideal": "Calculate integral term" intTime*PID_dintTerm = PID_errorI; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*gain*(PID_dpropTerm + PID_dintTerm + PID_dderivTerm); "Calculate AWFactor - Not in use in this mode" PID_AWFactor=1; case "Parallel": "Calculate integral term" intTime*PID_dintTerm = PID_errorI; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*(gain*PID_dpropTerm + PID_dintTerm + PID_dderivTerm); "Calculate AWFactor - Not in use in this mode" PID_AWFactor=1; case "Series": "Calculate integral term" intTime*PID_dintTerm = PID_errorI; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*(gain*(PID_dpropTerm + PID_dintTerm)*(1/'s' + PID_dderivTerm)*'s'); "Calculate AWFactor - Not in use in this mode" PID_AWFactor=1; case "Ideal_AWBT": "Calculate integral term with anti-windup and bumpless transfer" PID_action*gain*(intTime*PID_dintTerm-PID_errorI) = PID_output-PID_outp; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*gain*(PID_dpropTerm + PID_dintTerm + PID_dderivTerm); "Calculate AWFactor - Not in use in this mode" PID_AWFactor=1; case "Parallel_AWBT": "Calculate integral term with anti-windup and bumpless transfer" PID_action*gain*(intTime*PID_dintTerm-PID_errorI) = PID_output-PID_outp; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*(gain*PID_dpropTerm + PID_dintTerm + PID_dderivTerm); "Calculate AWFactor - Not in use in this mode" PID_AWFactor=1; case "Series_AWBT": "Calculate integral term with anti-windup and bumpless transfer" PID_action*gain*(intTime*PID_dintTerm-PID_errorI) = PID_output-PID_outp; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*(gain*(PID_dpropTerm + PID_dintTerm)*(1/'s' + PID_dderivTerm)*'s'); "Calculate AWFactor - Not in use in this mode" PID_AWFactor=1; case "Ideal_AW": "Calculate integral term with anti-windup" intTime*PID_dintTerm = PID_AWFactor*PID_errorI; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*gain*(PID_dpropTerm + PID_dintTerm + PID_dderivTerm); if abs(PID_outps)>1 and (PID_action*sign(PID_outps)*PID_errorI)>0 then "Calculate AWFactor" PID_AWFactor=-tanh(sign(PID_outps)*PID_outps*100-102); else "Calculate AWFactor" PID_AWFactor=1; end case "Parallel_AW": "Calculate integral term with anti-windup" intTime*PID_dintTerm = PID_AWFactor*PID_errorI; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*(gain*PID_dpropTerm + PID_dintTerm + PID_dderivTerm); if abs(PID_outps)>1 and (PID_action*sign(PID_outps)*PID_errorI)>0 then "Calculate AWFactor" PID_AWFactor=-tanh(sign(PID_outps)*PID_outps*100-102); else "Calculate AWFactor" PID_AWFactor=1; end case "Series_AW": "Calculate integral term with anti-windup" intTime*PID_dintTerm = PID_AWFactor*PID_errorI; "Sum of proportional, integral and derivative terms" PID_doutp = PID_action*(gain*(PID_dpropTerm + PID_dintTerm)*(1/'s' + PID_dderivTerm)*'s'); if abs(PID_outps)>1 and (PID_action*sign(PID_outps)*PID_errorI)>0 then "Calculate AWFactor" PID_AWFactor=-tanh(sign(PID_outps)*PID_outps*100-102); else "Calculate AWFactor" PID_AWFactor=1; end end INITIAL PID_output = bias; diff(PID_dFilt) = 0/'s^2'; diff(PID_inputFilt)=0/'s'; diff(PID_setPointFilt)=0/'s'; end