Converting 32 bit integers

lawebster

Member
Join Date
Dec 2006
Location
Baton Rouge, Louisiana
Posts
16
How do you convert 32 bit long integers into something that the AB PLC-5 can represent correctly?

My problem is that I am trying to get values from an OMNI flow computer which are signed 32 bit long integers and formatted as 2's compliment into a PLC-5/20 via serial.

According to the OMNI manual the 32 bit integer in this reg range are 32 bit signed formatted as 2's compliment. The order transmitted is MS byte of MS word, LS byte of MS word, MS byte of LS word, LS byte of LS word.

Is there a way to get this 32 bit value into 2 16 bit N regs?

Very confused and don't know where to begin.
Thanks
 
As you've learned, the PLC-5 doesn't support 32-bit integers. If you are doing a custody-transfer or commercial billing application you might not be able to do it accurately in a PLC-5 and may need to look at a ControlLogix.

PLC-5's do support large numbers as Floating Point values. The standard that is used is called "IEEE 754 Single-Precision Floating Point" and can maintain precision to 1 digit up to values of about 7 million.

Most programmers approach this problem by just taking off the first 15 bits and MOVing them into a Floating Point register.

Then they take the next several bits (up to 17 of them, really) and manually add the floating-point equivalent to the base register.

It's crude, but it does work. A lot of the time you're only going to use 20 bits or so in the 32-bit Integer so you limit your logic to examining those bits.
 
Thanks for the replies...

jim - I have tried just MOVing it to a Float data file but the number I get is not correct nor does it resemble anything close. The OMNI flow computer is the device that has 32 bit int values that I need to get. They are actually totalizer values which are set up as 9 digits but can be changed to 8 or 7.

ken - there is another piece to this that might help but not sure how to go about it. In between the PLC-5 and the OMNI is a prosoft card which is actually scanning the OMNI and then does Block Transfer with the PLC. This prosoft card has 4000 16 bit registers that store the values. So the 32 bit info from the OMNI is stored in module register 1 & 2 but when the PLC does the BTR it doesn't represent correctly. This is where I am stuck. After the BTR I get the values N7:0 = 7 & N7:1 = -1341 when the correct value should be 522947.
 
lawebster said:
Thanks for the replies...

jim - I have tried just MOVing it to a Float data file but the number I get is not correct nor does it resemble anything close. The OMNI flow computer is the device that has 32 bit int values that I need to get. They are actually totalizer values which are set up as 9 digits but can be changed to 8 or 7.

ken - there is another piece to this that might help but not sure how to go about it. In between the PLC-5 and the OMNI is a prosoft card which is actually scanning the OMNI and then does Block Transfer with the PLC. This prosoft card has 4000 16 bit registers that store the values. So the 32 bit info from the OMNI is stored in module register 1 & 2 but when the PLC does the BTR it doesn't represent correctly. This is where I am stuck. After the BTR I get the values N7:0 = 7 & N7:1 = -1341 when the correct value should be 522947.

If you create a project in RSlogix5 that supports LONG file types, you will notice that when you input 522947 in the LONG file type, and change the Radix to Binary, the bit pattern will match the bit pattern created by two type INTS with a value of
7 and a value of -1341


Long.jpg



twoInts.jpg
 
Couple issues... First, N7:0 seems to be you most signifigant word, so to start, take that and multiply it by 65536.0, storing it in a floating point register.

Next, if your N7:1 is positive, you can just add it to the same floating point register. If, as in your example, it is negative, you need to ADD it to another 65536.0 (float) and store in a temporary floating point register, then add the two registers together.

Note, that if N7:0 is ever negative, you also need to ADD that to 65536.0 before multiplying it by 65536.0

Basically, you need to deal with unsigned integers, which PLC5's don't support, and generally, the resultant can be found by multiplying the Most Significant Word by 65536, and adding the Least Significant Word.

For negative word values (PLC5 uses SIGNED integers), you can convert them into unsigned by adding them to 65536.0 and storing the result in a float.
 
Last edited:
you are getting the value 522947 in in 2 separate words.

-1341 (singed integer) is equal to 64195 (unsigned integer).

Convert -1341 to a unsigned integer and put in a float reg.

multiply 7 x 65536 = 458752 into Float reg

ADD 458752 + 64195 = 522947
 
Let's check some of our assumptions, guys.

This is a PLC-5 controller with a Prosoft module that reads the data from the OMNI flow computer. Therefor the data's going to show up in an N-file as the target of a Block Transfer Read (BTR) instruction.

PLC-5 controllers do not support Long (32-bit) Integers. Neither do SLC modular controllers like the SLC-5/03, 5/04, and 5/05.

MicroLogix 1100, 1200, and 1500 controllers have a Long Integer data type, which would be great for this application, but he's using a PLC-5.

ControlLogix controllers have 32-bit signed integers (we call them DINTs) as their base data type, so they can handle this application without breaking a sweat.

But he's using a PLC-5.

It's already been observed that N7:0 is actually the Most-Significant Word and N7:1 is the Least Significant Word.

Let's do it simply, as a lesson in Two's Complement, with 33 rungs:

MOV 0 F8:0
XIC N7:1/0 ADD 1 F8:0 F8:0
XIC N7:1/1 ADD 2 F8:0 F8:0
XIC N7:1/2 ADD 4 F8:0 F8:0
XIC N7:1/3 ADD 8 F8:0 F8:0
XIC N7:1/4 ADD 16 F8:0 F8:0
XIC N7:1/5 ADD 32 F8:0 F8:0
XIC N7:1/6 ADD 64 F8:0 F8:0
XIC N7:1/7 ADD 128 F8:0 F8:0
XIC N7:1/8 ADD 256 F8:0 F8:0
XIC N7:1/9 ADD 512 F8:0 F8:0
XIC N7:1/10 ADD 1024 F8:0 F8:0
XIC N7:1/11 ADD 2048 F8:0 F8:0
XIC N7:1/12 ADD 4096 F8:0 F8:0
XIC N7:1/13 ADD 8192 F8:0 F8:0
XIC N7:1/14 ADD 16384 F8:0 F8:0
XIC N7:1/15 ADD 32768 F8:0 F8:0
XIC N7:0/0 ADD 65536 F8:0 F8:0
XIC N7:0/1 ADD 131072 F8:0 F8:0
XIC N7:0/2 ADD 262144 F8:0 F8:0
XIC N7:0/3 ADD 524288 F8:0 F8:0
XIC N7:0/4 ADD 1048576 F8:0 F8:0
XIC N7:0/5 ADD 2097152 F8:0 F8:0
XIC N7:0/6 ADD 4194304 F8:0 F8:0
XIC N7:0/7 ADD 8388608 F8:0 F8:0
XIC N7:0/8 ADD 16777216 F8:0 F8:0
XIC N7:0/9 ADD 33554432 F8:0 F8:0
XIC N7:0/10 ADD 67108864 F8:0 F8:0
XIC N7:0/11 ADD 134217728 F8:0 F8:0
XIC N7:0/12 ADD 268435456 F8:0 F8:0
XIC N7:0/13 ADD 536870912 F8:0 F8:0
XIC N7:0/14 ADD 1073741824 F8:0 F8:0
XIC N7:0/15 ADD 2147483648 F8:0 F8:0
 
Last edited:
Pasteable into RSLogix 5:

SOR MOV 0 F8:0 EOR SOR XIC N7:1/0 ADD 1 F8:0 F8:0 EOR SOR XIC N7:1/1 ADD 2 F8:0 F8:0 EOR SOR XIC N7:1/2 ADD 4 F8:0 F8:0 EOR SOR XIC N7:1/3 ADD 8 F8:0 F8:0 EOR SOR XIC N7:1/4 ADD 16 F8:0 F8:0 EOR SOR XIC N7:1/5 ADD 32 F8:0 F8:0 EOR SOR XIC N7:1/6 ADD 64 F8:0 F8:0 EOR SOR XIC N7:1/7 ADD 128 F8:0 F8:0 EOR SOR XIC N7:1/8 ADD 256 F8:0 F8:0 EOR SOR XIC N7:1/9 ADD 512 F8:0 F8:0 EOR SOR XIC N7:1/10 ADD 1024 F8:0 F8:0 EOR SOR XIC N7:1/11 ADD 2048 F8:0 F8:0 EOR SOR XIC N7:1/12 ADD 4096 F8:0 F8:0 EOR SOR XIC N7:1/13 ADD 8192 F8:0 F8:0 EOR SOR XIC N7:1/14 ADD 16384 F8:0 F8:0 EOR SOR XIC N7:1/15 ADD 32768 F8:0 F8:0 EOR SOR XIC N7:0/0 ADD 65536 F8:0 F8:0 EOR SOR XIC N7:0/1 ADD 131072 F8:0 F8:0 EOR SOR XIC N7:0/2 ADD 262144 F8:0 F8:0 EOR SOR XIC N7:0/3 ADD 524288 F8:0 F8:0 EOR SOR XIC N7:0/4 ADD 1048576 F8:0 F8:0 EOR SOR XIC N7:0/5 ADD 2097152 F8:0 F8:0 EOR SOR XIC N7:0/6 ADD 4194304 F8:0 F8:0 EOR SOR XIC N7:0/7 ADD 8388608 F8:0 F8:0 EOR SOR XIC N7:0/8 ADD 16777216 F8:0 F8:0 EOR SOR XIC N7:0/9 ADD 33554432 F8:0 F8:0 EOR SOR XIC N7:0/10 ADD 67108864 F8:0 F8:0 EOR SOR XIC N7:0/11 ADD 134217728 F8:0 F8:0 EOR SOR XIC N7:0/12 ADD 268435456 F8:0 F8:0 EOR SOR XIC N7:0/13 ADD 536870912 F8:0 F8:0 EOR SOR XIC N7:0/14 ADD 1073741824 F8:0 F8:0 EOR SOR XIC N7:0/15 ADD 2147483648 F8:0 F8:0 EOR

I realize that such a subroutine looks a little clumsy, but it's not going to confuse a programmer who looks at it in the future, as long as he recognized powers of two. Run the subroutine only when the Block Transfer Read (BTR) updates the data values and you should be fine.
 
Last edited:
Dint to int :)

Ive just been through this. I used the cop function block. It copied the 32 bit pattern to two 16 bit registers. I just mult the MS word by 65535 and add the LS. However when the sign bit is set the LS word decreases in value. (becomes more negative). I then MSG the words to a PLC 5 and send the registers apended to a string to a display. I am still trying to deal with the sign bit problem. I do not want the LS word to decrease. I know Ken's solution will work but I was hoping to find an easier solution. :)
 
Actually Ken's solution will work great as long as the very highest bit isn't set. The original querent (I got that word from a much earlier post by Ken) did specify "signed 32 bit integers". This may not ever happen in actual practice though.
 
querent?

Yes that is very true Bernie.... I just use the LS word. The max number I am concerned with is 620000. The MS X 65535 Plus the result of the F8:0 addition. I smiled when I seen the logic. It is what I was doing to the LS word. You have to admit, this is way too much work. I am sure there may be PLC5 applications that use more MS bits but Ken's solution works for me, for the LS word. By the way, Querent? you do not hear this used very often!! My vocab just increased by ONE. Thanks!
 
Bruce99 almost has it right

Code:
MUL N7:0 65536.0 F8:0	// multiply the MSW by 65536.0
MOV N7:1 F8:1			// move the LSW a float register
LES F8:1 0 ADD F8:1 65536.0 F8:1  // if less than 0 add 65536.0
ADD F8:1 F8:0 F8:0	   // add the two floats together

I'm at home and can't test this.
Warning. A DINT can't be converted to a float without a possible loss of precision because the mantissa hold only 24 of the DINT's 32 bits.
 
It works! Thanks

I have tested the code and it seems to work. Thanks for all the advice, I now have a better understanding of what is happening and why. Now my new problem is that there is about 20 of these totalizers to do, wish there was a way to use the code once instead of having to copy it 20 times. Humm

Not real clear on Bernie's comment but assume that if you had a number that used all 32 bits it wouldn't work.. these totalizers are 9 digits so I'm assuming I'll be okay. 9 digits so the largest number would be 999999999 which is 30 bits - right?.

Anyway thanks again.
 
You can do it once. Put the conversion into a subroutine, then call the sub with two input parameters (your integer registers), and one return parameter (your floating point register)
 

Similar Topics

i am communicating 1766-l32bwb with conzerv make energy meter em 6436. I have communicated it on Modbus rtu. but i am not able to decode the data...
Replies
2
Views
4,672
I need help converting from a floating register to two integer words. I'm using a SLC 5/05 and need to be able to write 32 bit data to a servo...
Replies
2
Views
4,704
Well I am trying to cleanly convert a decimal value in a DINT to the corresponding bit in a different DINT So if I have the number 11 on in...
Replies
11
Views
1,978
I'm converting a program in FTView Studio from 32bit to 64bit program because the tech wanted some runtime securities for screens changed. I'm...
Replies
0
Views
1,461
I am having problems expressing an ANALOG OUTPUT 16bit INT word (0-10V Proportional Valve Voltage) as a REAL decimal number. From my...
Replies
6
Views
9,157
Back
Top Bottom