UINT to INT

cjjeeper

Member
Join Date
Aug 2018
Location
Nowhere
Posts
71
I have a Compactlogix 5380.

I am using the Modbus Client TCP IP Modbus Client to query a modicon 984.
I am getting UINT from the Modicon into INT in the PLC. I cannot change the data type of the data array in the PLC.


So I am getting values like 45676 which ends up being a negative number in INT format.



Is there anyway to deal with this? Get the UINT back to INT?
thanks
 
Last edited:
45676 is outside the range of an INT. It's gotta go to something else. Hopefully the data type you can't change is the Modicon, not the CompactLogix. You could BTD the INT to a DINT (source and dest bits = 0, length 16) or you could AND the INT with 16#FFFF to a DINT. If you're dealing with a substantial size array, a FOR loop might be beneficial to transfer the INT array to a DINT array.

Another fancy way I probably don't recommend is use a loop to build a new INT array twice the size of the Modbus array, with elements alternating from the Modbus array and 0 value elements and COP that array to a DINT array.
 
Do you know the correct value of the number that is coming from the Modicon? Is the correct value actually 45676 (0xB26C)? Is it possible the bytes are reversed, and the value is 27826 (0x6CB2)?

Because as @5618 notes, there is no way to represent 45676, or any positive integer greater than 32767, in a signed INT on Compactlogix. Period.

The Modbus protocol at its core merely transfers the bits; it is agnostic about whether the 16-bit data quantities it transfers are signed or unsigned, although when it uses 16-bit quantities internally (e.g. PDU addresses), it interprets them internally as unsigned (0-65535).

Is this an existing or new application on the CompactLogix that you are developing or modifying, or are you not able to change or otherwise work with the CompactLogix code?

If the former, using the COP instruction to transfer the bits from the 16-bit signed INT array into a new 16-bit unsigned UINT array (assuming 5380 and not 5370), and then using the UINT array's values where appropriate, would be my first choice.

The second would be using the BTD instruction, as @5618 suggests, to transfer the 16-bits from the Modbus value into the lower half (16-bits), and zeroing out the upper half, of a DINT, as @5618 suggests. Again, that assumes you can change the code on the CompactLogix.

A poor third choice would be to test the INT array element(s) for negative values, and simply replace same with a value of +32767. E.g.
XIC INT_array[123].15 MOV 32767 INT_array[123]
I don't know if that would work for your application, but it would replace a perhaps nonsensical negative and/or error-causing value on the CompactLogix with the upper limit of the INT data type that is as close as possible to the actual value from the Modicon, which might be a good enough poor-man's conversion.

But again, as @5618 wrote, if the data values in the Modicon UINTs greater than +32767 are indeed correct values, then although Modbus transfers those bits into INTs on the CompactLogix, there is absolutely no way to represent those UINT values via those INTs.
 
5380 controllers support UINT data type.
Use COP instruction to copy from INT to UINT. You can also use BTD instruction.
However, instead of UINT, you can use DINT, with the same BTD or COP approach. Both instructions do bit-by-bit copy. Do not use MOV as it will send a signed value instead.
 
I cannot change the compactlogix because I cannot change the datatype in the AOI that is bringing across the data from the modicon.


The words are not swapped.

The values are 2 consecutive UNINTs from the Modicon representing floating points so an approximation is not going to work.

It pretty much looks like I have to get a Prosoft card. I inherited this from a previous project and was trying to use the set up they started with. It just is not going to work.
 
Last edited:
You say you are getting a float as two 16 bit registers but cannot change the AOI, is this Uint supposed to be an input parameter to the AOI ? but assuming you can add extra logic to convert it to a float then use that float as an input to the AOI, The AOI surely is expecting a float as a parameter ? so it will need some logic to convert it. or is this data already in the AOI & how ?
 
That's a bit different than my initial interpretation of what you have. It sounds like you're fine. The data comes in as an array of INTs. Now you just have to get the data to a REAL. That's very doable. The exact steps depend on endian and byte order. The simplest if it matches, is COP from the first INT to a real. If that's not it, you will need some additional steps to reorder the bytes, or maybe reorder the bits. Whatever of these is needed, it's very possible and quite common when dealing with unpacking Modbus data.
 
I agree with 5618, however, I stopped using RW some years ago & only did a few projects in compact logix so not exactly an expert, It is a bit more of a problem with tag only based systems, in the other systems that can use address based tags rather than symbolic it easy to manipulate the bits/nibbles/words etc. for example, in Mitsubishi it is still fixed memory variables, using a symbol without giving a physical address works because at compile time it uses some reserved physical addresses, although it is possible to find what they are after a compile should a change be done then it may use another physical address which is a problem.
An example is a float is just two 16 bit words (or 4 for a precision one), this means a physical address of D100 & D101 is the float, it is possible to map those 16 bit words into two other words but treat it as a float or manipulate the bits/words as required, the only real things to watch out for is you may have to programm using the physical address rather than a symbolic one.
Example is My_Float is D100 & D101 so by using D101 rather than the symbolic name means you can load, manipulate & transfer it to some other float say D102,D103, so the code become Move D101 to D103.
 
I cannot change the compactlogix because I cannot change the datatype in the AOI that is bringing across the data from the modicon.


The words are not swapped.

The values are 2 consecutive UNINTs from the Modicon representing floating points so an approximation is not going to work.

It pretty much looks like I have to get a Prosoft card. I inherited this from a previous project and was trying to use the set up they started with. It just is not going to work.


How is the conversion done from the UINTs in the Modicon to the INTs in the CompactLogix to floating points (in the CompactLogix?)?

Do they COPy/CPS the bits, as mentioned by @5618, in which case the data type on the CompactLogix doesn't matter?

Or do they do some mathematical operations, from UINTs to floating point (far more messy than the COPy/CPS, but certainly possible)?

Where is the conversion done? Is it done inside the AOI? Or perhaps the AOI only does the Modbus transfer, and the array of INTs is an parameter passed to that AOI?

The more information you provide, the more likely you are to get a useful answer.
 
Or do they do some mathematical operations, from UINTs to floating point (far more messy than the COPy/CPS, but certainly possible)?


If it is this, which is possible, or even likely if the switch from UINTs to INTs has derailed your porting of the previous project, then can you post the code from that previous project that converts from UINTs to floating point?
 
I think a picture is worth a thousand words here.


On the right is the poll of the modicon starting at 40500. That is put into the compactlogix starting at 4xxx[0] So 4xxx[0] = 40501 on the left


On the left - 40504,40505 make up a float in the Modicon. (slight difference due to time, its pressure)
On the right - 4xxx[4],4xxx[5] is what gets put into the INT array. CANNOT CHANGE THE DATATYPE.

mb2PNG.PNG
 
Last edited:
It seems from my calcs that it is 57.475

Easy in Mitsi by using physical addresses, you can even give each physical address a symbolic name for example D0 = My_USINT1 D1 = My_USINT2
Then D0 = My_Real (takes up D0 & D1) providing you use the correct function like MOVE D0, D10 MOVE D1, D11Then refference D10 as a real in symbolic (D10 +D11) it is a real. i.e. D10 = My_Real (D10 + D11)
You can see in the pic that D5 in that case as a real

Float1.png
 
It seems from my calcs that it is 57.475

Easy in Mitsi by using physical addresses, you can even give each physical address a symbolic name for example D0 = My_USINT1 D1 = My_USINT2
Then D0 = My_Real (takes up D0 & D1) providing you use the correct function like MOVE D0, D10 MOVE D1, D11Then refference D10 as a real in symbolic (D10 +D11) it is a real. i.e. D10 = My_Real (D10 + D11)
You can see in the pic that D5 in that case as a real


I dont understand what your doing there...
 
It seems from my calcs that it is 57.475

Easy in Mitsi by using physical addresses, you can even give each physical address a symbolic name for example D0 = My_USINT1 D1 = My_USINT2
Then D0 = My_Real (takes up D0 & D1) providing you use the correct function like MOVE D0, D10 MOVE D1, D11Then refference D10 as a real in symbolic (D10 +D11) it is a real. i.e. D10 = My_Real (D10 + D11)
You can see in the pic that D5 in that case as a real




actually yes I see what you're doing but you're missing the part where the data on the RIGHT is the data I have to work with. It represents what came in. The data on the left is the source.
 
As parky's post indicates, the "sign" of the data doesn't matter in this case. Whether it is a UINT or an INT just determines the waythe data is displayed. the bit pattern (which is really what is important) is the same either way.

One would HOPE that the people who wrote the Logix program did things the easy way. that would be:

CPS(RW_RESPLC_Data.HoldRegister_4xxx[3], Pressure, 1)

This will have the plc copy starting at RW_RESPLC_Data.HoldRegister_4xxx[3] to Pressure (arbitrarily named float tag) the number of bytes needed to fill one instance of Pressure (4 bytes since it is a REAL).

So as long as the bytes are aligned so the lowest order bits are in the lowest order byte then the value in Pressure should match the value from the Modbus source. If it doesn't either the byte alignment is wrong (big endian vs little endian) or the Logix code authors are doing something REALLY wierd.

Keith
 

Similar Topics

I apologize for the basic question but I have read the documentation and searched online and I'm still not getting it... I want to convert UINT...
Replies
4
Views
998
I have a UDT with multiple elements that all show on the display perfectly using direct reference. For example I have the following instance on a...
Replies
2
Views
1,457
Hello, I'm using Compact Logix L33 in RSLogix 5000. I'm trying to message over modbus register that is 16bit UINT. In Rslogix 5000 do I message...
Replies
3
Views
1,573
Hello, It is possible to change form INT to UINT a variable data type? For the moment, I receive the value -32766 (Local:6:I.Ch0Data) from...
Replies
4
Views
2,730
HI, I am trying to read a UINT 64 bit data(active energy parameter) from a PQA meter(WM5-96) over Modbus TCP into a GE PLC.I am able to read...
Replies
0
Views
1,575
Back
Top Bottom