# Sorting Memory Words

## 6 posts in this topic

Hey Guys,

Modicon M221 PLC, programming with Machine Expert.

I have a project that I must create shifts for heating elements, requiring that some heating elements, those who were on for the longest period, do not turn on in the next shift.

I'm looking for a sorting mechanism to determine what %MW (6 words of 8 total) have the largest value.

I would like an array of 8 words, sort them, and retrieve the highest 6 or highest 4 or highest 2.

Thanks.

Edited by NoamC

##### Share on other sites

@NoamC There are function call "MAX_ARR" may be you should use it.

##### Share on other sites

MAX_ARR will only give the highest value in the array or table, and I need several values.

Any ideas ?

##### Share on other sites

@NoamC Maybe you compare data from previous data if it is more than last value put it in register.

##### Share on other sites

I'm not a Schneider guy, so I can make an example for you, but I would open-code a continuous search loop, examining one array element per scan.  You'd need seven registers for indirection into the array:

• Loop index "idx"
• Temporary index for largest "t0"
• Temporary index for next largest "t1"
• Result index for largest "r0"
• Result index for next largest "r1"
• Shift index for largest "s0"
• Shift index for next largest "s1"

All but "idx" would be retentive.  "idx" would startup pointing to the first array element (0?).

Pythonish pseudocode:

```if idx != t0 and array[idx] > array[t0]:
t1 = t0
t0 = idx
if idx != t0 and array[idx] > array[t1]:
t1 = idx
idx += 1
if idx >= len(array):
idx = 0
r0 = t0
r1 = t1
if newShift:
s0 = r0
s1 = r1```

Your heating element logic would disable when that heater's index is in s0 or s1.

##### Share on other sites

not Schneider guy either but here is a generic example in structured text for consideration. since it does not rely on specialized instruction, this is easy to implement on any platform. note that it does use simple bubble sort but this is fine when data set that is not big (and 8 elements is very small).

```VAR
PUMPS_ENABLED:INT;
PUMP_RUN : ARRAY[1..8] OF BOOL;
AGE_MEASURED :ARRAY[1..8] OF REAL;
AGE_SORTED :ARRAY[1..8] OF REAL;
INDEX : ARRAY[1..8] OF INT;
TMP_REAL:REAL;
TMP_INT:INT;
I:INT;
J:INT;
END_VAR

// assume some random data (before sorting...)
// this set is normally obtained by using retentive
// timer or counter to keep track of each pump age

AGE_MEASURED[1]:=763.91;
AGE_MEASURED[2]:=8161.8;
AGE_MEASURED[3]:=1008.9;
AGE_MEASURED[4]:=6731.8;
AGE_MEASURED[5]:=450.75;
AGE_MEASURED[6]:=108.3;
AGE_MEASURED[7]:=4400.18;
AGE_MEASURED[8]:=9250.75;

// Initialize sort data before sorting
FOR i:=1 TO 8 BY 1 DO
AGE_SORTED[i]:=AGE_MEASURED[i];
INDEX[i]:=i;
END_FOR

// simultaneously sort both AGE and INDEX arrayes by values in AGE
FOR i:=1 TO 8 BY 1 DO
FOR j:=i+1 TO 8 BY 1 DO
IF AGE_SORTED[i] > AGE_SORTED[j] THEN
// --- swap values for age ---
tmp_real:=AGE_SORTED[i];
AGE_SORTED[i]:=AGE_SORTED[j];
AGE_SORTED[j]:=tmp_real;
// --- also swap value for index ---
tmp_int:=INDEX[i];
INDEX[i]:=INDEX[j];
INDEX[j]:=tmp_int;
END_IF
END_FOR
END_FOR

// use index after sorting to control outputs
//PUMPS_ENABLED := 3; // just an example
FOR i:=1 TO 8 BY 1 DO
PUMP_RUN[INDEX[i]]:= i<=PUMPS_ENABLED;
END_FOR```

btw. code to totalize pump age is not shown but this is easy to accomplish in different ways.

for example just use periodic clock (1s or whatever) to increment 8 counters if their pump is active.

also may want to add some code to prevent reaching overflow some some day. for example from time to time (every hour or every day), subtract from each counter value of the lowest counter.

EDIT

attachments are broken again so here is external link showing result

1 person likes this

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account