SLC Math Wierdness

Tom Jenkins

Lifetime Supporting Member
Join Date
Apr 2002
Location
Milwaukee, WI
Posts
6,302
Please see the attached file.

There are two rungs of interest - 9 and 10. The CPT compute blocks should execute identically mathematically, since multiplying by 0.0001667 is the same as dividing by 6000.

The first executes properly, giving the correct answer of 600 when N12:10 = 3000 and N12:12 = 1200.

The second answer should be 1000 since N12:11 = 5000. However, this CPT seems to be rounding the value inside the parentheses to the nearest integer. I used the "|" (above the \) to enter the divide opertion. The file verifies without errors.

Have any of you seen this before? What is going on? Can I divide using a register instead of a constant without error?

I am totally stumped. The processor is a SLC 5/05.
 
Last edited:
Not an AB expert, but looks like a floating point issue, does the SLC have the F file, if you try writing to here instead it may help.

Or, just lookad again, what about using N10:22, then N10:24?

I am assuming that AB also uses 2 words for these types of calculations.
 
Tom Jenkins said:
multiplying by 0.0001667 is the same as dividing by 6000.
No it isn't. Rockwell converts integers to floats when you use the floating point number and then converts the float back to an integer in the first case. Try dividing by 6000.0 instead. It should convert the numbers to floats and then round and store the same way as the mulitiply.

In the second case an integer division is performed and Rockwell rounds the results to the nearest integer which I think is a mistake.

Have any of you seen this before?
Yes.

I always try to mulitply by constants as in your first example.
Muliplies are faster and less error prone.
 
Thanks, Peter.

I take it from your explanation that I will be well advised, when dividing by a register instead of a constant, to always first use DIV to get 1/NX:Y, output to a floating point FZ:A, and then multiply in the CPT block.

A-B should REALLY warn about this in the instructions and help files for the CPT function. I didn't see any reference to this in either my book or the online help for the CPT instruction!

I will try this out Monday. Thanks again.
 
I also think that Peter was trying to emphasize - if an operation (your N12:11 | 6000) has two integers then, at least for that portion of the execution of the CPT block, it assumes an integer partial result is needed. He recommended using, within the CPT block, 6000.0 (a float) instead of just 6000 (an integer).
 
Tom Jenkins said:
A-B should REALLY warn about this in the instructions and help files for the CPT function. I didn't see any reference to this in either my book or the online help for the CPT instruction!

AB should do lots of things but sometimes they dont!
 
I also have run into this. I had a PLC-5 app that needed to make a RTI data sample every 1/4 second. Part of this was incrementing a time stamp by 1/4 (.25 for the fractionally challenged) second. So, as the time incremented, I would get something like:

.25
.5000000001
.7500000022

...etc...

And this was with a simple ADD. FP was required in this case, due to the end PC's needs. I had to revert to a .125 data sample. The PLC-5 had no trouble adding that.

I had a similar problem in Wonderware, so AB is not alone in this. I was using a 1800 second timer to display a count down, and 1800/60 for the minutes gave me a count that every 30 seconds went:

30-29-28-29-27-28....

Before I ended up doing it with two instructions in the PLC, I made it work in Wonderware, in 10 lines of script.

PLEASE, vendors, DON'T HELP ME DO SIMPLE MATH!
 
tomalbright said:
I also have run into this. I had a PLC-5 app that needed to make a RTI data sample every 1/4 second. Part of this was incrementing a time stamp by 1/4 (.25 for the fractionally challenged) second. So, as the time incremented, I would get something like:

.25
.5000000001
.7500000022

...etc...

And this was with a simple ADD. FP was required in this case, due to the end PC's needs. I had to revert to a .125 data sample. The PLC-5 had no trouble adding that.
There is no excuse for this. However, I bet this error was caused by an error in the entry of the number so the number entered is not 0.25. 0.25 can be represented exactly even in single precision.

I had a similar problem in Wonderware, so AB is not alone in this. I was using a 1800 second timer to display a count down, and 1800/60 for the minutes gave me a count that every 30 seconds went:

30-29-28-29-27-28....
There is an excuse for this. If you are accumulating time in units of 0.1, 0.01 or 0.001 seconds then round off errors will occur. None of the above number can be represented exactly in floating point no matter what the precision. The correct way to count time is to count the number of periods in an INT or DINT and then multiply that by the time per period.

Our new product uses floating point and our tech support gets calls about the floating point errors.

Not all single precision processors are the same. Some have 'guard' bits that allow extra precision calculations while numbers are kept in the registers. For instance, the TI DSP has a 40 bit mantissa ( 8 extra bits ) but it truncates the mantissa when it stores the data. One must execute the round instruction before storing. Some computers don't have guard bits so they lose precision much quicker.

PC floating point is very good. There should be no problems with Wonderware if proper techniques are used. My Scilab and Mathcad agree to 16 to 17 digits. In fact I have got 'burned' working in this almost ideal world just to find that everything falls apart when using single precision floating point. My 'burns' were self inflicted due to my own ignorance of, or ignoring the use of, proper technique.
 
Peter Nachtwey said:
There is no excuse for this. However, I bet this error was caused by an error in the entry of the number so the number entered is not 0.25. 0.25 can be represented exactly even in single precision.

Well, I don't know. Entering .25 as a constant in an instruction, you would think that would be right. It didn't work.


There is an excuse for this. ... ...There should be no problems with Wonderware if proper techniques are used.

I agree. However, the ability to use an "INT(x)" type function in a numeric display expression would go a long way toward solving problems like this.

Everybody's favorite product has bugs. AB can't add, they make great software, but can't make a Windows text edit box that is usable, their touchpanels suck for longevity. Wonderware is good, but not intuitive at all, and some functions that are easily found in other products can only be done with scripts. GE Cimplicity is one of the best darn project organizers I have seen, but can you edit any processor? Nooooo.... have to buy special licenses for the obsolete 9070. The View software was great, AFTER they added a zoom in rev. umpty-seven.

Wish we could throw them all together and come up with one thing that does what we really need!
 
Last edited:
Its alwasy good practice when performing floating point operations that involve constants to "cast" the constant as a float. This is good programming practice regardless of whether one is programming in Ladder or C++ and avoids ambiguity. When you enter a constant of 6000 this is an integer in the program code and the processor must make the conversion to a float before it can be used. 6000.0 is alrady entered into the compiled code as a float constant.

As has been mentioned, RSLogix will perform this conversion in certain situations when the rung is verified, but not all software will do this. Some programming software converts it while other software generates the machine code for the PLC processor to make the conversion. So to avoid problems just get in the habit of entering xxx.0 when you mean it to be a float.

Never leave it up to the compiler to guess what you really meant for it to do.
 
Here is another wierd thing I have this cpt block
((F8:8*(F8:3-F8:4))*F8:5|F8:6 DESTINATION F8:17 When you look at the
data it has 1.#QNAN in the data display. Whats up with that.
 
Christoph said:
((F8:8*(F8:3-F8:4))*F8:5|F8:6 DESTINATION F8:17 When you look at the data it has 1.#QNAN in the data display.
Floating point values goes to +1.1754944e-38 .. +3.40282347e+38. As you have four floating point operations after each other, you can reach the limits if the values are big enough.
That, or F8:6 is zero. In either of these cases you will get "Not a Number" as the result.

About what Tom has experienced:
I allways assumed that when the SLC "sees" a floating point value in the formula, then the entire formula is calculated with floating point math.
But maybe the SLC only switches to floating point math from the point where it sees the first floating point value.
 
A #QNAN is a quiet not a number. It is a floating point error probably caused by the divide by 0 or divide by a very small number. Do you ever check F8:6 to see if it is valid? These errors are not good ones to get because the floating point process must be reset or the #QNAN will never go away.
 

Similar Topics

We are getting a fault...... Math Overflow Trap S:5/0 = 1 Apparently we are getting a value greater than 32767 or less than -32766. If...
Replies
6
Views
7,851
I am using the cpt instruction on a slc 5/05 i have used this before to add, subtracted and multiply but not to divid. now when i enter the...
Replies
3
Views
3,713
I need to multiply a float (0 - 36) by 1,000,000 and then totalize this. What I am thinking of doing is using the 32b math operations, but I'm not...
Replies
10
Views
2,140
Hello all, As the topic name says I am having an issue with math. I am using the CPT function with an equation of ((N7:60-N7:61)|N7:60)* 100) and...
Replies
7
Views
3,495
I recently had a SLC 5/04 processor fault out due to a math error. The overflow trap and zero bits were both set. I was finally able to locate it...
Replies
5
Views
5,601
Back
Top Bottom