Array Visitors - useful? mad useful? maddeningly useless?

JeremyM

Lifetime Supporting Member
Join Date
May 2014
Location
Dallas, Texas
Posts
1,233
I've been banging my head for a way to generalize data handling in a meaningful way in Logix. What I've concocted so far is the idea of "visitors" to an array that perform tiny roles.

Enter RVIS. This block does all the statistical math on a variably-sized array in a single scan pass. Each scan, it advances exactly one element in the array until reaching the end of the data, then does the math at once to keep the scan time down most of the time.

It can be told to calculate immediately, though...

Enter RCBUF. This block implements the activities of a circular buffer on a variably-sized array. It accepts a command to insert a new element from some command source (fixed pulse generator in this case). When it takes care of the insertion, it raises its Ready signal which is fed to RVIS to coerce a math update.

Does this have potential or are we looking at a heap of madness?

RCBUFVIS.PNG
 
I've been banging my head...

Does this have potential or are we looking at a heap of madness?
Without a doubt a heap of madness.

But it's ladder so it's beautiful, so don't give up. And don't convert it to ST, because, although it would be simple, it would also be so ugly you will be ashamed to look at it.

I'd am curious to see what the actual update in RVIS does, because it might be possible to do incremental updates each time it advances one element, as opposed to doing a long calculation during one scan cycle.
 
I've got an idea on how to achieve array indirection to pull this sort of thing off with UDTs, so that's kind of the source of my madness.

But wouldn't that be cool? :oops:

Source code so far. (the stat math may not be 100% correct ... yet)
 
Last edited:
Imagine building a generic visitor block that can accept NULL references to variable types of array and conditionally operate on the one you select. :nodi:

Array_AVIS.PNG
 
How can one 'generalize data handling' ?

The possible combinations of what data are in the array, how big the array is, and what operations or tests that can be done must be infinite.
And these general blocks will then be relatively obscure and inefficient for the particular task.

As an excercise in how one COULD do array operations, it is mildly interesting. But in real world application it would be madness.

IMO, arrays are best programmed in structured text, which will be easy to program and understand. It takes just minutes to churn out ST code for doing some operations on an array. So create specific ST code blocks for each particular usage, rather than a 'generic' code block. And then in each specific case you can add comments that clearly detail what the code is doing.

And then call the ST blocks from the ladder code, with enough comments that the function of the called block is clear from the ladder code.
 
Agree on ST (which the block’s code is), but hear me out:

What if the AVIS proof of concept above is used with a small family of UDT for recipe management (representing BOOL, REAL, DINT params, and so on). Suddenly we’ve not only got a way to generalize what a parameter is and how to constrain it, but we can also punt selecting what *type* they are and how many exist to the end-user/operator (on the fly).
 
This being the concept...

Instances of Param:
- user opts to be a BOOL, DINT, LINT, REAL, LREAL (online reinterpret_cast)
- user applies concrete constraints, sets precision, engineering unit, comment, description

List:
- maintains array of Param
- resize / re-assignment to/from smaller/larger arrays of Param are possible to meet application needs

Visitor:
- iterates over List(s), provides the interface to Param
- can handle any number of Param
- doesn't care about the underlying Param type

recipe.png
 
Last edited:
AVIS? Like in the car rental company?
lol, you got me.
What are you really trying to do?
Why must I ask this all the time?

Firstly, I'm not asking anyone else to solve my problems.

What I happen to be working on is a fully generic, scalable recipe manager. I'm also measuring is people's interest in the ability to type-pun or reinterpret_cast data contstructs in real-time to solve their specific problems in a flexible way.

Other manufacturers provide the means in their tools to do things like PVOID and ANY_ARRAY and ANY_NUM to generalize with and make it easier to keep the workload from being married to hard data types that require a re-work every time somebody needs a parameter to have another decimal point. Or they want a new one that wasn't foreseen and entire solutions need to be rebuilt.

I'm fully open to ideas on pulling it off, but I won't keep begging Rockwell to improve Logix.
Why is this being done in a PLC?
PLCs are worlds faster than they've ever been and improving all the time. A SLC-5 may have reliably scaled its analog inputs without a hit, but a modern 5380 doesn't break a sweat doing that and more. A 5480 packs a Core i7 that runs through massive amounts of this stuff on the scale of nanoseconds.

Doing what can be done on the PLC saves tons of work elsewhere, especially when the domain of your problem can be contained to one platform/entity in a process rather than potentially scattered into mish-mash HMI/SCADA solutions where the same problems seem to need to be solved over and over ... and over.

"Just make another faceplate" they say - 5013517 faceplates later...

Does this have anything to do with the previous filter questions?
It's a good idea now that you mention it - two of the above blocks (PulseGen and RCBUF) make sampling your signal over fixed intervals and into a variable-length array very easy.

Pick your sample depth -> declare array -> pass by ref -> ??? -> profit.

Peter and JesperMP,

For what it's worth ($0.27 and growing), the array functions bundled in RVIS are also rolled separately in RSUM, RAVG, RSPAN, RMIN, RMAX, and so on - the price you pay for being able to pick and choose is a loop through an array in a scan cycle. RVIS just rolls it as close as possible to doing all that math in a single loop. If you don't need the math answered right away, you can just let it iterate each scan cycle and you probably won't be able to measure the CPU time impact.

I'm not prescribing anything for your application - of course that always depends - but my goals include keeping the stuff as flexible and "free-function-y" as it can be.
 
Last edited:
A recipe will be very specific to the machine or process.
And 'recipes' will mean something different for different people or machines or processes. I write below what is my opinion and experience.

I am doubtful of using a generic function for recipes, apart from the basic loading function.
It is definitely an acceptable to have some basic checks in the PLC, as disaster-avoidance. If a parameter is way outside the allowable range for the particular machine or process.
But other than that, recipes are handled outside the PLC.
Recipes are very powerful but therefore also dangerous.
If you get a recipe wrong, you dont mess up one part, but possibly the whole production for an entire plant.
In my experience, the vital part is that the recipe is presented on the HMI or external recipe application, not as mere numbers but as meaningful texts that are human understandable. Both each recipe, and the components of each recipe. It must be possible for the operator to check at the last minute if everything looks correct before hitting the 'load recipe' button.
There is usually a database that provides the recipes and work orders, and there must be an interface for operator to view and edit the recipes and work orders. For us this is a database application because the recipes and work orders originate in the factorys ERP system.
The checks for if the components are correct may also be complex and be handled by this database application. For example, component A must be between 80-120% of component B. Component C must newer be used together with component D...
 
In the absence of a UNION here's a naïve first approach.

  • 48 bytes to store the value isn't great, so I'll have to figure out a way to manage that.
  • Each type requires at least 8 bytes to align correctly for the COP.

RecipeParams.PNG
 
Might have this. Going to try the COP in the other direction. Raw bytes in, cast back out to the first non-null reference present…
 
Last edited:
If anyone wants to try this program or improve on it, here's the base version.

edit: pulling for fault
 
Last edited:

Similar Topics

Hi, I'm having an issue in crimson 3.0 when I create a programme using a case statement referencing a fault word that each bit needs to change the...
Replies
4
Views
193
I am trying to copy an array of real numbers into a UDT with a real data type element. I have attached a snip below showing my COP instruction...
Replies
4
Views
203
I have an array of 55 REAL values. Is there a way to multiply based on the array location ? I have 55 transfer belts that are equally spaced...
Replies
3
Views
153
Hello everyone, I'm working on a project that involves controlling an array of nozzles within a CNC environment, where the nozzles travel along a...
Replies
5
Views
176
Hi. I'm using a Modbus ProSoft where I basically map data to a big INT array. Example, where GX_I_63HPU is a REAL, MNETC.DATA.WriteData[200] an...
Replies
21
Views
428
Back
Top Bottom