Trying to enhance my Siemens SCL abilities

ELake20

Lifetime Supporting Member
Join Date
Aug 2003
Location
N. Michigan
Posts
271
I have an application where I need to determine the minimum and maximum value of 6 analog inputs. (known as Cyl1-6 in code) I have it working in ladder with FC25 (Min) and FC27 (Max) but I think this would be a great exercise in SCL. The code I've got compiles, but I think I'm doing something wrong because it won't work.

The idea is to take the minimum and maximum values, toss them out and average the remaining 4. The various compares ensure that I will only have 1 Min and 1 Max. I had it setup with 3 IFs and ELSIFs to eliminate the over abundance of END_IFs. I'm using the Hans Berger SCL book for most of my information. I have a couple examples, but they are mostly just changing data types and doing complex functions that I don't need.

Any help is greatly appreciated!!!

FUNCTION_BLOCK FB1508

TITLE = 'MinMaxEDS'
Name: EDS_TEST
Family: EDS
Author: EML
Version: '0.1' //first attempt

VAR_INPUT

Cyl1 : REAL;
Cyl2 : REAL;
Cyl3 : REAL;
Cyl4 : REAL;
Cyl5 : REAL;
Cyl6 : REAL;
OnlineOffline1 : BOOL;
OnlineOffline2 : BOOL;
OnlineOffline3 : BOOL;
OnlineOffline4 : BOOL;
OnlineOffline5 : BOOL;
OnlineOffline6 : BOOL;

END_VAR

VAR_OUTPUT
EDS_SP : REAL; // Setpoint for EDS Algorithm
Cyl1IsMax : BOOL;
Cyl2IsMax : BOOL;
Cyl3IsMax : BOOL;
Cyl4IsMax : BOOL;
Cyl5IsMax : BOOL;
Cyl6IsMax : BOOL;
Cyl1IsMin : BOOL;
Cyl2IsMin : BOOL;
Cyl3IsMin : BOOL;
Cyl4IsMin : BOOL;
Cyl5IsMin : BOOL;
Cyl6IsMin : BOOL;
TotalVal : REAL;
AverageVal : REAL;

END_VAR



//Determine Maximum Value
IF Cyl1 > Cyl2 AND Cyl1 > Cyl3 AND Cyl1 > Cyl4 AND Cyl1 > Cyl5 AND Cyl1 > Cyl6 THEN // Cylinder 1 is Maximum Value Determination
Cyl1IsMax := TRUE;

IF Cyl2 > Cyl1 AND Cyl2 > Cyl3 AND Cyl2 > Cyl4 AND Cyl2 > Cyl5 AND Cyl2 > Cyl6 THEN // Cylinder 2 is Maximum Value Determination
Cyl2IsMax := TRUE;

IF Cyl3 > Cyl1 AND Cyl3 > Cyl2 AND Cyl3 > Cyl4 AND Cyl3 > Cyl5 AND Cyl3 > Cyl6 THEN // Cylinder 3 is Maximum Value Determination
Cyl3IsMax := True;

IF Cyl4 > Cyl1 AND Cyl4 > Cyl2 AND Cyl4 > Cyl3 AND Cyl4 > Cyl5 AND Cyl4 > Cyl6 THEN // Cylinder 4 is Maximum Value Determination
Cyl4IsMax := True;

IF Cyl5 > Cyl1 AND Cyl5 > Cyl2 AND Cyl5 > Cyl3 AND Cyl5 > Cyl4 AND Cyl5 > Cyl6 THEN // Cylinder 5 is Maximum Value Determination
Cyl5IsMax := True;

IF Cyl6 > Cyl1 AND Cyl6 > Cyl2 AND Cyl6 > Cyl3 AND Cyl6 > Cyl4 AND Cyl6 > Cyl5 THEN // Cylinder 6 is Maximum Value Determination
Cyl6IsMax := True;

//Determine Minimum Value
IF Cyl1 < Cyl2 AND Cyl1 < Cyl3 AND Cyl1 < Cyl4 AND Cyl1 < Cyl5 AND Cyl1 < Cyl6 THEN // Cylinder 1 is Minimum Value Determination
Cyl1IsMin := TRUE;

IF Cyl2 < Cyl1 AND Cyl2 < Cyl3 AND Cyl2 < Cyl4 AND Cyl2 < Cyl5 AND Cyl2 < Cyl6 THEN // Cylinder 2 is Minimum Value Determination
Cyl2IsMin := TRUE;

IF Cyl3 < Cyl1 AND Cyl3 < Cyl2 AND Cyl3 < Cyl4 AND Cyl3 < Cyl5 AND Cyl3 < Cyl6 THEN // Cylinder 3 is Minimum Value Determination
Cyl3IsMin := True;

IF Cyl4 < Cyl1 AND Cyl4 < Cyl2 AND Cyl4 < Cyl3 AND Cyl4 < Cyl5 AND Cyl4 < Cyl6 THEN // Cylinder 4 is Minimum Value Determination
Cyl4IsMin := True;

IF Cyl5 < Cyl1 AND Cyl5 < Cyl2 AND Cyl5 < Cyl3 AND Cyl5 < Cyl4 AND Cyl5 < Cyl6 THEN // Cylinder 5 is Minimum Value Determination
Cyl5IsMin := True;

IF Cyl6 < Cyl1 AND Cyl6 < Cyl2 AND Cyl6 < Cyl3 AND Cyl6 < Cyl4 AND Cyl6 < Cyl5 THEN // Cylinder 6 is Minimum Value Determination
Cyl6IsMin := True;


//Subtract Minimum & Maximum and get Total Value
IF Cyl1IsMin = TRUE OR Cyl1IsMax = True THEN TotalVal := Cyl2 + Cyl3 + Cyl4 + Cyl5 + Cyl6;
IF Cyl2IsMin = TRUE OR Cyl2IsMax = True THEN TotalVal := Cyl1 + Cyl3 + Cyl4 + Cyl5 + Cyl6;
IF Cyl3IsMin = True OR Cyl3IsMax = True THEN TotalVal:= Cyl1 + Cyl2 + Cyl4 + Cyl5 + Cyl6;
IF Cyl4IsMin = True OR Cyl4IsMax = True THEN TotalVal := Cyl1 + Cyl2 + Cyl3 + Cyl5 + Cyl6;
IF Cyl5IsMin = True OR Cyl5IsMax = True THEN TotalVal := Cyl1 + Cyl2 + Cyl3 + Cyl4 + Cyl6;
IF Cyl6IsMin = True OR Cyl6IsMax = True THEN TotalVal := Cyl1 + Cyl2 + Cyl3 + Cyl4 + Cyl5;

//Divide Total Value by 4 to get Average Value
AverageVal := TotalVal / 4;






END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;
END_IF;


END_FUNCTION_BLOCK
 
Calculate Max using SCL

Hi there,
When in SCL think like SCL !! ;)

ok I gave a try and here it is:

Code:
VAR_input
Ai:ARRAY[1..6] OF INT;
END_VAR

VAR_output
Ai_max:INT;
Ai_min:INT;
END_VAR




VAR_TEMP
    i:INT;
    x:INT;
    y:INT;
    konst:int;
    m:BOOL;
END_VAR

BEGIN
konst:=6;

x:=1;
while x<konst DO
 y:=x+1; 
 WHILE Ai[x]> Ai[y]AND y<=konst DO
 y:=y+1;
 m:=1;
END_WHILE;
//when false
  IF m=0 AND x<=konst THEN
     x:=x+1;
  END_IF;
//when true  
  IF m=1 AND y<=konst THEN
     x:=y;
     m:=0;
  END_IF; 

END_WHILE; 
y:=x;  
Ai_max:=Ai[y];


END_FUNCTION

This is not working code !!
Some problem out there with VAR_input.
But will give you idea as how to proceed !!
Note: This is only to calculate the Max value !!
 
What about using min and max, you have those in scl too.. Then you can just add up all and subtract min+max then divide by four to get average.
 
Agreed...

Code:
FUNCTION_BLOCK FB1508
VAR_INPUT
Cyl1 : REAL;
Cyl2 : REAL;
Cyl3 : REAL;
Cyl4 : REAL;
Cyl5 : REAL;
Cyl6 : REAL;
END_VAR
VAR_OUTPUT
AverageVal : REAL;
END_VAR

Begin
AverageVal := (Cyl1 + Cyl2 + Cyl3 + Cyl4 + Cyl5 + Cyl6
              - MIN(In1:=Cyl1, In2:=Cyl2,In3:=Cyl3,In4:=Cyl4,In5:=Cyl5,In6:=Cyl6)
              - MAX(In1:=Cyl1, In2:=Cyl2,In3:=Cyl3,In4:=Cyl4,In5:=Cyl5,In6:=Cyl6))/4.0;
END_FUNCTION_BLOCK:
 
Hello :
please could you help me?:
I have PROFIBUS Mono System Network(One Master(CPU313C-2Dp) & Tow Slave's(CPU313C-2Dp))when any Slave go out from the service ,the Master goes to Stop Mode and the second slave still in RUN Mode.
but I want to keep the Master in RUN Mode too.
What can I do?
 
I'm trying to take it to the next level now. Operator can disable individual cylinders and I want to remove those from the average calculation.

I wish it were as simple as Cyl1 NOT Offline1 + Cyl2 NOT Offline2 etc. This has been a great exercise and it is so much cleaner than doing this in ladder!

My solution to modifying the divisor is this:

OfflineParkCount := (ParkCount + OfflineCount);

IF OfflineParkCount = 0 THEN AverageDivisor := 4;
END_IF;
IF OfflineParkCount = 1 THEN AverageDivisor := 3;
END_IF;
IF OfflineParkCount = 2 THEN AverageDivisor := 2;
END_IF;
IF OfflineParkCount = 3 THEN AverageDivisor := 1;
END_IF;
 
Only 2 can be disabled or parked. I bring in both the disable and park and sum them to get a total, I made the divisor = 1 to cover myself in the event something freakish happens...
 
Last edited:
Code:
OfflineParkCount := (ParkCount + OfflineCount);  

IF OfflineParkCount = 0 THEN AverageDivisor := 4;
END_IF;
IF OfflineParkCount = 1 THEN AverageDivisor := 3;
END_IF;
IF OfflineParkCount = 2 THEN AverageDivisor := 2;
END_IF;
IF OfflineParkCount = 3 THEN AverageDivisor := 1;
END_IF;
Try using the right tools (statements) for the job. It'll make the code so much more readable. (part of the learning process)

Code:
CASE (ParkCount + OfflineCount) OF
  0    : AverageDivisor := 4;
  1    : AverageDivisor := 3;
  2    : AverageDivisor := 2;
  ELSE : AverageDivisor := 1;
END_CASE;
 
Last edited:
Thanks Jeebs I'm working on it :nodi:

This looks a little better IMO
AverageDivisor := (6 - 2 - OfflineParkCount) //Subtract total number of cylinders (6) from (2) since min & max are tossed and subtract OfflineParkCount to get divisor for average.
Now my biggest hurdle is removing the offline/parked cylinder from the min & max determination.

I wish I had some better examples, the Hans Berger book isn't a very good one
 
I kept the arithmetic the same but overwrote the offline cylinder values with a non-offline value.

Code:
FUNCTION_BLOCK FB1508
VAR_INPUT
Cyl1 : REAL;
Cyl2 : REAL;
Cyl3 : REAL;
Cyl4 : REAL;
Cyl5 : REAL;
Cyl6 : REAL;
Offline1:BOOL;
Offline2:BOOL;
Offline3:BOOL;
Offline4:BOOL;
Offline5:BOOL;
Offline6:BOOL;
END_VAR
VAR_OUTPUT
AverageVal : REAL;
END_VAR
VAR
Data:ARRAY[0..15] OF BOOL;
iIndex AT Data:INT;
end_var    
BEGIN
Data[8]:=OffLine1;
Data[9]:=OffLine2;
Data[10]:=OffLine3;
Data[11]:=OffLine4;
Data[12]:=OffLine5;
Data[13]:=OffLine6;
CASE iIndex OF
    1:  Cyl1:=Cyl2;
    2:  Cyl2:=Cyl1;
    4:  Cyl3:=Cyl1;
    8:  Cyl4:=Cyl1;
    16: Cyl5:=Cyl1;
    32: Cyl6:=Cyl1;
    3:  Cyl1:=Cyl3;Cyl2:=Cyl3;
    5:  Cyl1:=Cyl2;Cyl3:=Cyl2;
    9:  Cyl1:=Cyl2;Cyl4:=Cyl2;
    17: Cyl1:=Cyl2;Cyl5:=Cyl2;
    33: Cyl1:=Cyl2;Cyl6:=Cyl2;
    6:  Cyl2:=Cyl1;Cyl3:=Cyl1;
    10: Cyl2:=Cyl1;Cyl4:=Cyl1;
    18: Cyl2:=Cyl1;Cyl5:=Cyl1;
    34: Cyl2:=Cyl1;Cyl6:=Cyl1;
    12: Cyl3:=Cyl1;Cyl4:=Cyl1;
    20: Cyl3:=Cyl1;Cyl5:=Cyl1;
    36: Cyl3:=Cyl1;Cyl6:=Cyl1;
    24: Cyl4:=Cyl1;Cyl5:=Cyl1;
    40: Cyl4:=Cyl1;Cyl6:=Cyl1;
    48: Cyl5:=Cyl1;Cyl6:=Cyl1;
END_CASE;    
AverageVal := (Cyl1 + Cyl2 + Cyl3 + Cyl4 + Cyl5 + Cyl6
              - MIN(In1:=Cyl1, In2:=Cyl2,In3:=Cyl3,In4:=Cyl4,In5:=Cyl5,In6:=Cyl6)
              - MAX(In1:=Cyl1, In2:=Cyl2,In3:=Cyl3,In4:=Cyl4,In5:=Cyl5,In6:=Cyl6))/4.0;
END_FUNCTION_BLOCK:
 

Similar Topics

I can't seem to get the Panel View Plus 7 standard edition to downgrade to V_11, when I check the AB downloads and compatibility websites for this...
Replies
1
Views
97
Hi I used to be able to launch PLCsim without any problem. Now it tells me " STEP 7 Professional Licence is required to simulate this PLC"...
Replies
15
Views
454
Hello! When trying to load the hardware configuration I get error 0050-133 2 2458, check the diagnostic buffer. When checking the buffer, it says...
Replies
4
Views
128
We have a keg check weigher that that lost a fight to a forklift. The scale was previously a Systec IT3000, which was the only PROFIBUS slave...
Replies
5
Views
646
Back
Top Bottom