. Siemens SCL.

: 2013-03-27

: komatic

: SCL



.
, REAL.


array


oscat.de



:
(), , ().




array


( )

, - (pointer) . .

, , .



FUNCTION_BLOCK
VAR_INPUT
pt : POINTER;
_pt AT pt : STRUCT
DBNr: WORD;
Adr: DWORD;
END_STRUCT;
size : INT;
END_VAR

BEGIN

(* *)
rTEST_DB := TEST_DB(DB_NUMBER := _pt.DBNr ,DB_LENGTH := DB_LENGTH ,WRITE_PROT := WRITE_PROT);

(* *)
IF rTEST_DB <> 0 THEN RETURN; END_IF;

(* *)
IF WORD_TO_INT(DB_LENGTH)/4 < size THEN RETURN; END_IF;

(* *)
Adr := DWORD_TO_INT(SHR(IN:=SHL(IN:=_pt.Adr,N:=8),N:=11));

(* code
***********************
***********************
***********************
*)

END_FUNCTION_BLOCK



array


:




FOR i := 0 TO size-1 DO
WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4] := REAL_TO_DWORD(init);
END_FOR;




stop := size - 1;
FOR i := 0 TO stop DO
WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4] := REAL_TO_DWORD(ABS(DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4])));
END_FOR;




stop := size - 1;
FOR i := 0 TO stop DO
WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4] := REAL_TO_DWORD(DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) + X);
END_FOR;




stop := size - 1; //stop := SHR(size,2)-1;
FOR i := 0 TO stop DO
WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4] := REAL_TO_DWORD(DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) * X);
END_FOR;




//this function will calculate the median of a given array.
//in order to do so the ariginal array is sorted and stays sorted after the function finishes
//the function needs to be called: _array_median(adr("array"),sizeof("array"));
//this function will manipulate a given array.
//the function will return the median of the original array.
//for example [12,0,4,7,1] the median is 4 and the array after the function is called is [0,1,4,7,12]
//
//uses: EVEN [FC76]
// _ARRAY_SORT [FB11]
sort(pt:=pt,size:=size);
stop := size-1;
IF even(stop) THEN
median := DWORD_TO_REAL(WORD_TO_BLOCK_DB(at_pt.DBNr).DD[Adr+(stop/2)*4]);
ELSE
i := WORD_TO_INT(SHR(IN:=INT_TO_WORD(stop),N:=1));
median := (DWORD_TO_REAL(WORD_TO_BLOCK_DB(at_pt.DBNr).DD[Adr+i*4]) + DWORD_TO_REAL(WORD_TO_BLOCK_DB(at_pt.DBNr).DD[Adr+(i+1)*4]))/2;
END_IF;




//
//this function will randomly shuffle the elements of an array
//
//uses: RDM2 [FC102]
// RDM [FC101]
// T_PLC_MS [FC64]
// STIME [FB64],IDB_STIME [DB64]
// BIT_COUNT [FC291]
// FRACT [FC83]
//

stop := size - 1;//WORD_TO_INT(SHR(IN:=INT_TO_WORD(size),N:=2))-1;
FOR i := 0 TO stop DO
pos := RDM2(last:=i+pos,low:=0,high:=stop);
(* swap elements *)
temp := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4] := WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+pos*4];
WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+pos*4] := REAL_TO_DWORD(temp);
END_FOR;




//this function will sort a given array.
//the function needs to be called: _array_sort(adr("array"),sizeof("array"));
//this function will manipulate a given array.
//the function will not return anything except true, it will instead manipulate the original array.

links := 1; (* Anfangselement des Arrays *)
rechts := WORD_TO_INT(SHR(IN:=INT_TO_WORD(size),N:=2)); (* Endelement des Arrays *)
stack_count := 1; (* Laufvariable Stack *)

WHILE NOT ende_aussen DO (* uere Schleife *)
IF links < rechts THEN
pivot := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[(Adr+WORD_TO_INT(SHR(IN:=INT_TO_WORD(rechts+links),N:=1)))*4]); (* Wert des mittleren Elements als Pivot-Wert *)
i := links -1;
j := rechts +1;

(* innere Schleife, teile Feld *)
ende_innen := FALSE;
REPEAT

(* steigende Reihenfolge *)
REPEAT i := i+1; UNTIL (DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[(Adr+i)*4]) >= pivot) OR NOT (i < rechts) END_REPEAT;
REPEAT j := j-1; UNTIL (DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[(Adr+j)*4]) <= pivot) OR NOT (j > links) END_REPEAT;


(*sinkende Reihenfolge *)
(* REPEAT i := i+1; UNTIL (PT^[i] <= pivot) OR NOT (i < rechts) END_REPEAT *)
(* REPEAT j := j-1; UNTIL (PT^[j] >= pivot) OR NOT (j > links) END_REPEAT *)

IF i >= j THEN
ende_innen := TRUE;
ELSE
tmp := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[(Adr+j)*4]);
WORD_TO_BLOCK_DB(_pt.DBNr).DD[(Adr+j)*4] := WORD_TO_BLOCK_DB(_pt.DBNr).DD[(Adr+i)*4];
WORD_TO_BLOCK_DB(_pt.DBNr).DD[(Adr+i)*4] := REAL_TO_DWORD(tmp);
END_IF;

UNTIL ende_innen END_REPEAT;

(* Push stack *)
stack[stack_count] := rechts; (* rechten Teil spter sortieren *)
IF Stack_count < 32 THEN
stack_count := stack_count +1;
ELSE
ende_aussen := TRUE;
SORT := FALSE; (* Fehler: Stack zu klein *)
END_IF;

(* linken Teil sortiern *)
rechts := MAX(IN1:=links,IN2:=i-1);

ELSE

IF stack_count = 1 THEN
ende_aussen := TRUE;
ELSE

links := rechts+1;

(* pop stack *)
stack_count := stack_count -1; (* jetzt rechten Teil sortierne *)
rechts:= stack[stack_count];
END_IF;

END_IF;

END_WHILE;




array


:






_max := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]);
FOR i := 1 TO size-1 DO
IF DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) > _max THEN
_max := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
END_IF;
END_FOR;




_min := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]);
FOR i := 1 TO size-1 DO
IF DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) < _min THEN
_min := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
END_IF;
END_FOR;




stop := size-1;
avg := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]);
FOR i := 1 TO stop DO
avg := avg + DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
END_FOR;
avg := avg / INT_TO_REAL(stop + 1);



sum := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]);
FOR i := 1 TO size-1 DO
sum := sum + DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
END_FOR;



(geometric average)


//this function will calculate the geometric average of a given array.
//the function needs to be called: array_avg(adr("array"),sizeof("array"));
//
//uses: SQRTN [FC112]
//

stop := size - 1;
_GAV := 1.0;
FOR i := 0 TO stop DO
IF DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) > 0.0 THEN
_GAV := _GAV * DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
ELSE
_GAV := 0.0;
RETURN;
END_IF;
END_FOR;
_GAV := SQRTN(X:=_GAV,N:=stop+1);



(harmonic average)


//this function will calculate the harmonic average of a given array.
//the function needs to be called:array_avg(adr("array"),sizeof("array"));
//because this function works with pointers its very time efficient and it needs no extra memory.
//

stop := size - 1;
FOR i := 0 TO stop DO
IF DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) <> 0.0 THEN
_HAV := _HAV + 1.0/DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
ELSE
_HAV := 0.0;
RETURN;
END_IF;
END_FOR;
_HAV := (INT_TO_REAL(stop) + 1.0) / _HAV;



(standard deviation)


(* at first we calculate the arithmetic average of the array *)

stop := (size - 1) / 1;
avg := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]);
FOR i := 1 TO stop DO
avg := avg + DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
END_FOR;
avg := avg / (stop + 1);

(* in a second run we calculate the variance of the array *)

_var := (DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]) - avg) ** 2;
FOR i := 1 TO stop DO
_var := _var + ((DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) - avg) ** 2);
END_FOR;
_var := _var / stop;

(* standard deviation is simply the square root of the variance *)

sdv := SQRT(_var);



(spread)


//this function will calculate the spread of a given array.
//the function needs to be called: array_spr(adr("array"),sizeof("array"));
//for example: spread of [12,0,4,1,7] is 12 - 0 = 12.

stop := (size - size / size);
array_min := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]);
array_max := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]);
FOR i := 1 TO stop DO
IF DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) > array_max THEN
array_max := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
ELSIF DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) < array_min THEN
array_min := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
END_IF;
END_FOR;
spr := array_max - array_min;



(trend)


//this function will calculate the trend of a given array.
//trend will calculate the avg of the first half of the array and then the avg of the second half, trend = avg2 - avg1.
//for example: [0,1,4,5,3,4,6,3] = 4 - 2.5 = 1.5
//
//uses: EVEN [FC76]
//

stop := size - 1;
stop2 := stop / 2;
FOR i := 0 TO stop2 DO x := x - DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]); END_FOR;
IF even(stop) THEN
FOR i := stop2 TO stop DO X := X + DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]); END_FOR;
ELSE
FOR i := stop2 + 1 TO stop DO X := X + DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]); END_FOR;
END_IF;
trend := x / INT_TO_REAL(stop2 + 1);



(variance)



stop := size - 1;
avg := DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]);
FOR i := 1 TO stop DO
avg := avg + DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]);
END_FOR;
avg := avg / (stop + 1);

(* in a second run we calculate the variance of the array *)

_var := (DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]) - avg) * (DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+0]) - avg);
FOR i := 1 TO stop DO
_var := _var + (DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) - avg) * (DWORD_TO_REAL(WORD_TO_BLOCK_DB(_pt.DBNr).DD[Adr+i*4]) - avg);
END_FOR;
_var := _var / INT_TO_REAL(stop);



S7 (oscat.de)


oscat_basic_332_s7.zip (1.8Mb)







: 6711

: OldBell    : 2018-07-14

, weit for ? .

:

(4000 max):

: