Rounding in the PLC

Atticus

Member
Join Date
Sep 2021
Location
USA
Posts
11
Yes, I know. This topic seems to be beat to death, but usually the answer is "just don't". I have a situation where we're checking to see if a weight is within tolerance in the PLC, then sending the weight and the pass/fail to a database. Since the pass/fail check is performed on the PLC, we need to round the weight to the tenths decimal place (xxx.y) before we perform the check. I want the result to follow "normal" rounding, not half to even. My plan is this:

ADD .055 to Weight
MUL Weight by 10
TRN Weight
DIV Weight by 10

Am I missing any edge cases where this won't work? Thanks for your input.
 
Here's another pass at it:

ADD Weight plus .0001
MUL Weight by 10
MOV Weight into Temp (DINT)
MOV Temp into Weight (REAL)
DIV Weight by 3

If I'm thinking about this correctly, adding .0001 should avoid any half to even tiebreaks in the range I care about.
 
The check works fine, but we need to perform the check after the limits are rounded. i.e. a lower limit of 15.002 should actually be rounded down to 15.0. Since all of these calculations are done dynamically on the PLC, we end up with very precise limits.
 
Am I missing any edge cases where this won't work?


Yes; comparing non-integral values of REALs should be avoided. Do this instead:
MULtiply by 10
ADD 0.5 (Note 1)
TRN
LIM/LES/LEQ/GEQ/GRT (Notes 2 & 3)
Notes

  1. Assumes positive values
  2. Do not do the divide by 10; do the pass-fail on the ten-times, truncated value instead
  3. Requires multiplying by 10, ADDing 0.5, and TRN'ing the limits as well
  4. Assumes, e.g. with an upper limit of 10.8, that 10.8499 should pass and 10.85 should fail
Rationale; TL;DR

Code:
>>> for v in numpy.arange(110,113,dtype=numpy.float32)/10.0:
...   print('{0:.8f}'.format(v))
... 
11.00000000
[COLOR=DarkOrange][B]11[/B][/COLOR].[COLOR=Red][B]100000[/B][/COLOR][B][COLOR=Blue]38[/COLOR][/B]
11.19999981
>>> [COLOR=Blue][B]1e-6[/B][/COLOR]*[COLOR=darkorange][B]11[/B][/COLOR][COLOR=Red][B]100000[/B][/COLOR][COLOR=blue][B]38[/B][/COLOR]./[COLOR=blue][B]38[/B][/COLOR].
29.21052731578947       ### <== between 2**24 and 2**25
 
Last edited:
I'm not understanding something.. why would limits be flexible/roundable. Limits are generally hard numbers. the live number can fluctuate within them to pass or outside to fail. rounding the live number after testing for a printout/record.
 
I'm not understanding something.. why would limits be flexible/roundable. Limits are generally hard numbers. the live number can fluctuate within them to pass or outside to fail. rounding the live number after testing for a printout/record.

Say a weight tolerance is +-2%. This could lead to some very precise tolerances such as 15.002. The rounding spec is to round the final values to the same tolerance as the least accurate instrument, which is to the tenths. So if you weigh 15.000, by our spec you should round the lower limit of 15.002 to 15.0, then round the actual to 15.0, and compare which results in a pass (inclusive limits).

Edit: So in all honesty, I suppose we don't care about rounding the weights, but rather rounding the calculated limits. Rounding the weights would just be nice for the reports.
 
Last edited:
The check works fine, but we need to perform the check after the limits are rounded. i.e. a lower limit of 15.002 should actually be rounded down to 15.0. Since all of these calculations are done dynamically on the PLC, we end up with very precise limits.


Why not change the limits to be whatever would round to be OK?


If the official upper limit is 15.0, but you want to include numbers that round to that, couldn't you make it so the upper bound check is less than 15.05 instead (or less than or equal to 15.0499999999, depending how you want to code it)?
 
Why not change the limits to be whatever would round to be OK?


If the official upper limit is 15.0, but you want to include numbers that round to that, couldn't you make it so the upper bound check is less than 15.05 instead (or less than or equal to 15.0499999999, depending how you want to code it)?

Limits are all dynamic based on the recipes, also calculated in the PLC. i.e
LowerLimit = RecipeTarget * .08
UpperLimit = RecipeTarget * 1.02
 
Say a weight tolerance is +-2%. This could lead to some very precise tolerances such as 15.002. The rounding spec is to round the final values to the same tolerance as the least accurate instrument, which is to the tenths. So if you weigh 15.000, by our spec you should round the lower limit of 15.002 to 15.0, then round the actual to 15.0, and compare which results in a pass (inclusive limits).

Edit: So in all honesty, I suppose we don't care about rounding the weights, but rather rounding the calculated limits. Rounding the weights would just be nice for the reports.

Lim block still makes more sense.

so say your product run is 15LBs packs..

HI Limit = HiTest

Test = Live Weight

Lo Lim = LoTest.


HiLim=15+(15*.02)
LoLim = 15-(15*.02)

Test for Pass Fail within the limits. No rounding needed.

14.69 will fail as its not over 14.7 and outside tolerance.

Rounding limits and then also rounding live weight.. then testing.. I don't get whyy you bother testing with junk numbers at that point. If your product runs vary all you have to do is use a variable where the 15 is, feed in a target weight and bang done.
 
Yes.
MULtiply by 10
ADD 0.5 (Note 1)
TRN
LIM/LES/LEQ/GEQ/GRT (Notes 2 & 3)
Notes

  1. Assumes positive values
  2. Do not do the divide by 10; do the pass-fail on the ten-times, truncated value instead
  3. Requires multiplying by 10, ADDing 0.5, and TRN'ing the limits as well
  4. Assumes, e.g. with an upper limit of 10.8, that 10.8499 should pass and 10.85 should fail
Rationale; TL;DR

Code:
>>> numpy.arange(1084,1087,dtype=numpy.[COLOR=Blue][I][B]float32[/B][/I][/COLOR])/100.0
array([10.84, 10.85, 10.86], dtype=float32)
>>> 
 >>> for v in numpy.arange(1084,1087,dtype=numpy.float32)/100.0:
...   print('{0:.8f}'.format(v))
... 
10.84000015
[COLOR=DarkOrange][B]10[/B][/COLOR].[B][COLOR=darkorange]850000[/COLOR][/B][COLOR=blue][I][B]38[/B][/I][/COLOR]
10.85999966
>>> 
>>> [COLOR=Magenta][I][B]1e-6[/B][/I][/COLOR]*[B][COLOR=darkorange]10850000[/COLOR][COLOR=Blue]38[/COLOR][/B]./[B][COLOR=blue]38[/COLOR][/B].
 28.552632578947367       ### <== between 2**24 and 2**25

Thanks for continuing to add detail. My only question is would it be safe to still perform the DIV by 10 at the end? These values are all stored in a database, so if I can keep the number is the "correct" format, then I don't need to touch the reports. Thanks again.
 
BTW.. by rounding you are throwing your 2% tolerance in the trash and going for 2% +/- some other extra % so now not its not even 2%.

Correct, but that's the spec it seems. I can try making the argument, but I suspect I'll be shutdown.

I've also muddied the water by using +-2%, so we get nice round numbers. Say the tolerance is actually +-1.9%. Now our upper and lower are 15.285 and 14.715. This is where the rounding comes into play.
 

Similar Topics

Dear All, I need to round off the analog value FOR EXAMPLE: 123.45 to 123 Please prove solution. Thanks
Replies
14
Views
20,877
Hi all, Grounding and earthing problems are hardest to find. in our plant we are having Ctrl logix plc. each 4-20 ma instrument is showing display...
Replies
1
Views
1,905
I am installing a panel mounted hard-wired UPS to protect a Versaview and a ControlLogix processor. The UPS has grounding connections on the input...
Replies
7
Views
3,887
Hi all, I'm connecting several 4-20mA sensors together in parallel (only one shown below) The enclosure is ABS plastic with metal backplate DAQ...
Replies
5
Views
274
I have Rhino 120 to 24 dc power supply and it has 2 Positive and 2 negative terminals on the DC side but no ground terminal. Should I connect one...
Replies
9
Views
435
Back
Top Bottom