PDA

View Full Version : slc 5/05 - floating point accuracy


venkum00
February 11th, 2008, 06:34 AM
I am working with huge numbers (max of 300,000,000). I used a floating point to store my counter values, but am not sure about the accuracy. Will the SLC round off numbers when working with 9-10 digits? In other words can it add 150,000,001 and 150,000,001 and store it as 300,000,0002?

Thanks in advance.

Ven

RMA
February 11th, 2008, 07:16 AM
I don't know AB at all, but I strongly suspect the answer to your question is "no". You can find out for yourself if you check the specs to see what format is used for floating point notation. If it is single precision (i.e. 32 Bit) IEE 754, then your accuracy is limited to about 7 digits. If it's double precision (64 Bit) then you would theoretically have enough resolution (about 11 digits), however you still couldn't rely on the answer (in your example) because of the inherant rounding errors which occur when working with floating point numbers.

Edit, if your maximum is not going to exceed 300 million, then you could always work with DINTs (or whatever they're called in the AB world). 32 Bits allow for a maximum value of 4294967295. Just remember to be careful of the order you do things in if you're going be multiplying or dividing, though!

venkum00
February 11th, 2008, 09:18 AM
Thank you RMA. I will look for the specs.

TConnolly
February 11th, 2008, 10:33 AM
If you want to increment ones using a float then the maximum number you can reach is 16,777,215. After that adding 1 will no longer increase the value of the float. This is true for not just PLCs, but all computing devices which use the 32 bit IEEE-764 floating point format.

For huge number counting consider using 32 bit integers (4.2 billion counts) as RMA suggested. Even though its a 16 bit machine, you can do it in the SLC 5/05 if you use two words and a bit of gymnastics. Look for a technote on unsigned integers in the AB knowledgebase (IIRC the technote targets the PLC5, but the same principle will work on the SLC)

(edit, incidentally, the 300,000,002 you chose for your example just happens to be one number that cannot be represented exactly, as is 150,000,001.)

Here (http://babbage.cs.qc.edu/IEEE-754/Decimal.html) is a link where you can play with some various floats and see how they work.

Ron Beaufort
February 11th, 2008, 10:45 AM
it might be a good idea to tell us what you plan to do with that "great big" number ... some examples:

(1) display it on an operator's screen ...
(2) write it down on a paper and hand the paper to the boss ...
(3) no one will ever see it but the PLC programmers ...
(4) something else ...

depending on the purpose involved, sometimes we can recommend a workaround solution ...

venkum00
February 11th, 2008, 11:24 AM
Thanks for the info Alaric.

Ron, I am counting the length of a cable for speeds up to 400 meters/min using an encoder and a counter card. I am using the ring functionality in the counter card to rest the pulses.

In other words, I need to add numbers anywhere between 1 to 6000 once every program scan time. The number could reach up to 300 million before i can reset it to zero.

Thanks,
Ven

spaderkung
February 11th, 2008, 11:59 AM
The problem you describe can not, and should not, be solved with floating point numbers. Decide on the need for resolution first, is it m, dm or smaller? How do you get "/min"?

venkum00
February 11th, 2008, 01:17 PM
Resolution is meter. I used the inbuilt functionality of the counter card to get the "/min" (rate).

TConnolly
February 11th, 2008, 02:43 PM
Spaderkung is right, you need to do this with integers.

You can do this with 16 bit integers and a feature on your SLC 5/05 that will let you do 32 bit math using two consecuitve N registers. That will let you track encoder pulses accurately up to 2.1 billion.

Its not hard, in fact the program is very simple, but here is the kicker: the low order 16 bit word will be an unsigned integer, but the data monitor is going to show it as signed, or negative, so it might be helpful to use the binary or hex radix instead of the decimal radix.

You need to use the S:2/14 bit to permit 32 bit math. Normally, when an overflow occurs the destination address usually contains either 32767 or -32768 and it does not wrap around. Setting S:2/14 lets it wrap around. But that gives us another kicker: The S:2/14 bit is asserted only when going from program to run or only at the end of the scan, so latching and unlatching it won't produce the expected results, set it using the data monitor before downloading. Using the S:2/14 bit changes the way overflows are processed, it might (I stress might) mess up the way your program normally handles overflows if you are currently trapping and responding to them. If you don't trap and resopond programatically to overflows elsewhere in the program then there is probably nothing to worry about, but something like

MUL N7:30 N7:31 N7:32
GRT N7:32 15000 OTE B3/xx

could bite you if N7:32 overflows. With S:2/14 clear N7:32 would be 32767 on overflow - no problem for the following comparrison. With S:2/14 set, N7:32 could go negative on overflow - whic is a problem for the following comparrison. You'll have to evaluate the implications for the rest of your program. Refer to the instructions set reference manual for more information on using this bit.

As long as the encoder count since the last addition is < 32767, add the encoder count to the low order word. Each time the carry bit is set add 1 to the high order word. 300,000,000 is 11E1A300 in hexadecimal. So by comparing the high order word to 11E1 and the low order word to A300 we can determine if we have reached 300,000,000 counts - we need to take care that we include the sign bit as a part of the comparrison (A300 would be negative in decimal radix and the PLC would evaluate the comparrison as true prematurely)

I've attached an example. I wrote it for a SLC5/04 that I keep on my desk. I put the PLC into single scan mode and tested it one scan at a time, adding 5000 at at time to make sure it was working. Then I set the high order word, N7:0 to 11E0h and ran several single scans to test the comparrison. It latches a bit when 300,000,000 is reached and clears the 32 bit counter.

EDIT:
I just noticed this.
Rung comment 3:0000 should be corrected to read
The 32 bit word is stored in N7:0 and N7:1. N7:0 is the high order word (bits 16-31), N7:1 is the low order word (bits 0-15).

JBJennings
February 11th, 2008, 04:26 PM
Would this not be a wee bit simpler than having to set up multiple integers????

Divide your counter's accumulated value by 1000, store the result as thousands, on each scan cycle add this value to the thousands bit and reduce your counter's accumulated value by that number of thousands....


See the RS500 example attached...

TConnolly
February 11th, 2008, 04:36 PM
Would this not be a wee bit simpler than having to set up multiple integers????

Divide your counter's accumulated value by 1000, store the result as thousands, on each scan cycle add this value to the thousands bit and reduce your counter's accumulated value by that number of thousands....


See the RS500 example attached...


Watch out for rounding. If the count is 4,600 then N7:1, thousands, will get a value of 5.

gmferg
February 11th, 2008, 04:51 PM
Wouldn't it be simpler to do the following with no rounding error?

http://www.plctalk.net/qanda/uploads/HSCE_HighCount.GIF

TConnolly
February 11th, 2008, 04:56 PM
That would work only when the count is less than 2000 pulses per scan. The OP said

...I need to add numbers anywhere between 1 to 6000 once every program scan time. ...

What happens when one scan he gets more than two thousand pulses from the encoder from one reading of the HSC to the next? He can't afford to regularly miss a thousand counts.

32 bit math is a piece of cake, the logic is only three rungs long, including the comparrison, no rounding, no loss of resolution.

venkum00
February 11th, 2008, 05:01 PM
Alaric, You are correct about the pulses from encoder. one question though, what if the cable is moved backward, is there a way to subtract the cable length? I saw that your code is for unsigned integers?

Thank you all for the input so far...

TConnolly
February 11th, 2008, 05:08 PM
Yes, there is a way. If you'll look in the instruction set reference manual for the SLC500 and go to the status file information for the S:2/14 bit, it will refer you to a page in the manual that gives an example of how to do 32 bit math, including unsigned subtraction. Its pretty simple. Since the count is negatvie you still add it in, but if negative and underflow occurs you need to subtract from the high order word.

If you don't have the manual you can download it from AB's literature library for the SLC500.

I have one question: Does the 300,000,000 ever change? If so, does an operator ever change it? If so is this something we need to address?


edit: when I first tested the program I used a 32 bit hex constant 11E1A300 for 300,000,000. I changed that to use a 32 bit value in N7:2 and N7:3 where 11E1h and A300h were stored, but I didn't carry it through the program I attached. :doh: This version has that carry through, I fixed comment 3:0000 too. I also attached a PDF copy for anyone without Logix500.

venkum00
February 11th, 2008, 07:43 PM
Great effort Alaric!! Thank you.
300 mil should hopefully not change - I put in twice the capacity that we needed considering the future. This is used for 2 purposes. One to read the current length of the cable at any give time and Two for operator to enter a length value, so that the machine knows when to stop.

Thanks,
Ven