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

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.

agreed.

I did notice that RSLogix only displays whole numbers. So a value of 1 = 1. And a value of 0.1=1. If true, then all my values would either be a 0 or 1. This is only a theory, i have not yet tested it.
 
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?
Yes. this is the grand plan.

I am open to optimisation though. I have learnt so much through this thread.
 
I did notice that RSLogix only displays whole numbers.
That should be only true when the tag being displayed is an integer (INT, SINT, DINT, UINT, USINT, UDINT). Make the Destination of the AVE instruction be a REAL, and you should see some decimal points (and be able to compare 3/10 to 4/10).
 
Yes. this is the grand plan.

I am open to optimisation though. I have learnt so much through this thread.


Okay then, here are my suggestions:

  • you are only ever doing anything with the statistics at the expiry of the 2s (2000ms) repeating timer, and the .DN of that timer should be 1 for only one scan at a time,
    • so you don't need the CTU built-in one-shot (rising edge) functionality.
      • You can instead use a simple INT[0..15] array to keep track of the counts of the directions, and use the ADD instruction to increment the count-in-this-minute INT tag of the current direction by 1 on that single scan when that .DN is 1
        • Another nice result of this is that you can clear all sixteen INTs in that array with a single FLL instruction e.g. at the start of every minute
    • The same is true, i.e. the .DN is true for only one scan, at the end of every minute (i.e. 30 2s-timer expiries.
  • The same is true for the counts (sums; e.g. last_10minutes_dominant_counts_array[0..15]), for the sixteen compass points' directions, that keep track of how many minutes of the last ten minutes each compass point was dominant.
    • The 10-element FIFO, that is updated once per minute, will
      • FFU the index, [0..15], call it DD_OLDEST, of the dominant direction of the minute that passed ten minutes ago
        • So decrementing last_10minutes_dominant_counts_array[DD_OLDEST] by 1 will adjust that direction's count for that fact that it was the dominant direction 11 minutes ago
      • FFL the index, [0..15], call it DD_NEWEST, of the dominant direction that of the most recent minute
        • So increment last_10minutes_dominant_counts_array[DD_NEWEST] by 1 will adjust that direction's count for that fact that it was the dominant direction in the most recent minute.
    • You will want to initialize the 10-element FIFO with ten invalid values, e.g. -1, which will alert the code to not decrement anything over the first ten minutes
The best part of this will be if the compass point calculation is based on an analog value e.g. a direction in the range [0..360), that you are converting to individual booleans. Instead, simply adding 11.25 to that [0..360)-ranged number to a REAL, then dividing that REAL by 22.5 putting the result in an INT, then bitwise ANDing that INT by 15, will give you the integer direction in the range [0..15] that you can use as an index into the per-minute dominant direction count arrays, and also allow you to keep track of the index with the highest count during that minute, and not have to compare all 16 values to find the dominant direction.
 
Last edited:
Okay then, here are my suggestions:

  • you are only ever doing anything with the statistics at the expiry of the 2s (2000ms) repeating timer, and the .DN of that timer should be 1 for only one scan at a time,
    • so you don't need the CTU built-in one-shot (rising edge) functionality.
      • You can instead use a simple INT[0..15] array to keep track of the counts of the directions, and use the ADD instruction to increment the count-in-this-minute INT tag of the current direction by 1 on that single scan when that .DN is 1
        • Another nice result of this is that you can clear all sixteen INTs in that array with a single FLL instruction e.g. at the start of every minute
    • The same is true, i.e. the .DN is true for only one scan, at the end of every minute (i.e. 30 2s-timer expiries.
  • The same is true for the counts (sums; e.g. last_10minutes_dominant_counts_array[0..15]), for the sixteen compass points' directions, that keep track of how many minutes of the last ten minutes each compass point was dominant.
    • The 10-element FIFO, that is updated once per minute, will
      • FFU the index, [0..15], call it DD_OLDEST, of the dominant direction of the minute that passed ten minutes ago
        • So decrementing last_10minutes_dominant_counts_array[DD_OLDEST] by 1 will adjust that direction's count for that fact that it was the dominant direction 11 minutes ago
      • FFL the index, [0..15], call it DD_NEWEST, of the dominant direction that of the most recent minute
        • So increment last_10minutes_dominant_counts_array[DD_NEWEST] by 1 will adjust that direction's count for that fact that it was the dominant direction in the most recent minute.
    • You will want to initialize the 10-element FIFO with ten invalid values, e.g. -1, which will alert the code to not decrement anything over the first ten minutes
The best part of this will be if the compass point calculation is based on an analog value e.g. a direction in the range [0..360), that you are converting to individual booleans. Instead, simply adding 11.25 to that [0..360)-ranged number to a REAL, then dividing that REAL by 22.5 putting the result in an INT, then bitwise ANDing that INT by 15, will give you the integer direction in the range [0..15] that you can use as an index into the per-minute dominant direction count arrays, and also allow you to keep track of the index with the highest count during that minute, and not have to compare all 16 values to find the dominant direction.
lots to try here.

I will create a working model first. I will then experiment with all of your suggestions after.

Will update with successes or problems.

Thanks again.
 
get your own model working first. then you will have something to compare my ideas against. And if it comes to that, it would not be the first time my ideas were useless.
 
See the attachment.

Since this is simply a pair of cascading histograms, the code can keep track on the fly of which is the dominant wind direction (compass point) over each one- or ten-minute period. This is implemented in RSLogix 500, so it uses Data Files instead of arrays, but the approach would work in RSLogix5000.

Actually, with a 300-element FIFO, the logic for the ten minutes of one-minute samples could be re-configured for ten minutes of two-second samples, and the intermediate one-minute sampling eliminated entirely.


This is an example of something a friend taught me once: when designing a program, they usually start by designing the data structures, as well-designed data structures can result in simpler code.
 
Here it is: the dominant wind direction over the past ten minutes and 250* samples (sample time is 2400ms = a rate of 25samples/minute), without binning into one-minute bins (although I understand that OP may want the binning to make the dominant result appear more stable).

Less than a dozen rungs and two dozen instructions, excluding the compass point simulation.

* Arrays larger than 256 add complexity in the SLC/Micrologix environment; with RSLogix5000 the FIFO size is arbitrary.
 
This topic/thread has been addressed before on another forum. A lot of the same concerns came up. Espicially the on one about wind gusts. I think the solution was to integrate the speed as a function of time. A wind gust might have a high value but only for a short time. This way more consistent readings are weighted more..
 
yeah, lies, damn lies, and statistics ...

I can see it either way; if I was sailing/racing, I would not be as interesting in weighting wind direction by speed.

I am curious what the sensor is like. Is it a wind vane (telltale) with encoder and an anemometer, or 3-D sonic, or what? Does the direction come in as a number [0:360) or is there a contact for each compass point?
 
Last edited:
yeah, lies, damn lies, and statistics ...

I can see it either way; if I was sailing/racing, I would not be as interesting in weighting wind direction by speed.

I am curious what the sensor is like. Is it a wind vane (telltale) with encoder and an anemometer, or 3-D sonic, or what? Does the direction come in as a number [0:360) or is there a contact for each compass point?
It is a weather station. 3 spinning cups on a vertical shaft to measure speed with an arrow on the top to show direction. It also measures rain, temp, humidity.

This unit has been around the block. It is around 30 years old. I bought it from gumtree (craigslist). The seller sold the entire unit to me for 50$. It used to do environmental monitoring for a company that closed. So he had the unit in his shed for years. Then he wanted to be rid of it.

It is an anemometer. Wind direction is measured in 4-20mA, (-32650 < x > 32650). Wind speed signal is from a contact sensor.

I wired it up to my PLC so i can use the input for automation.

In case i did not mention previously, (thread has been going for a while now). I am measuring the direction and speed so that when the conditions are just right, one of the kitchen downlights will light up to tell me it is time for me to get to the water (5min away) and launch my kite.
 
Last edited:
get your own model working first. then you will have something to compare my ideas against. And if it comes to that, it would not be the first time my ideas were useless.

Finally found the time to complete a working model.

Does it work? Yes. I compared my results with the local wind report and it appears to be tracking very accurately.

Could it do with refinement? Most likely.

I have attached a copy of the code. There is a lot of pages, but most of it is repetitive, (16 wind directions). The final layout followed the process flow diagram i sent over a few posts ago.

I made it as neat as i could.

Left some notes.

Please feel free to offer suggestions for streamlining and i will try them out. If for no other reason but to learn more useful coding tricks.

Side note. Before this post, i did not really understand how to use arrays and address indexing. You can see from the final code that i really went to town on the arrays once i got the hang of them. Looking forward to learning more tricks :).
 
Last edited:
Here it is: the dominant wind direction over the past ten minutes and 250* samples (sample time is 2400ms = a rate of 25samples/minute), without binning into one-minute bins (although I understand that OP may want the binning to make the dominant result appear more stable).

Less than a dozen rungs and two dozen instructions, excluding the compass point simulation.

* Arrays larger than 256 add complexity in the SLC/Micrologix environment; with RSLogix5000 the FIFO size is arbitrary.
I tried reading it. I must admit, i am not as familiar with the Logix500 environment.

Unfortunately i did not understand it easily.

I might revisit it another time.
 
I tried reading it. I must admit, i am not as familiar with the Logix500 environment.

Unfortunately i did not understand it easily.

I might revisit it another time.

Yeah, I tend to write compact code that does a lot in a few instructions. For example, my two rungs 0003 and 0004 with seven instructions in LAD 6 (Ladder Subroutine 6) do pretty much the same task as your roughly two dozen rungs 29 through 53 with ~eighty instructions. Also some of the comments in my initial ten one-minute dominants approach were not rewritten in the latter ten-minute dominant approach.

But in this case there is nothing that is hard to understand or in any way obfuscated; the main difference between my code and yours is the underlying data model, which means my code much less to do.

RSLogix 500 was, I think, the precursor to Logix 5000. So if you can read the latter you can read the former. All of the instructions I used in 500 are either identical or nearly so to those for 5k. Also, you should ignore LAD 4, which emulates variable wind direction over time via a pseudo-random algorithm so I can test the rest of the code.

The main difference is the data ("variables") in 500 are "file-based," and the data in 5k are tag-based. In 500, if you look at the green symbols above each instruction, associated with the output of that instruction, you can usually think of those symbols as tag names.

So, where a 5000 program might have a Boolean variable (tag) with the name OSR_Trig_FFL_Wind_Dominant, 500 would need to use the boolean data file, B3, and bit B3:2/1 would be designated to represent the quantity OSR_Trig_FFL_Wind_Dominant (Boolean Data file 3, Word at offset 2, Bit-in-word at offset 1). The other bits in B3 would be available for other purposes, assigned by the programmer. For an INT, I use the 16-bit Integer files N7:

  • N7:0 (symbol COMPASS_POINT_SAMPLE) is the most-recently sampled wind direction
    • updated every 2.4s
      • = 2400ms, or
      • 25 times per minute, and
      • 250 times over ten minutes
    • value of 0 for North, of 1 for NNE, ..., of 8 for South, ..., of 15 for NNW
  • N7:1 (symbol 10MIN_DOMINANT) is the dominant wind direction (0-15) over the past 10 minutes
  • N7:2 (symbol LOOP_INDEX) is the step counter for the loop.
  • N254 is the Data File, with 251 elements, that is the FIFO of the past ten minutes of wind direction samples (250 values from N7:0)
    • N254:0 is the first value in the FIFO, so it is the oldest sample and the one that is being removed (First Out)
    • N254:250 is the last value in the FIFO, so it is the newest sample and the one that is being added (First In)
  • N253 is the Data File, with 16 elements, that is the array of the counts of each wind direction over the past ten minutes
    • N253:0 is the count of 0s (North samples) in FIFO N254
    • N253:1 is the count of 1s (NNE samples) in FIFO N254
    • ...
    • N253:8 is the count of 8s (South samples) in FIFO N254
    • ...
    • N253:15 is the count of 15s (NNW samples) in FIFO N254
    • N253:[N7:1] is the largest value in N253, and is at the index (offset from N253:0) of N7:1, i.e. the count of the dominant wind direction (in N253) over the past ten minutes.
There are no arrays by name in 500 per se, but a single Data File, or contiguous run of elements in a data file, can be used as a de facto array, and enclosing an INT in square brackets (cf. N253:[N7:1] above) in 500 yields more or less equivalent syntax to array_tag in 5k.
 

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,110
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,841
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
2,998
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,319
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
122
Back
Top Bottom