RSLogix5000. How to write Expression to find Greater Than other values

you can't.

You can (i think; consider item (iv) below ;)) create an array of counter structures (cf. here), and each one has a .acc element e.g. So counters[0].acc, counters[1].acc, ..., counters[15].acc.

[+]-counters | counter[16] | ...

eureka!!!

This is what i was looking for.

I will continue plugging away again at the process and work towards the end goal. Will likely come unstuck again and send another callout . Will post final results if i succeed.

Wind Direction array.png
 
See the images below.

The first image counts how many time the wind comes from a given direction; I only used the cardinal compass points (North, East, South West), but of course it could be expanded to additional inter-cardinal points (NNE, NE, ...). The direction indices are 1, 2, 3, and 4 for directions North, East, South, and West, respectively.

The important thing to note is that the cts (Array DINT[1..4]) contains the counts for each direction (cts[1] has the North counts; cts[2], cts[3], and cts[4] for East, South, and West, respectively.
View attachment 62545

CCW was what I had to hand when I did this, I assume it is similar enough to RSLogix to be clear what I am doing. The [sample_trigger] is equivalent to the /DN bit of a one-repeating one-second RSLogix timer.

N.B. [Switch 1] is 1 when the wind is coming from North, [Switch 2] is 1 when the wind is coming from the East, etc.
The second image shows how to determine the direction (N/E/W/S), as a directional index (1/2/3/4), that has the greatest number of counts. I hope it is straightforward enough to understand. To answer the original question from Post #1, we don't need to compare the North count against all 16 counts from NNE, NE, ENE, E, ..., to determine if North is the wind direction with the most counts, then compare the NNE count against N, NE, ENE, ..., etc. It is enough to compare N counts against NNE counts, and save the wind direction of the greater of the two, then compare NE counts against that previous result and update the result, then ENE, etc. Since at any point in that process, the count of the intermediate result (wind direction) cannot be less than any of the previously-tested counts, if the next count tested is greater than the intermediate result, then that next count must be greatest.

That is called the invariant condition of the algorithm: the count of the intermediate direction result is not less than any of the previous directions tested. To initialize the algorithm, we assign 1 (North) as the intermediate result, which meets the invariant condition because no other direction has been tested. Then on each pass of the algorithm, we test a new index, and adjust the intermediate result as needed to maintain the invariant condition.My point is that the code from my other example does exactly this, but in a loop, so there needs to be only one rung branch that does the compare and move sixteen times with a different value of the direction index TEST_INDEX each time (instead of 1, 2, 3, ..._, and the other branches increment the direction index to be tested and repeat (loop) until all direction indices have been tested:

hey BB.

I attempted your suggestion. It took me a good hour just looking at that single rung trying to understand how it works. But i finally understood it.

Then i tried creating it.

Steps i followed:
1. Created an array of 4 counters for testing.
2. Created a tag : Wind_Index
3. Created a tag : WindMax_Index

Both new tags (Wind_Index and WindMax_Index) are BOOL.



My code did not work. I suspect it is because my tags are BOOOL.

Is this the culprit? Or am i doing something else wrong?

Thank you.

Attempt at Array Counter Index.png
 
hey BB.

I attempted your suggestion. It took me a good hour just looking at that single rung trying to understand how it works. But i finally understood it.

Then i tried creating it.

Steps i followed:
1. Created an array of 4 counters for testing.
2. Created a tag : Wind_Index
3. Created a tag : WindMax_Index

Both new tags (Wind_Index and WindMax_Index) are BOOL.



My code did not work. I suspect it is because my tags are BOOOL.

Is this the culprit? Or am i doing something else wrong?

Thank you.
Have thought about it more. It is definitely the BOOL. Because BOOL does not store number. And i need to increment the number to increase the index position being tested.

Will explore more...
 
Have thought about it more. It is definitely the BOOL. Because BOOL does not store number. And i need to increment the number to increase the index position being tested.

Will explore more...

Found the problem (I think). Changed BOOL to INT.

RSLogix seems to like it a lot more.

Will update at next problem...

Attempt at Array Counter Index 2.png
 
See the images below.

The first image counts how many time the wind comes from a given direction; I only used the cardinal compass points (North, East, South West), but of course it could be expanded to additional inter-cardinal points (NNE, NE, ...). The direction indices are 1, 2, 3, and 4 for directions North, East, South, and West, respectively.

The important thing to note is that the cts (Array DINT[1..4]) contains the counts for each direction (cts[1] has the North counts; cts[2], cts[3], and cts[4] for East, South, and West, respectively.
View attachment 62545

CCW was what I had to hand when I did this, I assume it is similar enough to RSLogix to be clear what I am doing. The [sample_trigger] is equivalent to the /DN bit of a one-repeating one-second RSLogix timer.

N.B. [Switch 1] is 1 when the wind is coming from North, [Switch 2] is 1 when the wind is coming from the East, etc.
The second image shows how to determine the direction (N/E/W/S), as a directional index (1/2/3/4), that has the greatest number of counts. I hope it is straightforward enough to understand. To answer the original question from Post #1, we don't need to compare the North count against all 16 counts from NNE, NE, ENE, E, ..., to determine if North is the wind direction with the most counts, then compare the NNE count against N, NE, ENE, ..., etc. It is enough to compare N counts against NNE counts, and save the wind direction of the greater of the two, then compare NE counts against that previous result and update the result, then ENE, etc. Since at any point in that process, the count of the intermediate result (wind direction) cannot be less than any of the previously-tested counts, if the next count tested is greater than the intermediate result, then that next count must be greatest.

That is called the invariant condition of the algorithm: the count of the intermediate direction result is not less than any of the previous directions tested. To initialize the algorithm, we assign 1 (North) as the intermediate result, which meets the invariant condition because no other direction has been tested. Then on each pass of the algorithm, we test a new index, and adjust the intermediate result as needed to maintain the invariant condition.My point is that the code from my other example does exactly this, but in a loop, so there needs to be only one rung branch that does the compare and move sixteen times with a different value of the direction index TEST_INDEX each time (instead of 1, 2, 3, ..._, and the other branches increment the direction index to be tested and repeat (loop) until all direction indices have been tested:
Hey DBB.

I was able to write the code as you had presented it. I was not able to make it work.

Can you please advise if you were able to run the code?

I have begun breaking down your structure into separate rungs to try and troubleshoot. I do not think i can make the code work in its current structure, but i will try restructuring it and see if i can make it work another way.

Will not be as elegant i am sure, but it will be a lot more elegant than my idea 1.0.

Please get back to me if you have any ideas.

Attempt at Array Counter Index 3.png
 
See the images below.

The first image counts how many time the wind comes from a given direction; I only used the cardinal compass points (North, East, South West), but of course it could be expanded to additional inter-cardinal points (NNE, NE, ...). The direction indices are 1, 2, 3, and 4 for directions North, East, South, and West, respectively.

The important thing to note is that the cts (Array DINT[1..4]) contains the counts for each direction (cts[1] has the North counts; cts[2], cts[3], and cts[4] for East, South, and West, respectively.
View attachment 62545

CCW was what I had to hand when I did this, I assume it is similar enough to RSLogix to be clear what I am doing. The [sample_trigger] is equivalent to the /DN bit of a one-repeating one-second RSLogix timer.

N.B. [Switch 1] is 1 when the wind is coming from North, [Switch 2] is 1 when the wind is coming from the East, etc.
The second image shows how to determine the direction (N/E/W/S), as a directional index (1/2/3/4), that has the greatest number of counts. I hope it is straightforward enough to understand. To answer the original question from Post #1, we don't need to compare the North count against all 16 counts from NNE, NE, ENE, E, ..., to determine if North is the wind direction with the most counts, then compare the NNE count against N, NE, ENE, ..., etc. It is enough to compare N counts against NNE counts, and save the wind direction of the greater of the two, then compare NE counts against that previous result and update the result, then ENE, etc. Since at any point in that process, the count of the intermediate result (wind direction) cannot be less than any of the previously-tested counts, if the next count tested is greater than the intermediate result, then that next count must be greatest.

That is called the invariant condition of the algorithm: the count of the intermediate direction result is not less than any of the previous directions tested. To initialize the algorithm, we assign 1 (North) as the intermediate result, which meets the invariant condition because no other direction has been tested. Then on each pass of the algorithm, we test a new index, and adjust the intermediate result as needed to maintain the invariant condition.My point is that the code from my other example does exactly this, but in a loop, so there needs to be only one rung branch that does the compare and move sixteen times with a different value of the direction index TEST_INDEX each time (instead of 1, 2, 3, ..._, and the other branches increment the direction index to be tested and repeat (loop) until all direction indices have been tested:
I created something that is a compromise between elegance and brute force.

Will looke something like this. Only working with 4 counters at this stage, but you can see where i am going with it i am sure.

Will keep thinking how i can loop it as i am very keen to learn how to use loop to cycle through test data.

Attempt at Array Counter Index 4.png
 
rung 22: the canonical way to control when to count or not would be to put a 3 in Array_Counter_Test2.PRE, and then use [XIO Array_Counter_Test2.DN] instead of [LES Array_Counter_Test2.ACC 3].

So the OSF_FL_2sec has a rising edge once every one (or two) seconds? Doesn't that mean it will take three (or six) seconds to latch (eliminate as not the wind with the highest count) three of the four B_Wind_NOT_X bits, and determine which wind has the highest counts? And that three seconds becomes fifteen (or thirty) when the algorithm is applied to sixteen compass points? The algorithm could spend more time with several of the B_Wind_NOT_X bits incorrectly assigned as 0s in the middle of the the cycle than it does with the final correct result.

What causes B_Test_Array[0].4 to become 1, and restart the cycle?

Also, what happens if two or more wind directions have the same counts? Is that result acceptable?
 
rung 22: the canonical way to control when to count or not would be to put a 3 in Array_Counter_Test2.PRE, and then use [XIO Array_Counter_Test2.DN] instead of [LES Array_Counter_Test2.ACC 3].

So the OSF_FL_2sec has a rising edge once every one (or two) seconds? Doesn't that mean it will take three (or six) seconds to latch (eliminate as not the wind with the highest count) three of the four B_Wind_NOT_X bits, and determine which wind has the highest counts? And that three seconds becomes fifteen (or thirty) when the algorithm is applied to sixteen compass points? The algorithm could spend more time with several of the B_Wind_NOT_X bits incorrectly assigned as 0s in the middle of the the cycle than it does with the final correct result.

What causes B_Test_Array[0].4 to become 1, and restart the cycle?

Also, what happens if two or more wind directions have the same counts? Is that result acceptable?
This code is built primarily to verify a working design.

Now that i have verified it, and i think i will use this design until i refine the looping method, i can now refine it to make it fit for purpose.

To answer your questions:
1. Rung 22. Do not quite understand it yet, but i will try and see what happens. I am sure you are right, I do not have the skills yet to understand your description without first trying it.

Although i did write a note for myself to make the following changes next time i do an update, (i went to bed, so no time to update).

Rung 22. Counter to count up every 1 second.
Set counter preset to 4 and change the LES instruction on left of rung to 4.
When 4, all values will become 0, counters will reset, Latched bits will unlatch.
Use XIO to reset this rung

The more i read your instructions, i think we were both thinking the same thing. Which is very positive from my point of view.

2. OSF_FL_2sec is a two second flashing light. So with the design you are looking it, it samples every 2 seconds. This is only for verification so i can see the code working. Will be changing this to 100 milliseconds. Which for 16 wind directions, will take 1.6 seconds to cycle through all the tests. All rungs run simultaneously so it will only every take 1.6 seconds to cycle through all the tests.

3. B_Wind_NOT_X bits. Instead of energixing which wind directions have the highest counts, i am now energising which wind direction does not have the highest count. The wind direction no energised at the end of a cycle is the wind direction with the highest count.

4. Zero values. Zero values are ok as long as at least one of the wind directions has a count value higher than zero.

5. What happens when there are duplicate values? This one i am sort of leaving to chance as i do not think it will be a problem. Reason is, in the final design, wind counters sample the wind direction every 2 seconds, making 30 samples every minute. After 60 seconds, the above "comparison" algorithm is applied to compare which wind direction was dominant in this minute. I expect most of the wind directions to be a zero value and 2 maybe 3 wind directions possessing a count greater than 0. From these 3 wind directions, i expect one direction to be dominant. having 2 duplicate maximum directions would be a surprise. I will run for a while and see if the "surprise" breaks anything... :p
 
Rung 22. Counter to count up every 1 second.
Set counter preset to 4 and change the LES instruction on left of rung to 4.
When 4, all values will become 0, counters will reset, Latched bits will unlatch.
Use XIO to reset this rung


Oh dear. So until the final of four two-second steps per cycle, all of the bits will be in an intermediate state and you will not know which wind direction has had the most samples.


Once the final step executes, you do know which wind direction has had the most samples, but then you unlatch them all. So you will never know the answer for more than one scan (a few ms) out of 4s, or a few ms out of 1.6s when you have the whole thing running.

I think this approach is going to be a dog's breakfast. Still, I encourage you to pursue it, see if you can make it work. Then we'll try something much simpler, that gets the answer in one scan.
 
The goal is to find which tag is the highest, right?


If you can create a FBD rountine, you can use the ESEL (Enhanced Select) function to easily output the highest values of all. It won't sort all values however.
 
Oh dear. So until the final of four two-second steps per cycle, all of the bits will be in an intermediate state and you will not know which wind direction has had the most samples.


Once the final step executes, you do know which wind direction has had the most samples, but then you unlatch them all. So you will never know the answer for more than one scan (a few ms) out of 4s, or a few ms out of 1.6s when you have the whole thing running.

I think this approach is going to be a dog's breakfast. Still, I encourage you to pursue it, see if you can make it work. Then we'll try something much simpler, that gets the answer in one scan.

Not as bad as it might seem in the face of it.

2 seconds sounds like a long time if the compare instructions, which takes 1.6 seconds, ran consecutively 16 times. But they run simultaneously. So the total execution time to complete is only 1.6 seconds total. Only one of the rungs will actually require the 1.6 seconds, it is the rung with the highest count, (dominant wind direction).

Even 1.6 seconds may be a long time in some processes. This process is not so time critical.

Reason is because of how the dominant wind direction will ultimately be measured.

I have attached the flow chart for my strategy to measure the dominant wind direction over a 10 minute real time moving average. So at any given time, a user can view the dominant wind direction in the last 10min.

What we have been working on this entire time is the "Compare Arrays". In the case of the flow chart, there are 2 sets of 16 making a total of 32 compare arrays to be executed.

But they are only executed every 60 seconds.

So 1.6 seconds of execution time is not a lot in comparison.

This still leaves me with 58 seconds of house keeping, (ie. resets, unlatching, counting, etc).

Fortunately i have been working on FIFO for a few weeks now and have applied it in a few of my routines, so i have the hang of it.

The videos i have watched on FIFO have taught me how to find the average in the FIFO array, but none yet has demonstrated how to ADD all the values inside an array. Any suggestions?

Now it is about crunching code. Will work on this over the weekend. We have rain all day tomorrow. I am working a little in the morning, but should be able to work on it in the afternoon. Hopefully finish by end of weekend.

Wind Direction Flow Chart.jpg
 
The videos i have watched on FIFO have taught me how to find the average in the FIFO array, but none yet has demonstrated how to ADD all the values inside an array. Any suggestions?


Umm, an average is the sum (ADDition) of all the FIFO values in the array, divided by the number of values in the array. i.e.

average = sum(array) / N(array)


so, if you have the average, and the number of values in the array, then

sum(array) = average * N(array)


What is the data type of the array, and of the average?

You could also maintain a running sum of the values in the FIFO:

  • Initialize the sum to 0,
  • add to the sum every new value pushed (FFLed) onto the array,
  • subtract from the sum every value popped (FFUed) off of the array
but if you are already doing the average, the formula above might be adequate.
 
Also, since the length of the one-per-minute arrays being averaged is always 10, finding the largest average will yield the same result as finding the largest sum.
 
So, every minute,

  • exactly one of the sixteen 10-element FIFO arrays will
    • have a 1 FFLed onto it, and
    • its oldest value FFUed off of it,
  • and each of the other fifteen 10-element FIFO arrays will
    • have a 0 FFLed onto it,
    • its oldest value FFUed off of it
  • and the 10-element FIFO array with the largest sum (largest number of times it was the dominant wind direction over any of the past ten 1-minute periods) will be declared the dominant wind direction over the previous 10 minutes.
Is that correct?
 
Umm, an average is the sum (ADDition) of all the FIFO values in the array, divided by the number of values in the array. i.e.

average = sum(array) / N(array)


so, if you have the average, and the number of values in the array, then

sum(array) = average * N(array)


What is the data type of the array, and of the average?

You could also maintain a running sum of the values in the FIFO:

  • Initialize the sum to 0,
  • add to the sum every new value pushed (FFLed) onto the array,
  • subtract from the sum every value popped (FFUed) off of the array
but if you are already doing the average, the formula above might be adequate.
i had a feeling this would be the case. I was hoping there was a single instruction that would add the values inside the array that i just did not know about.

Oh well. Will do it this way then.
 

Similar Topics

I am replacing a PLC5 with a 1756-L73 and i am trying to reuse a 1771-DB Basic Module. I am leaving the PLC5 in the chassis setup as RIO adapter...
Replies
7
Views
5,128
Need good example/sample of aoi RSLogix5000 code to read&write through RS232 port on Need good example/sample of aoi RSLogix5000 code to...
Replies
0
Views
1,844
Hey All, As the title states, how do I write a MinorFault generated by an instruction, for example a negative .PRE value was entered for a timer...
Replies
12
Views
3,007
Is it possible to partially restrict the types of communications allowed through a ControlLogix communications module? Ideally I'd like something...
Replies
7
Views
3,331
Hi! So my problem is a little funky, I had Studio 5000 v 24 and 30 installed, but forgot to install RSLogix (which I cannot go without). Is there...
Replies
2
Views
160
Back
Top Bottom