Hello, I would like to see if anyone can give me some pointers on how to optimize this function block that I have written for a Omron CJ2M. It is just simple piecewise line formula, but the only way I know to handle the piecewise portion is with a slew of if-then statements, which is gobbling up more memory than I can spare. This FB consumes 989 steps and 78 non-retain memory locations! As you can see, I'm not the text-based programming savant. please help!
I see one obvious thing: defining constants like "X2_Neg80:= -80.0;" and then using X2_Neg80 in the code when I could just use -80.0, but I don't think that's the bulk of the problem. I think the problem is deeper and there is an entirely different, better way to write the code from the ground up. I just don't know what that might be.
Code:
(*
This function block takes a bipolar floating point -100 to +100 reference with zero
deadband and converts it to a unipolar integer reference with deadband compensation
and multipoint mapping linearization for a bidirectional analog proportional flow control
valve with nonlinear output.
(EX: 2500 [full reverse] to 7500 [full forward] with deadband [zero speed] from 4000 to 6000)
(*define variables and constants:*)
X1_Neg100:= -100.0;
Y1_NEG100Float:= INT_TO_REAL(NEG100);
X2_Neg80:= -80.0;
Y2_NEG80Float:= INT_TO_REAL(NEG80);
X3_Neg60:= -60.0;
Y3_NEG60Float:= INT_TO_REAL(NEG60);
X4_Neg40:= -40.0;
Y4_NEG40Float:= INT_TO_REAL(NEG40);
X5_Neg20:= -20.0;
Y5_NEG20Float:= INT_TO_REAL(NEG20);
X6_Neg1:= -1.0;
Y6_NEG1Float:= INT_TO_REAL(NEG1);
X7_Pos1:= +1.0;
Y7_POS1Float:= INT_TO_REAL(POS1);
X8_Pos20:= +20.0;
Y8_POS20Float:= INT_TO_REAL(POS20);
X9_Pos40:= +40.0;
Y9_POS40Float:= INT_TO_REAL(POS40);
X10_Pos60:= +60.0;
Y10_POS60Float:= INT_TO_REAL(POS60);
X11_Pos80:= +80.0;
Y11_POS80Float:= INT_TO_REAL(POS80);
X12_Pos100:= +100.0;
Y12_POS100Float:= INT_TO_REAL(POS100);
(*INPUT CONDITIONING - invert incoming value an apply speed limit if speed limit if desired*)
IF Invert = TRUE THEN
IF SpeedLimit = TRUE THEN
InputFloat_X:= Input_float100*(-1.0)*ScalingFactor*(0.5);
ELSE
InputFloat_X:= Input_float100*(-1.0)*ScalingFactor;
END_IF;
ELSE
IF SpeedLimit = TRUE THEN
InputFloat_X:= Input_float100*ScalingFactor*(0.5);
ELSE
InputFloat_X:= Input_float100*ScalingFactor;
END_IF;
END_IF;
(*calculate slope and y-intercept of line segments for positive range and negative range:*)
IF Input_float100 > X11_Pos80 THEN
ValveCenter:= FALSE;
M_Slope:= (Y12_POS100Float-Y11_POS80Float)/(X12_Pos100-X11_Pos80);
Y_Int_B:= Y12_POS100Float-(M_Slope*X12_Pos100);
ELSIF Input_float100 < X11_Pos80 AND Input_float100 > X10_Pos60 THEN
ValveCenter:= FALSE;
M_Slope:= (Y11_POS80Float-Y10_POS60Float)/(X11_Pos80-X10_Pos60);
Y_Int_B:= Y11_POS80Float-(M_Slope*X11_Pos80);
ELSIF Input_float100 < X10_Pos60 AND Input_float100 > X9_Pos40 THEN
ValveCenter:= FALSE;
M_Slope:= (Y10_POS60Float-Y9_POS40Float)/(X10_Pos60-X9_Pos40);
Y_Int_B:= Y10_POS60Float-(M_Slope*X10_Pos60);
ELSIF Input_float100 < X9_Pos40 AND Input_float100 > X8_Pos20 THEN
ValveCenter:= FALSE;
M_Slope:= (Y9_POS40Float-Y8_POS20Float)/(X9_Pos40-X8_Pos20);
Y_Int_B:= Y9_POS40Float-(M_Slope*X9_Pos40);
ELSIF Input_float100 < X8_Pos20 AND Input_float100 > X7_Pos1 THEN
ValveCenter:= FALSE;
M_Slope:= (Y8_POS20Float-Y7_POS1Float)/(X8_Pos20-X7_Pos1);
Y_Int_B:= Y8_POS20Float-(M_Slope*X8_Pos20);
ELSIF Input_float100 < X7_Pos1 AND Input_float100 > X6_Neg1 THEN
ValveCenter:= TRUE;
ELSIF Input_float100 < X6_Neg1 AND Input_float100 > X5_Neg20 THEN
ValveCenter:= FALSE;
M_Slope:= (Y6_NEG1Float-Y5_NEG20Float)/(X6_Neg1-X5_Neg20);
Y_Int_B:= Y6_NEG1Float-(M_Slope*X6_Neg1);
ELSIF Input_float100 < X5_Neg20 AND Input_float100 > X4_Neg40 THEN
ValveCenter:= FALSE;
M_Slope:= (Y5_NEG20Float-Y4_NEG40Float)/(X5_Neg20-X4_Neg40);
Y_Int_B:= Y5_NEG20Float-(M_Slope*X5_Neg20);
ELSIF Input_float100 < X4_Neg40 AND Input_float100 > X3_Neg60 THEN
ValveCenter:= FALSE;
M_Slope:= (Y4_NEG40Float-Y3_NEG60Float)/(X4_Neg40-X3_Neg60);
Y_Int_B:= Y4_NEG40Float-(M_Slope*X4_Neg40);
ELSIF Input_float100 < X3_Neg60 AND Input_float100 > X2_Neg80 THEN
ValveCenter:= FALSE;
M_Slope:= (Y3_NEG60Float-Y2_NEG80Float)/(X3_Neg60-X2_Neg80);
Y_Int_B:= Y3_NEG60Float-(M_Slope*X3_Neg60);
ELSIF Input_float100 < X2_Neg80 THEN
ValveCenter:= FALSE;
M_Slope:= (Y2_NEG80Float-Y1_NEG100Float)/(X2_Neg80-X1_Neg100);
Y_Int_B:= Y2_NEG80Float-(M_Slope*X2_Neg80);
END_IF;
(*write valve output*)
IF ValveCenter= TRUE THEN
OutputFloat_Y:= +5000.0;
ELSE
OutputFloat_Y:= M_Slope*InputFloat_X+Y_Int_B;
END_IF;
OutputInt:= REAL_TO_INT(OutputFloat_Y);
I see one obvious thing: defining constants like "X2_Neg80:= -80.0;" and then using X2_Neg80 in the code when I could just use -80.0, but I don't think that's the bulk of the problem. I think the problem is deeper and there is an entirely different, better way to write the code from the ground up. I just don't know what that might be.