//OpenSCADA module Special.FLibComplex1 file: libcompl1.h /*************************************************************************** * Copyright (C) 2005-2022 by Roman Savochenko, * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef LIBCOMPL1_H #define LIBCOMPL1_H #include #include #include #include #include "statfunc.h" using std::string; using std::vector; namespace FLibComplex1 { //********************************************************************* //* Complex1 functions: * //********************************************************************* //* DigitBlock * //* Support digital blocks: 0-Open;1-Start;2-Enable;3-Norm;4-Block * //********************************************************************* class DigitBlock : public TFunction { public: DigitBlock( ) : TFunction("digitBlock", SSPC_ID) { ioAdd(new IO("cmdOpen",trS("Command \"Open\""),IO::Boolean,IO::Output,"0")); ioAdd(new IO("cmdClose",trS("Command \"Close\""),IO::Boolean,IO::Output,"0")); ioAdd(new IO("cmdStop",trS("Command \"Stop\""),IO::Boolean,IO::Output,"0")); ioAdd(new IO("stOpen",trS("State \"Opened\""),IO::Boolean,IO::Default,"0")); ioAdd(new IO("stClose",trS("State \"Closed\""),IO::Boolean,IO::Default,"0")); ioAdd(new IO("tCmd",trS("Time of commands holding, seconds"),IO::Integer,IO::Default,"5")); ioAdd(new IO("frq",trS("Frequency of the calculating, Hz"),IO::Integer,IO::Default,"1")); ioAdd(new IO("w_tm",trS("Counter of the commands processing"),IO::Real,IO::Output,"0",true)); ioAdd(new IO("last_cmd",trS("Last command"),IO::Integer,IO::Output,"0",true)); } string name( ) { return _("Discrete block"); } string descr( ) { return _("The function contains a control algorithm for the collection of discrete signals " "for latches and pumps that contain: signs \"Opened\", \"Closed\", and commands \"Open\", \"Close\", and \"Stop\".\n" "The function supports the operation of pulsed commands, that is it can take a signal within a specified time interval."); } void calc( TValFunc *val ) { bool set = false; if(val->getB(0) && val->getI(8) != 1) { val->setI(8, 1); set = true; } if(val->getB(1) && val->getI(8) != 2) { val->setI(8, 2); set = true; } if(val->getB(2) && val->getI(8) != 3) { val->setI(8, 3); set = true; } if(set && val->getI(5) > 0) val->setR(7, val->getI(5)); if(val->getR(7) > 0) val->setR(7, val->getR(7)-1/vmax(1e-3,val->getI(6))); else { val->setR(7, 0); if(val->getI(5) > 0) { if(val->getI(8) == 1) val->setB(0, 0); if(val->getI(8) == 2) val->setB(1, 0); if(val->getI(8) == 3) val->setB(2, 0); val->setI(8, 0); } } } }; //********************************************************************* //* Simple summator * //* Formula: out=in1_1*in1_2+in2_1*in2_2+in3_1*in3_2+in4_1*in4_2+ * //* in5_1*in5_2+in6_1*in6_2+in7_1*in7_2+in8_1*in8_2; * //********************************************************************* class Sum : public TFunction { public: Sum( ) : TFunction("sum", SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"1")); for(int i_in = 1; i_in <= 8; i_in++) { ioAdd(new IO(TSYS::strMess("in%d_1",i_in).c_str(),TSYS::strMess(_("Input %d.1"),i_in),IO::Real,IO::Default,"0")); ioAdd(new IO(TSYS::strMess("in%d_2",i_in).c_str(),TSYS::strMess(_("Input %d.2"),i_in),IO::Real,IO::Default,"0")); } } string name( ) { return _("Simple sumator"); } string descr( ) { return _("Simple sumator with multiplication:\n" "out=in1_1*in1_2+in2_1*in2_2+in3_1*in3_2+in4_1*in4_2+\n" " in5_1*in5_2+in6_1*in6_2+in7_1*in7_2+in8_1*in8_2;"); } void calc( TValFunc *val ) { val->setR(0, val->getR(1)*val->getR(2) + val->getR(3)*val->getR(4) + val->getR(5)*val->getR(6) + val->getR(7)*val->getR(8) + val->getR(9)*val->getR(10) + val->getR(11)*val->getR(12) + val->getR(13)*val->getR(14) + val->getR(15)*val->getR(16)); } }; //********************************************************************* //* Simple multiplication * //* Formula: out=(in1_1*in1_2*in1_3*in1_4*in1_5*in1_6)/ * //* (in2_1*in2_2*in2_3*in2_4); * //********************************************************************* class Mult : public TFunction { public: Mult( ) : TFunction("mult", SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"1")); for(int iC = 1; iC <= 6; iC++) ioAdd(new IO(("in1_"+i2s(iC)).c_str(),(_("Input 1.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Simple multiplication"); } string descr( ) { return _("Simple multiplication with division:\n" "out=(in1_1*in1_2*in1_3*in1_4*in1_5*in1_6)/(in2_1*in2_2*in2_3*in2_4);"); } void calc( TValFunc *val ) { val->setR(0, (val->getR(1)*val->getR(2)*val->getR(3)*val->getR(4)*val->getR(5)*val->getR(6))/ (val->getR(7)*val->getR(8)*val->getR(9)*val->getR(10))); } }; //********************************************************************* //* Multiplier and divider * //* Formula: out=(in1_1*in1_2*in1_3*in1_4*in1_5*(in2_1*in2_2*in2_3*in2_4*in2_5+ //* (in3_1*in3_2*in3_3*in3_4*in3_5)/(in4_1*in4_2*in4_3*in4_4*in4_5))) //********************************************************************* class MultDiv : public TFunction { public: MultDiv( ) : TFunction("multDiv", SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in1_"+i2s(iC)).c_str(),(_("Input 1.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in3_"+i2s(iC)).c_str(),(_("Input 3.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Multiplication and division"); } string descr( ) { return _("Branched multiplication and division:\n" "out=in1_1*in1_2*in1_3*in1_4*in1_5*(in2_1*in2_2*in2_3*in2_4*in2_5+\n" " (in3_1*in3_2*in3_3*in3_4*in3_5)/(in4_1*in4_2*in4_3*in4_4*in4_5));"); } void calc( TValFunc *val ) { double tmp1 = val->getR(16)*val->getR(17)*val->getR(18)*val->getR(19)*val->getR(20); double tmp2 = val->getR(1)*val->getR(2)*val->getR(3)*val->getR(4)*val->getR(5); double tmp3 = val->getR(6)*val->getR(7)*val->getR(8)*val->getR(9)*val->getR(10); double tmp4 = val->getR(11)*val->getR(12)*val->getR(13)*val->getR(14)*val->getR(15); val->setR(0, tmp2*(tmp3+tmp4/tmp1)); } }; //********************************************************************* //* Exponent * //* Formula: out=exp (in1_1*in1_2*in1_3*in1_4*in1_5 + * //* (in2_1*in2_2*in2_3*in2_4*in2_5+in3) / * //* (in4_1*in4_2*in4_3*in4_4*in4_5+in5) ) * //********************************************************************* class Exp : public TFunction { public: Exp( ) : TFunction("exp", SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in1_"+i2s(iC)).c_str(),(_("Input 1.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); ioAdd(new IO("in3",trS("Input 3"),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); ioAdd(new IO("in5",trS("Input 5"),IO::Real,IO::Default,"1")); } string name( ) { return _("Exponent"); } string descr( ) { return _("Calculate an exponent over a group of variables:\n" "out=exp (in1_1*in1_2*in1_3*in1_4*in1_5 +\n" " (in2_1*in2_2*in2_3*in2_4*in2_5+in3) / (in4_1*in4_2*in4_3*in4_4*in4_5+in5) );"); } void calc( TValFunc *v ) { double tmp1 = v->getR(12)*v->getR(13)*v->getR(14)*v->getR(15)*v->getR(16) + v->getR(17); double tmp2 = v->getR(1)*v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5); double tmp3 = v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)*v->getR(10) + v->getR(11); v->setR(0, exp(tmp2+tmp3/tmp1)); } }; //********************************************************************* //* Power * //* Formula: out=(in1_1*in1_2*in1_3*in1_4*in1_5)^ * //* (in2_1*in2_2*in2_3*in2_4*in2_5 + * //* (in3_1*in3_2*in3_3*in3_4*in3_5)/ * //* (in4_1*in4_2*in4_3*in4_4*in4_5) ) * //********************************************************************* class Pow : public TFunction { public: Pow( ) : TFunction("pow",SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in1_"+i2s(iC)).c_str(),(_("Input 1.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in3_"+i2s(iC)).c_str(),(_("Input 3.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Power"); } string descr( ) { return _("Raising to the power:\n" "out=(in1_1*in1_2*in1_3*in1_4*in1_5)^(in2_1*in2_2*in2_3*in2_4*in2_5 +\n" " (in3_1*in3_2*in3_3*in3_4*in3_5)/(in4_1*in4_2*in4_3*in4_4*in4_5));"); } void calc( TValFunc *v ) { double tmp1 = v->getR(16)*v->getR(17)*v->getR(18)*v->getR(19)*v->getR(20); double tmp2 = v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)*v->getR(10); double tmp3 = v->getR(11)*v->getR(12)*v->getR(13)*v->getR(14)*v->getR(15); tmp2 = tmp2 + tmp3/tmp1; tmp3 = v->getR(1)*v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5); v->setR(0, pow(tmp3,tmp2)); } }; //********************************************************************* //* Condition < * //* Formula: out=if( in1<(in2_1*in2_2*in2_3*in2_4) ) * //* then in3_1*in3_2*in3_3*in3_4; * //* else in4_1*in4_2*in4_3*in4_4; * //********************************************************************* class Cond1 : public TFunction { public: Cond1( ) : TFunction("cond_lt", SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); ioAdd(new IO("in1",trS("Input 1"),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in3_"+i2s(iC)).c_str(),(_("Input 3.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Condition '<'"); } string descr( ) { return _("Operation of the branching according to the condition \"less\":\n" "out=if( in1<(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;\n" " else in4_1*in4_2*in4_3*in4_4;"); } void calc( TValFunc *v ) { double tmp1 = v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5); if(v->getR(1) < tmp1) v->setR(0,v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)); else v->setR(0,v->getR(10)*v->getR(11)*v->getR(12)*v->getR(13)); } }; //********************************************************************* //* Condition > * //* Formula: out=if( in1>(in2_1*in2_2*in2_3*in2_4) ) * //* then in3_1*in3_2*in3_3*in3_4; * //* else in4_1*in4_2*in4_3*in4_4; * //********************************************************************* class Cond2 : public TFunction { public: Cond2( ) : TFunction("cond_gt",SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); ioAdd(new IO("in1",trS("Input 1"),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in3_"+i2s(iC)).c_str(),(_("Input 3.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Condition '>'"); } string descr( ) { return _("Operation of the branching according to the condition \"great\":\n" "out=if( in1>(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;\n" " else in4_1*in4_2*in4_3*in4_4;"); } void calc( TValFunc *v ) { double tmp1 = v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5); if(v->getR(1) > tmp1) v->setR(0, v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)); else v->setR(0, v->getR(10)*v->getR(11)*v->getR(12)*v->getR(13)); } }; //********************************************************************* //* Condition x>, x<, >x> * //* Formula: out = if( in1<(in2_1*in2_2*in2_3*in2_4) ) * //* then in3_1*in3_2*in3_3*in3_4; * //* else if( in1>(in4_1*in4_2*in4_3*in4_4) * //* then in5_1*in5_2*in5_3*in5_4; * //* else in6_1*in6_2*in6_3*in6_4; * //********************************************************************* class Cond3 : public TFunction { public: Cond3( ) : TFunction("cond_full", SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); ioAdd(new IO("in1",trS("Input 1"),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in3_"+i2s(iC)).c_str(),(_("Input 3.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in5_"+i2s(iC)).c_str(),(_("Input 5.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in6_"+i2s(iC)).c_str(),(_("Input 6.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Full condition"); } string descr( ) { return _("Full condition check including great, less and equal:\n" "out = if( in1<(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;\n" " else if( in1>(in4_1*in4_2*in4_3*in4_4) then in5_1*in5_2*in5_3*in5_4;\n" " else in6_1*in6_2*in6_3*in6_4;"); } void calc( TValFunc *v ) { double tmp1 = v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5); double tmp2 = v->getR(10)*v->getR(11)*v->getR(12)*v->getR(13); double tmp3 = v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9); double tmp4 = v->getR(18)*v->getR(19)*v->getR(20)*v->getR(21); double tmp5 = v->getR(14)*v->getR(15)*v->getR(16)*v->getR(17); if(v->getR(1) < tmp1) v->setR(0, tmp3); else if(v->getR(1) > tmp2) v->setR(0, tmp5); else v->setR(0, tmp4); } }; //********************************************************************* //* Selector * //* Formula: out = if( sel = 1 ) then in1_1*in1_2*in1_3*in1_4; * //* if( sel = 2 ) then in2_1*in2_2*in2_3*in2_4; * //* if( sel = 3 ) then in3_1*in3_2*in3_3*in3_4; * //* if( sel = 4 ) then in4_1*in4_2*in4_3*in4_4; * //********************************************************************* class Select : public TFunction { public: Select( ) : TFunction("select",SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); ioAdd(new IO("sel",trS("Select"),IO::Integer,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in1_"+i2s(iC)).c_str(),(_("Input 1.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in3_"+i2s(iC)).c_str(),(_("Input 3.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 4; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Selection"); } string descr( ) { return _("Choose one from the four options:\n" "out = if( sel = 1 ) then in1_1*in1_2*in1_3*in1_4;\n" " if( sel = 2 ) then in2_1*in2_2*in2_3*in2_4;\n" " if( sel = 3 ) then in3_1*in3_2*in3_3*in3_4;\n" " if( sel = 4 ) then in4_1*in4_2*in4_3*in4_4;"); } void calc( TValFunc *v ) { switch(v->getI(1)) { case 1: v->setR(0, v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5)); break; case 2: v->setR(0, v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)); break; case 3: v->setR(0, v->getR(10)*v->getR(11)*v->getR(12)*v->getR(13)); break; case 4: v->setR(0, v->getR(14)*v->getR(15)*v->getR(16)*v->getR(17)); break; default: v->setR(0, 0); } } }; //********************************************************************* //* Increment * //* Formula: out = if( in > prev ) * //* then prev + k_pos*(in-prev); * //* else prev - k_neg*(prev-in); * //********************************************************************* class Increm : public TFunction { public: Increm( ) : TFunction("increment",SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); ioAdd(new IO("in",trS("Input"),IO::Real,IO::Default,"1")); ioAdd(new IO("prev",trS("Previous"),IO::Real,IO::Default,"1")); ioAdd(new IO("k+",trS("Positive coefficient"),IO::Real,IO::Default,"0.1")); ioAdd(new IO("k-",trS("Negative coefficient"),IO::Real,IO::Default,"0.1")); } string name( ) { return _("Iterator"); } string descr( ) { return _("Iterative calculation with the increment specifying, gain ratio for different directions is different:\n" "out = if( in > prev ) then prev + (k+)*(in-prev); else prev - (k-)*(prev-in);"); } void calc( TValFunc *v ) { if(v->getR(1) > v->getR(2)) v->setR(0, v->getR(2) + v->getR(3)*(v->getR(1)-v->getR(2))); else v->setR(0, v->getR(2) - v->getR(4)*(v->getR(2)-v->getR(1))); } }; //********************************************************************* //* Divider * //* Formula: out = (in1_1*in1_2*in1_3*in1_4*in1_5 + in2_1*in2_2*in2_3*in2_4*in2_5 + in3) / //* (in4_1*in4_2*in4_3*in4_4*in4_5 + in5_1*in5_2*in5_3*in5_4*in5_5 + in6); //********************************************************************* class Divider : public TFunction { public: Divider( ) : TFunction("div", SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in1_"+i2s(iC)).c_str(),(_("Input 1.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); ioAdd(new IO("in3",_("Input 3"),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in5_"+i2s(iC)).c_str(),(_("Input 5.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); ioAdd(new IO("in6",_("Input 6"),IO::Real,IO::Default,"1")); } string name( ) { return _("Division"); } string descr( ) { return _("Divides assemblies of variables:\n" "out = (in1_1*in1_2*in1_3*in1_4*in1_5 + in2_1*in2_2*in2_3*in2_4*in2_5 + in3) /\n" " (in4_1*in4_2*in4_3*in4_4*in4_5 + in5_1*in5_2*in5_3*in5_4*in5_5 + in6);"); } void calc( TValFunc *v ) { double t1 = v->getR(1)*v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5) + v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)*v->getR(10) + v->getR(11); double t2 = v->getR(12)*v->getR(13)*v->getR(14)*v->getR(15)*v->getR(16) + v->getR(17)*v->getR(18)*v->getR(19)*v->getR(20)*v->getR(21) + v->getR(22); v->setR(0, t1/t2); } }; //********************************************************************* //* PID * //* Inputs: * //* 0:var - Variable * //* 1:sp - Set-point * //* 2:max - Maximum scale * //* 3:min - Minimum scale * //* 4:manIn - Manual input * //* 5:out - Output * //* 6:auto - Automatic mode * //* 7:casc - Cascade mode * //* 8:Kp - Gain * //* 9:Ti - Integral time (ms) * //* 10:Kd - Kd * //* 11:Td - Differential time (ms) * //* 12:Tzd - Filter (lag) time (ms) * //* 13:Hup - Up output limit (%) * //* 14:Hdwn - Down output limit (%) * //* 15:Zi - Insensibility zone (%) * //* 16:followSp - Follow to sp from variable for manual * //* 17:K1 - Scale input 1 * //* 18:in1 - Add input 1 * //* 19:K2 - Scale input 2 * //* 20:in2 - Add input 2 * //* 21:K3 - Scale input 3 * //* 22:in3 - Add input 3 * //* 23:K4 - Scale input 4 * //* 24:in4 - Add input 4 * //* 25:cycle- Calc cycle (ms) * //* Internal data: * //* 26:#int - Curent integral value * //* 27:#dif - Curent differential value * //* 28:#lag - Curent lag value * //********************************************************************* class PID : public TFunction { public: PID( ) : TFunction("pid",SSPC_ID) { //Inputs ioAdd(new IO("var",trS("Variable"),IO::Real,IO::Default,"0")); ioAdd(new IO("sp",trS("Setpoint"),IO::Real,IO::Output,"0")); ioAdd(new IO("max",trS("Maximum of the scale"),IO::Real,IO::Default,"100")); ioAdd(new IO("min",trS("Minimum of the scale"),IO::Real,IO::Default,"0")); ioAdd(new IO("manIn",trS("Manual input, %"),IO::Real,IO::Default,"0")); ioAdd(new IO("out",trS("Output, %"),IO::Real,IO::Return,"0")); ioAdd(new IO("auto",trS("Auto mode"),IO::Boolean,IO::Default,"0")); ioAdd(new IO("casc",trS("Cascade mode"),IO::Boolean,IO::Default,"0")); ioAdd(new IO("Kp",trS("Kp"),IO::Real,IO::Default,"1")); ioAdd(new IO("Ti",trS("Ti, milliseconds"),IO::Integer,IO::Default,"1000")); ioAdd(new IO("Kd",trS("Kd"),IO::Real,IO::Default,"1")); ioAdd(new IO("Td",trS("Td, milliseconds"),IO::Integer,IO::Default,"0")); ioAdd(new IO("Tzd",trS("Td lag, milliseconds"),IO::Integer,IO::Default,"0")); ioAdd(new IO("Hup",trS("Upper limit of the out, %"),IO::Real,IO::Default,"100")); ioAdd(new IO("Hdwn",trS("Lower limit of the out, %"),IO::Real,IO::Default,"0")); ioAdd(new IO("Zi",trS("Insensibility, %"),IO::Real,IO::Default,"1")); ioAdd(new IO("followSp",trS("Follow setpoint from variable on the manual mode"),IO::Boolean,IO::Default,"1")); ioAdd(new IO("K1",trS("K input 1"),IO::Real,IO::Default,"0")); ioAdd(new IO("in1",trS("Input 1"),IO::Real,IO::Default,"0")); ioAdd(new IO("K2",trS("K input 2"),IO::Real,IO::Default,"0")); ioAdd(new IO("in2",trS("Input 2"),IO::Real,IO::Default,"0")); ioAdd(new IO("K3",trS("K input 3"),IO::Real,IO::Default,"0")); ioAdd(new IO("in3",trS("Input 3"),IO::Real,IO::Default,"0")); ioAdd(new IO("K4",trS("K input 4"),IO::Real,IO::Default,"0")); ioAdd(new IO("in4",trS("Input 4"),IO::Real,IO::Default,"0")); ioAdd(new IO("f_frq",trS("Frequency of the calculating, Hz"),IO::Real,IO::Default,"1")); //Internal data: ioAdd(new IO("int",trS("Integral value"),IO::Real,IO::Output,"0",true)); ioAdd(new IO("dif",trS("Differential value"),IO::Real,IO::Output,"0",true)); ioAdd(new IO("lag",trS("Differential lag"),IO::Real,IO::Output,"0",true)); } string name( ) { return _("PID regulator"); } string descr( ) { return _("Proportional-integral-differential regulator."); } void calc( TValFunc *v ) { double val = v->getR(0), sp = v->getR(1), max = v->getR(2), min = v->getR(3), manIn = v->getR(4), out = v->getR(5), kp = v->getR(8), kpd = v->getR(10), h_up = v->getR(13), h_dwn = v->getR(14), zi = v->getR(15), followSp = v->getB(16), k1 = v->getR(17), in1 = v->getR(18), k2 = v->getR(19), in2 = v->getR(20), k3 = v->getR(21), in3 = v->getR(22), k4 = v->getR(23), in4 = v->getR(24), frq = v->getR(25), integ = v->getR(26), difer = v->getR(27), dlag = v->getR(28); double Tzd = vmin(1e3/(frq*v->getI(12)), 1); double Kint = vmin(1e3/(frq*v->getI(9)), 1); double Kdif = vmin(1e3/(frq*v->getI(11)), 1); //Scale error if(max <= min) return; //Prepare values sp = vmin(100, vmax(0,100*(sp-min)/(max-min))); val = 100*(val-min)/(max-min); val += k1*in1 + k2*in2; val = vmin(100, vmax(-100,val)); //Error double err = sp - val; //Insensibility err = (fabs(err) < zi) ? 0 : ((err>0)?err-zi:err+zi); //Gain err *= kp; err = vmin(100, vmax(-100,err)); integ += Kint*err; //Integral difer -= Kdif*(difer-val); //Differecial wait dlag += Tzd*((difer-val)-dlag); //Differecial lag //Automatic mode enabled if(v->getB(6)) out = err + integ + kpd*dlag + k3*in3 + k4*in4; else { v->setB(7, false); if(followSp) v->setR(1, v->getR(0)); out = manIn; } //Check output limits out = manIn = vmin(h_up, vmax(h_dwn,out)); //Fix integral for manual and limits integ = out - err - kpd*dlag - k3*in3 - k4*in4; //Write outputs v->setR(4, manIn); v->setR(5, out); v->setR(26, integ); v->setR(27, difer); v->setR(28, dlag); } }; //********************************************************************* //* Alarm * //* Formula: out = if (val>max || valmax || valgetR(2), min = v->getR(3), val = v->getR(1); if(max != min && (val < min || val > max)) v->setB(0, true); else v->setB(0, false); } }; //********************************************************************* //* Flow * //* Formula: f = k1*((k3+k4*x)^k2)+Krnd*RAND * //********************************************************************* class Flow : public TFunction { public: Flow( ) : TFunction("flow",SSPC_ID) { ioAdd(new IO("f",trS("Flow"),IO::Real,IO::Return,"0")); ioAdd(new IO("x",trS("X position"),IO::Real,IO::Default,"0")); ioAdd(new IO("K1",trS("K1"),IO::Real,IO::Default,"1")); ioAdd(new IO("K2",trS("K2"),IO::Real,IO::Default,"1")); ioAdd(new IO("K3",trS("K3"),IO::Real,IO::Default,"0")); ioAdd(new IO("K4",trS("K4"),IO::Real,IO::Default,"1")); } string name( ) { return _("Flow"); } string descr( ) { return _("Calculation of the gas flow:\n" "f = K1*((K3+K4*x)^K2);"); } void calc( TValFunc *v ) { v->setR(0, v->getR(2)*pow(v->getR(4)+v->getR(5)*v->getR(1),v->getR(3))); } }; //********************************************************************* //* Sum+mult * //* Formula: out = in1_1*in1_2*(in1_3*in1_4+in1_5) + * //* in2_1*in2_2*(in2_3*in2_4+in2_5) + * //* in3_1*in3_2*(in3_3*in3_4+in3_5) + * //* in4_1*in4_2*(in4_3*in4_4+in4_5); * //********************************************************************* class SumMult : public TFunction { public: SumMult( ) : TFunction("sum_mult",SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in1_"+i2s(iC)).c_str(),(_("Input 1.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in3_"+i2s(iC)).c_str(),(_("Input 3.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Sum and multiplicating"); } string descr( ) { return _("Sum with multiplication of values group:\n" "out = in1_1*in1_2*(in1_3*in1_4+in1_5) + in2_1*in2_2*(in2_3*in2_4+in2_5) +\n" " in3_1*in3_2*(in3_3*in3_4+in3_5) + in4_1*in4_2*(in4_3*in4_4+in4_5);"); } void calc( TValFunc *v ) { double t1 = v->getR(1)*v->getR(2)*(v->getR(3)*v->getR(4)+v->getR(5)); double t2 = v->getR(6)*v->getR(7)*(v->getR(8)*v->getR(9)+v->getR(10)); double t3 = v->getR(11)*v->getR(12)*(v->getR(13)*v->getR(14)+v->getR(15)); double t4 = v->getR(16)*v->getR(17)*(v->getR(18)*v->getR(19)+v->getR(20)); v->setR(0, t1+t2+t3+t4); } }; //********************************************************************* //* Sum+div * //* Formula: out = in1_1*in1_2*(in1_3+in1_4/in1_5) + * //* in2_1*in2_2*(in2_3+in2_4/in2_5) + * //* in3_1*in3_2*(in3_3+in3_4/in3_5) + * //* in4_1*in4_2*(in4_3+in4_4/in4_5); * //********************************************************************* class SumDiv : public TFunction { public: SumDiv( ) : TFunction("sum_div",SSPC_ID) { ioAdd(new IO("out",trS("Output"),IO::Real,IO::Return,"0")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in1_"+i2s(iC)).c_str(),(_("Input 1.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in2_"+i2s(iC)).c_str(),(_("Input 2.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in3_"+i2s(iC)).c_str(),(_("Input 3.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); for(int iC = 1; iC <= 5; iC++) ioAdd(new IO(("in4_"+i2s(iC)).c_str(),(_("Input 4.")+i2s(iC)).c_str(),IO::Real,IO::Default,"1")); } string name( ) { return _("Sum with division"); } string descr( ) { return _("Sum with division of values group:\n" "out = in1_1*in1_2*(in1_3+in1_4/in1_5) + in2_1*in2_2*(in2_3+in2_4/in2_5) +\n" " in3_1*in3_2*(in3_3+in3_4/in3_5) + in4_1*in4_2*(in4_3+in4_4/in4_5);"); } void calc( TValFunc *v ) { double t1 = v->getR(1)*v->getR(2)*(v->getR(3)+v->getR(4)/v->getR(5)); double t2 = v->getR(6)*v->getR(7)*(v->getR(8)+v->getR(9)/v->getR(10)); double t3 = v->getR(11)*v->getR(12)*(v->getR(13)+v->getR(14)/v->getR(15)); double t4 = v->getR(16)*v->getR(17)*(v->getR(18)+v->getR(19)/v->getR(20)); v->setR(0, t1+t2+t3+t4); } }; //********************************************************************* //* Lag * //* Formula: y = y - Klag*( y - x ); * //********************************************************************* class Lag : public TFunction { public: Lag( ) : TFunction("lag",SSPC_ID) { ioAdd(new IO("y",trS("Y"),IO::Real,IO::Return,"0")); ioAdd(new IO("x",trS("X"),IO::Real,IO::Default,"0")); ioAdd(new IO("Klag",trS("Klag"),IO::Real,IO::Default,"0.1")); } string name( ) { return _("Lag"); } string descr( ) { return _("Delay of the change of a variable, practically it is a filter without binding to time:\n" "y = y - Klag*( y - x );"); } void calc( TValFunc *v ) { double y = v->getR(0); v->setR(0, y - v->getR(2)*(y-v->getR(1))); } }; } //End namespace virtual #endif //LIBCOMPL1_H