
adccommunitymod (AutomationDirect) asked a question.
Created Date: August 29,2007
Created By: dramsier
**** This post has been imported from our legacy forum. Information in this post may be outdated and links contained in the post may no longer work.****
I'm using I-Boxes to do a fairly lengthy signed integer math calculation with intermediate results in V memory. Some of the values can be negative, unfortunately this includes the dividend in a divide operation. I 've discovered that the output of the MATHBIN Ibox is different if I create a negative dividend using constants versus having it stored in variable memory. For example, the equation (K1-K6)/K2 gives 0xFFFD, but if I store the dividend in Vmemory first and then reference it I get the following K1-K6 - > V430 (V430)/K2 gives 0x7FFD The former looks correct while the latter is clearly not what I intended. In either case, I would have expected them to be identical but they aren't. Is this an error in the Ibox implementation, or am I misunderstanding something about its use? Thanks, Dean
Created Date: August 29,2007
Created by: dramsier
I forgot to mention, DL06 using DS5.1
Thanks,
Dean
Created Date: August 29,2007
Created by: franji1
It's the implementation of the PLC architecture. It does not distinguish between signed and unsigned 16 bit values. It assumes 16 bit unsigned when it matters.
You have to look at the actual instructions generated by the Math IBox.
LD K1
SUBB K6
DIVB K2
Let's just look at the K1-K6 portion:
LD K1
SUBB K6
The accumulator is 32 bits, so when you did
these first 2 instructions, the result is 0xFFFFFFFB in the 32 bit accumulator.
When you do the DIVB K2, you get
0x7FFFFFFD
When you OUT to a WORD you get 0xFFFD in that Word (the lower 16 bits of the 32 bit accumulator)
Now let's look at the 2nd example
V430 / K2
This generates
LD V430
DIVB K2
I'm going to assume that it equals -5, but it is a 16 bit register, -5 is 0xFFFB, so when you do a LD V430 you end up with 0x0000FFFB in the accumulator.
When you do the DIVB K2 on that 32 bit value you get 0x00007FFD, which is what you are seeing.
There is no "signed math ", although it works when doing ADD and SUBTRACT due to the Modulo Math involved. However, when doing MULTIPLY or DIVIDE, there must be "sign extension " operations done on the MSBit. This would be bit 15 on a 16 bit binary number.
There is no "Load 16 bit signed value " instruction that knows to extend the sign bit of V430 such that the accumulator ends up being 0xFFFFFFFB (extending bit 15 out all the way to bit 31).
Other than doing it all by hand (i.e. doing the LD and checking the sign bit, then OR K FFFF0000 if it is set, etc.), your best bet is to conver everything to REAL, do all the math in MATHR, then convert back.
Note that when converting BINARY 2 REAL (BTOR), it assumes UNSIGNED, so you would still have to look at the MSBit, save its status, do a 2's complement if it was negative, convert the absolute (positive) value to real, then set the MSBit of the real value to make the real value negative.
Something like (this will put the "real " value of V430 into V2000/V2001 and handle conversion to negative numbers)
STR B430.15
OUT C0 // store whether V430 is negative or not
LD V430
INV
ADDB K1
BTOR
ORD K80000000 // set the MSBit to make the IEEE Float be negative
OUTD V2000
STRN C0 // if it was NOT negative
LD V430 // just convert V430 to REAL
BTOR
OUTD V2000
Then in your MATHR IBox, do
V2000 / R2
This should give you -2.5
Created Date: August 30,2007
Created by: dramsier
Thanks for the detailed explanation, I figured it would be something like this.
This particular algorithm depends on integer math (dropping remainders etc) so I was unable to fix it with real numbers.
However, I was able to get around it by modifying the algorithm slightly to guarantee that when the division occured it would always have positive numbers. I just wanted to understand the issue in case a future algorithm couldn't be fixed in the same way.
In case anyone is curious, I was calculating the date of Easter (along with other holidays) for some building control work at our church. Algorithm is here http://aa.usno.navy.mil/faq/docs/easter.html
Thanks!
Dean
Created Date: August 29,2007
Created by: dramsier
I'm using I-Boxes to do a fairly lengthy signed integer math calculation with intermediate results in V memory. Some of the values can be negative, unfortunately this includes the dividend in a divide operation.
I 've discovered that the output of the MATHBIN Ibox is different if I create a negative dividend using constants versus having it stored in variable memory.
For example, the equation
(K1-K6)/K2 gives 0xFFFD,
but if I store the dividend in Vmemory first and then reference it I get the following
K1-K6 -> V430
(V430)/K2 gives 0x7FFD
The former looks correct while the latter is clearly not what I intended. In either case, I would have expected them to be identical but they aren't.
Is this an error in the Ibox implementation, or am I misunderstanding something about its use?
Thanks,
Dean