#*------------------------------------------------------------------- * 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: PIDs.mso 558 2008-07-21 20:41:41Z rafael $ *-------------------------------------------------------------------*# using "types"; Model MPorts ATTRIBUTES Pallete = false; Brief = "Model of Ports to be used with PIDs."; VARIABLES input as control_signal (Brief="Previous scaled input signal", Default=0.5); output as control_signal (Brief="Scaled output signal", Default=0.5); setPoint as control_signal (Brief="Scaled setPoint",Default=0.5); end Model MInternal_Variables ATTRIBUTES Pallete = false; Brief = "Model of Internal Variables to be used with PIDs."; VARIABLES derivTerm as control_signal (Brief="Derivative term", Default=0); dFilt as control_signal (Brief="Derivative term filtered", Default=0.5); error as control_signal (Brief="Error definition for proportional term"); errorD as control_signal (Brief="Error definition for derivative term"); errorI as control_signal (Brief="Error definition for integral term"); inputFilt as control_signal (Brief="Filtered input"); intTerm as control_signal (Brief="Integral term", Default=0); outp as control_signal (Brief="Sum of proportional, integral and derivative terms"); outps as control_signal (Brief="Variable outp scaled between -1 and 1"); propTerm as control_signal (Brief="Proportional term", Default=0); setPointFilt as control_signal (Brief="Filtered setPoint", Default=0); end Model PID ATTRIBUTES Pallete = false; Icon = "icon/PID"; Brief = "Model of PIDs."; Info = "== Inputs == * scaled processs variable. * scaled bias. * scaled setpoint. == Outputs == * 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"); VARIABLES Internal as MInternal_Variables; Ports as MPorts; AWFactor as Real (Brief="Integral term multiplier used in anti-reset windup"); action as Real(Protected=true); INITIAL Internal.intTerm = 0; diff(Internal.dFilt) = 0/'s'; diff(Internal.inputFilt) = 0/'s'; diff(Internal.setPointFilt) = 0/'s'; EQUATIONS if (tau equal 0) then "Input first order filter" (tau + 1e-3*'s')*diff(Internal.inputFilt)= Ports.input - Internal.inputFilt; else "Input first order filter" tau*diff(Internal.inputFilt)= Ports.input - Internal.inputFilt; end if (tauSet equal 0) then "setPoint first order filter" (tauSet + 1e-3*'s')*diff(Internal.setPointFilt)= Ports.setPoint - Internal.setPointFilt; else "setPoint first order filter" tauSet*diff(Internal.setPointFilt)= Ports.setPoint - Internal.setPointFilt; end switch Mode case "Manual": "Error definition for proportional term" Internal.error = Internal.inputFilt*(beta-1.0); "Error definition for derivative term" Internal.errorD= Internal.inputFilt*(gamma-1.0); "Error definition for integral term" Internal.errorI= 0; case "Automatic": "Error definition for proportional term" Internal.error = beta*Internal.setPointFilt - Internal.inputFilt; "Error definition for derivative term" Internal.errorD = gamma*Internal.setPointFilt - Internal.inputFilt; "Error definition for integral term" Internal.errorI = Internal.setPointFilt-Internal.inputFilt; end "Calculate proportional term" Internal.propTerm=Internal.error; if (derivTime equal 0) then "Derivative term filter" alpha*(derivTime + 1e-3*'s')*diff(Internal.dFilt) = Internal.errorD - Internal.dFilt; else "Derivative term filter" alpha*(derivTime)*diff(Internal.dFilt) = Internal.errorD - Internal.dFilt; end "Calculate derivative term" Internal.derivTerm = derivTime*diff(Internal.dFilt); "Scale outp" Internal.outps=2*Internal.outp-1; switch Clip case "Clipped": if abs(Internal.outps)>1 then "Calculate clipped output when itīs saturated" Ports.output=(sign(Internal.outps)*1+1)/2; else "Calculate clipped output when itīs not saturated" Ports.output=Internal.outp; end case "Unclipped": "Calculate unclipped output" Ports.output=Internal.outp; end switch Action case "Direct": action = -1.0; case "Reverse": action = 1.0; end switch PID_Select case "Ideal_AW": "Calculate integral term with anti-windup" intTime*diff(Internal.intTerm) = AWFactor*Internal.errorI; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*gain*(Internal.propTerm + Internal.intTerm + Internal.derivTerm); if abs(Internal.outps)>1 and (action*sign(Internal.outps)*Internal.errorI)>0 then "Calculate AWFactor" AWFactor=-tanh(sign(Internal.outps)*Internal.outps*100-102); else "Calculate AWFactor" AWFactor=1; end case "Parallel_AW": "Calculate integral term with anti-windup" intTime*diff(Internal.intTerm) = AWFactor*Internal.errorI; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*(gain*Internal.propTerm + Internal.intTerm + Internal.derivTerm); if abs(Internal.outps)>1 and (action*sign(Internal.outps)*Internal.errorI)>0 then "Calculate AWFactor" AWFactor=-tanh(sign(Internal.outps)*Internal.outps*100-102); else "Calculate AWFactor" AWFactor=1; end case "Series_AW": "Calculate integral term with anti-windup" intTime*diff(Internal.intTerm) = AWFactor*Internal.errorI; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*(gain*(Internal.propTerm + Internal.intTerm)*(1 + Internal.derivTerm)); if abs(Internal.outps)>1 and (action*sign(Internal.outps)*Internal.errorI)>0 then "Calculate AWFactor" AWFactor=-tanh(sign(Internal.outps)*Internal.outps*100-102); else "Calculate AWFactor" AWFactor=1; end case "Ideal": "Calculate integral term" intTime*diff(Internal.intTerm) = Internal.errorI; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*gain*(Internal.propTerm + Internal.intTerm + Internal.derivTerm); "Calculate AWFactor - Not in use in this mode" AWFactor=1; case "Parallel": "Calculate integral term" intTime*diff(Internal.intTerm) = Internal.errorI; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*(gain*Internal.propTerm + Internal.intTerm + Internal.derivTerm); "Calculate AWFactor - Not in use in this mode" AWFactor=1; case "Series": "Calculate integral term" intTime*diff(Internal.intTerm) = Internal.errorI; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*(gain*(Internal.propTerm + Internal.intTerm)*(1 + Internal.derivTerm)); "Calculate AWFactor - Not in use in this mode" AWFactor=1; case "Ideal_AWBT": "Calculate integral term with anti-windup and bumpless transfer" action*gain*(intTime*diff(Internal.intTerm)-Internal.errorI) = Ports.output-Internal.outp; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*gain*(Internal.propTerm + Internal.intTerm + Internal.derivTerm); "Calculate AWFactor - Not in use in this mode" AWFactor=1; case "Parallel_AWBT": "Calculate integral term with anti-windup and bumpless transfer" action*gain*(intTime*diff(Internal.intTerm)-Internal.errorI) = Ports.output-Internal.outp; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*(gain*Internal.propTerm + Internal.intTerm + Internal.derivTerm); "Calculate AWFactor - Not in use in this mode" AWFactor=1; case "Series_AWBT": "Calculate integral term with anti-windup and bumpless transfer" action*gain*(intTime*diff(Internal.intTerm)-Internal.errorI) = Ports.output-Internal.outp; "Sum of proportional, integral and derivative terms" Internal.outp = bias + action*(gain*(Internal.propTerm + Internal.intTerm)*(1 + Internal.derivTerm)); "Calculate AWFactor - Not in use in this mode" AWFactor=1; end end Model PID_gui as PID ATTRIBUTES Pallete = true; Icon = "icon/PIDIncr"; PARAMETERS MinInput as control_signal(Default=-1000); MaxInput as control_signal(Default=1000); VARIABLES in Input as control_signal(Protected=true, PosX=0, PosY=0.5); out Output as control_signal(Protected=true, PosX=1, PosY=0.5); SetPoint as control_signal; EQUATIONS Ports.input*(MaxInput - MinInput) = Input - MinInput; Ports.output = Output; Ports.setPoint*(MaxInput - MinInput) = SetPoint - MinInput; end Model FirstOrder ATTRIBUTES Pallete = true; Icon = "icon/PIDIncr"; PARAMETERS tau as Real (Brief="Time Constant", Unit = 's', Default=4); A as Real (Unit='1/s'); B as Real (Unit='1/s'); C as Real; D as Real(Default=0); VARIABLES x as control_signal(Brief="State"); in u as control_signal(Brief="Input signal", PosX=0, PosY=0.5); out y as control_signal(Brief="Output signal", PosX=1, PosY=0.5); EQUATIONS diff(x) = A*x + B*u; y = C*x + D*u; end Model StepSignal ATTRIBUTES Pallete = true; Icon = "icon/PIDIncr"; PARAMETERS StepTime as positive(Unit='s'); StartValue as control_signal; FinalValue as control_signal; VARIABLES out OutSignal as control_signal(PosX=1, PosY=0.5); EQUATIONS if(time < StepTime) then OutSignal = StartValue; else OutSignal = FinalValue; end end Model ConstantSignal ATTRIBUTES Pallete = true; Icon = "icon/PIDIncr"; PARAMETERS Value as control_signal; VARIABLES out OutSignal as control_signal(PosX=1, PosY=0.5); EQUATIONS OutSignal = Value; end