A customer wants our next machine on a CompactLogix instead of a 1200, so I'm teaching myself Studio 5000 V33 on Emulate before the real one lands. Two rungs:
```
ADD 0.1 0.2 Sum
EQU Sum Setpoint ---( ) Match
```
Sum and Setpoint are REALs, Setpoint has 0.3 in it, and Match never comes on. The watch window shows Sum 0.3 and Setpoint 0.3. Put 0.5 and 0.5 into the ADD against 1.0 and Match comes on straight away.
I built a fresh project in case I'd broken something and got the same, then I tried it in TIA on a 1214C with Real tags and got the same again, so it isn't a Rockwell thing.
Is the Emulate maths broken, or does a real controller do this too? Am I missing something obvious, a status bit on the ADD maybe?
Smallest test first. Make the watch window show more digits, set the tag style to Float and widen the column, or put Sum into a tag with 9 decimals. What do you see then?
0.30000001 for Sum, 0.3 for Setpoint. Oh. So they aren't equal, not quite. I think I see it. Why doesn't 0.1 plus 0.2 make 0.3? And no status bit, the ADD hasn't got one for this as far as I can see.
No status bit, nothing went wrong. Same in TIA, same in C. 0.1 in binary is a fraction that never ends, like a third in decimal, so the controller stores the nearest 32 bit value and the tiny errors add up. DINT for everything is the other wrong answer, you lose the decimals you wanted in the first place.
The rule, on every platform: never compare REALs for equal, compare for close enough. Ladder: SUB Sum Setpoint Diff, ABS Diff Diff, LES Diff 0.001, OTE Match. Or LIM with Setpoint - 0.001 as low and Setpoint + 0.001 as high on Sum. ST: IF ABS(Sum - Setpoint) < 0.001 THEN. Pick the tolerance from what the number means, 0.001 bar is fine, 0.001 litres per hour on a big flow is silly.
SUB, ABS, LES 0.001 in the ladder version and the ABS line in ST. Match comes on for 0.1 + 0.2 now, on Emulate and on the 1214C.
Neither 0.1 nor 0.2 fits exactly in a REAL, so the sum landed on 0.30000001 and EQU compares exactly, which is why it never went true. Comparing the difference against a tolerance instead of comparing the two values is what I should have written in the first place.
What I still don't get is why 0.5 plus 0.5 worked when 0.1 plus 0.2 didn't. Thanks carav9 and eddieb.
0.5 is a power of two, exact in binary. 0.1 isn't.