# Datatypes, Arrays & Best Practices

## Recommended Posts

Good morning and happy Friday to all!

I am still learning the ropes of PLCs ladder logic, etc and I am hoping to get some suggestions.  I am from the world of traditional code-writing and microcontrollers, so the handling of arrays and datatypes within ladder logic has been a bit of a learning curve.  Here's my situation:

I am using a 4-20ma signal from a laser to measure the level of a material within a tank.  The tank has a rotating arm which periodically passes through the laser beam.  To filter this out, I am taking a measurement every .1 seconds and writing it to the 0th element of an array (after shuffling the rest of the values).  I am taking the minimum element of that array as the true level at that moment (arm in front of the beam will only make the measurement appear higher, never lower).

I am taking the 'true level'/minimum measurements and writing them to another 10 element array every 0.1s, same scheme, shuffling, etc.  I have a third 10 element array in order to do calculations on the rate of change from the 0th element to the 1st, 2nd, 3rd, 4th, etc.  Essentially I am working to get the volumetric flow out of this tank....

The issue I'm having is that I am getting only whole numbers, and non-negative numbers.  The order of magnitude and precision should be X.XX.  I am only getting the integer portion, unsurprisingly.

I used a formula function block and did my calculations in there.  Very handy.  Avoided me having to add another function block to divide by 0.1, 0.2, 0.3, 0.4 etc.  (Also, that was giving me datatype errors using the MULT function block).

I realize I've given a lot of details and not asked any questions directly, so here goes:

1.  When is the 'right' time to use real numbers?

2.  Given I only need 3 significant digits of precision, should I multiply my values by 100 or 1000 and format it on the HMI to show the decimal place?

3.  If I want to know both positive and negative values, should I use multiply by 100 or 1000 AND choose 32768/2 as the zero point?  As in, shift the values, so that below 16384 represents a negative volumetric flow?

4.  Are there better ways to handle arrays than creating multiple arrays just to store 9 elements, then move them back to the original array, or copying a whole array just to run numeric operations?  For example, is there a clever/elegant way to calculate the volumetric flow from the 0th element to the 1st, 2nd, 3rd, so on...getting 9 values and averaging, sorting, etc. to get a less noisy signal?

Kindest regards!

##### Share on other sites
6 minutes ago, Dancho said:

1.  When is the 'right' time to use real numbers?

Almost never. Multiply by 100 or 1000 (or whatever precision you need) in your linearization function block and then keep track of the location of the decimal point through any subsequent calculations. The HMI display function for integers has a handy virtual decimal point that you can use for display.

11 minutes ago, Dancho said:

3.  If I want to know both positive and negative values, should I use multiply by 100 or 1000 AND choose 32768/2 as the zero point?  As in, shift the values, so that below 16384 represents a negative volumetric flow?

I spend most of my time with VisiLogic rather than UniLogic, but my recollection is that the 16-bit integer registers are signed (VisiLogic has both signed and unsigned 32-bit registers, and only signed 16-bit registers - I think UniLogic is the same). Just use negative numbers as you normally would. Just be careful about register overflow and divide by zero.

15 minutes ago, Dancho said:

For example, is there a clever/elegant way to calculate the volumetric flow from the 0th element to the 1st, 2nd, 3rd, so on...getting 9 values and averaging, sorting, etc. to get a less noisy signal?

It seems I'm always dealing with converting flow rates to volume (most of the time) and volume measurements to flow rate (less often). Either many system designers don't understand that they need to use the proper sensor for the job at hand or they just go with whatever is cheaper at the moment (sometimes you need both flow and volume so conversion is necessary regardless). Converting between those two domains is very cumbersome and elegant solutions are rare.

For converting flow to volume, you need to integrate. I just time slice the flow (usually in 100ms increments) and sum (there is some additional math involved to get the units correct). For the reverse, you just have to measure the volume as often as you can, calculate the time interval and filter as heavily as needed to get something approximately matching reality. If there's a better way, I sure would like to hear it.

##### Share on other sites
1 hour ago, Flex727 said:

Almost never. Multiply by 100 or 1000 (or whatever precision you need) in your linearization function block and then keep track of the location of the decimal point through any subsequent calculations. The HMI display function for integers has a handy virtual decimal point that you can use for display.

Fantastic.  That is very helpful.  I can appreciate 'almost never'.

That being said, my program has evolved over time, 2 different system integrators, and now me.  There are real numbers used in several places...generally related to drives and encoder outputs, speed, etc.  Is this the 'right' time to use real numbers, or just another way to handle those things?

1 hour ago, Flex727 said:

It seems I'm always dealing with converting flow rates to volume (most of the time) and volume measurements to flow rate (less often). Either many system designers don't understand that they need to use the proper sensor for the job at hand or they just go with whatever is cheaper at the moment (sometimes you need both flow and volume so conversion is necessary regardless). Converting between those two domains is very cumbersome and elegant solutions are rare.

For converting flow to volume, you need to integrate. I just time slice the flow (usually in 100ms increments) and sum (there is some additional math involved to get the units correct). For the reverse, you just have to measure the volume as often as you can, calculate the time interval and filter as heavily as needed to get something approximately matching reality. If there's a better way, I sure would like to hear it.

I'm actually just converting from displacement/position to volume.  Little bit easier, but I will keep this in the back of my mind.

##### Share on other sites
59 minutes ago, Dancho said:

Is this the 'right' time to use real numbers, or just another way to handle those things?

I've been doing this for many many years and can't remember the last time I needed floating point numbers in my program except for some crazy flowmeters that insisted on outputting their data via MODBUS as floating point. Insane, if you ask me. I guess if you have a situation where the number of significant figures in the decimal varies and is unknown at the time of programming then floating point is necessary. Other than that it's poor programming practice in my humble opinion.

##### Share on other sites

I whole heartedly agree with "almost never", but as the saying goes "never say never"

When working with most sensor devices you have a finite range 0-20ma = 0-100% or 0-10bar or 0-12feet

using whole number math insulates you from idiot number results like a 1234% full tank,

it simply can't happen.

However you are trying to average positive and negative numbers, this would be a good place to have an

exception to the rule of thumb  and use real numbers.

In "the old days" plc's could not handle real numbers well and used a long, long time to calculate them

this gave long CPU cycle times and not particularily good results.

Todays plc's have much better cpu's and can handle real numbers pretty well.

We are never trying to calculate the budgjet deficite of a world economy so 8 significant places

is good enough for us in real life usage.

Unitronics scaling is really easy min - max what you get input to min - max what you want output.

I would like to suggest that you filter out the unresonable values given by the arm passing in front.

If input > 123456 mm then goto end

run your stacked array average only with ok numbers.

"garbage in garbage out"

##### Share on other sites
On 1/18/2020 at 8:52 AM, bobnorway said:

However you are trying to average positive and negative numbers, this would be a good place to have an

exception to the rule of thumb  and use real numbers.

In "the old days" plc's could not handle real numbers well and used a long, long time to calculate them

this gave long CPU cycle times and not particularily good results.

Speaking of cycle times...I've wondered if there is a way to measure cycle time of a program?  I can do it in Python...😝

Does it particularly matter, or should I assume that I will always get a reasonable cycle time unless I'm doing/something has gone terribly terribly wrong?  I assume the watch dog timer on a PLC has to be extremely short as well?

##### Share on other sites

You do not need any Pyton code.

You can find required information about scan time in UniLogic  "System->Execution".

B.R.

##### Share on other sites
On 1/18/2020 at 1:32 AM, Dancho said:

The tank has a rotating arm which periodically passes through the laser beam.

Put an inductive in a suitable location to sense when the arm is going to affect the beam.  Disable the reading for that period.

Alternatively, when the laser returns the reading it should get as constants with perhaps a given range  from when the arm is in the way, set the program to ignore anything near those values.  (Much like Bob suggested.)

(This topic has also reminded me I never got around to showing to the world my "simple" averaging example, which I should try to find time to do!)

cheers, Aus

##### Share on other sites
17 hours ago, Ausman said:

Put an inductive in a suitable location to sense when the arm is going to affect the beam.  Disable the reading for that period.

Alternatively, when the laser returns the reading it should get as constants with perhaps a given range  from when the arm is in the way, set the program to ignore anything near those values.  (Much like Bob suggested.)

(This topic has also reminded me I never got around to showing to the world my "simple" averaging example, which I should try to find time to do!)

cheers, Aus

That is an option as well.....though I did try it.

The arm is made of round stock, and the reflection from it was throwing an error in an extremely wide and random range.  But always up...which is why I landed on taking the minimum element of an array.

Now, if you wanted to share the averaging example I am ALLL eyes and ears.

##### Share on other sites
On 1/21/2020 at 8:23 AM, Ausman said:

Put an inductive in a suitable location

By this I mean that the inductive doesn't necessarily need to actually be on the arm.  Most of the time you can find a convenient bolt head or similar within the drive train that can be used very easily by adjusting the sensor's mounting point to be in exactly the correct location.  If the bolt etc is mechanically connected to the arm then it isn't going to vary!  Although not applicable to this, in some instances where all else was not possible, I have even machined slots in motor shafts at the fan end to enable a definite read that the motor is actually turning correctly, an inductive picks this up very easily.

Or put a leg on the arm that will prevent the scatter.

Busy at present....just a quick drop in during morning start.....wait!

cheers, Aus

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×