Posted 31 Dec 2021 (edited) 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 31 Dec 2021 by NoamC Share this post Link to post Share on other sites
Posted 31 Dec 2021 @NoamC There are function call "MAX_ARR" may be you should use it. Share this post Link to post Share on other sites
Posted 1 Jan 2022 MAX_ARR will only give the highest value in the array or table, and I need several values. Any ideas ? Share this post Link to post Share on other sites
Posted 1 Jan 2022 @NoamC Maybe you compare data from previous data if it is more than last value put it in register. Share this post Link to post Share on other sites
Posted 1 Jan 2022 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 this post Link to post Share on other sites
Posted 1 Jan 2022 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 https://ibb.co/stvtRvj 1 person likes this Share this post Link to post Share on other sites