Controllogix, J1939, Two's Complement

nhicks

Member
Join Date
Jan 2007
Location
Whitewater, WI
Posts
111
As you can see from the title, I have a number of questions/issues;

Two different situations/issues:
1. Im reading Oil Pressure and Fuel Pressure over J1939 through a Pyramid Solutions Bridgeway. Im getting the data in, im just having issues getting the correct display. When either the fuel or Oil pressure reaches 75 (PSI, after being converted from kPa)- the number turns negative and start decreasing by 2 (-73, -71, -69) although the pressure continues to rise. The data comes into a SINT. I tried moving bit for bit to a INT to try and defeat the signing - but that didnt work, same problem. Im starting to wonder if this data is coming across as Twos complement?
I have zipped and attached the logix5000 file, a quick reference:
Raw Binary data is read into AB7645:I.Data.9 (Oil Pressure) - and you can see under the J1939 subroutine, where I tried to cheat and move bit for bit into CAT_J1939_OIL_PRESSURE. Before that, I used a COP command from AB7645:I.Data.9 into CAT_J1939_OIL_PRESSURE which was also a SINT. Rung 2 of the J1939 subroutine takes the incoming value times 4 (to give kPa.) Then rung 3 takes the oil kPa times .14503 to give PSI.) That value (AB_J1939_OIL_PRESSURE) is what im displaying on the HMI.


2. Im trying to read Current across Modbus RTU, from a G.E. 489 Generator protection relay. The data type is listed as the following "2's Complement, Signed Long Value" 32bits total - 1st 16 bits are High Order Word of Long Value, 2nd 16bits are Low Order Word of Long Value. Example; -123456 stored as -123456 (i.e. 1st word: FFFE hex, 2nd word 1DC0 hex)

Im not sure how to take a two word, two's complement value, and put it into a real number/floating number? Im searchig the web and see examples of how to change from two's complement into decimal, but not sure how to relate it to logix5000. Im under the gun and return to the job site down south Monday, only having Monday and Tuesday to get both items going - so any help will be greatly appreciated!!!!

NH
 
Greetings nhicks ...



sorry that I personally don’t have time to tackle this right now - but I’ll certainly give it a shot tomorrow - unless you or someone else has it nailed by then ...



quick question for you to move the project along ...



can you - or can you NOT - “do the math” by hand? ... specifically, let’s say that you have X pressure in the field ... and Y data signal coming into the ControlLogix ... can you “do the math” with a manual calculator to arrive at the CORRECT value Z ? ...



if you can do that, please work a few examples and post the results AND SHOW THE MATH STEPS that you used ...



once we have that carefully specified “target” to shoot for, I’m sure that there are many forum members who can make the magic happen automatically ...



and just between you and me, I’m betting that once you work out that step-by-step procedure, you’ll probably have a “eureka” moment and be able to solve the puzzle yourself ...



big idea: after reading your post several times, I’m still not 100% sure that I know what you WANT to happen with those values ... you’ve told us something about what IS happening now, but (as least as far as I can tell) you haven’t spelled out exactly what “the answer” should look like ... (but then maybe that’s just me) ...



anyway ... if you decide to jump through those “post some examples” hoops, then please work some that will cover HIGH values - and LOW values - and POSITIVE values - and NEGATIVE values ... assuming of course that you need all of those ranges ...



wish I had time to work on this now - but I’ve got pressing matters to take care of ... good luck ...
 
Ron, thanks for the quick response.
Some more detail on situation #1;
I dont know the actual values coming accross, I wont know until I hook back up Monday morning. The data source is from a Caterpillar Engine Control Module. Using Cat ET, we can read the value (and what is should susequently be sending over J1939) - and that value and my value correspond correctly from 0-74PSI. When the Cat hits 75, my HMI goes to -75. When the Cat hits 76, my HMI goes to -73 and so on. What I should find out, (and will Monday), in the raw binary data being sent to me, is if the sign bit is going to 1. Personally, we shouldnt ever have negative oil or fuel pressure - so I dont know why they would send it from the Bridgeway to me ( or from CAT to the Bridgeway.)

For #2, I dont have actual numbers, im just trying to put the logic in to read the info when they hook the relay sometime down the road. I was going to use a program to simulate the relay (and check my logic) - but due to issues with the engineering firm and the customer, we are not doing this. So I will be putting the logic in blind, and during actual commisioning a year from now, we will see if it works.
As for the math, im not sure that I understand it yet. Ive never been good with math at all!
But when I take the example given > -123456, I assumed I put the Hex values in order, FFFE1DC0 gives me 4294843840, but flipping the words 1DC0FFFE gives me 499187710. SO im not sure what im missing. Im hoping once I see it ill just slap myself and someone else wont have to.

NH
 
Showing the math

Let's follow the datatypes:

AB7645:I.Data[9] is a SINT
CAT_J1939_OIL_PRESSURE is an INT
J1939_OIL_PSI is a REAL
AB_J1939_OIL_PRESSURE is a REAL

The equation is
AB7645:I.Data[9] = CAT_J1939_OIL_PRESSURE

CAT_J1939_OIL_PRESSURE x 4 = J1939_OIL_PSI

J1939_OIL_PSI = 0.14503 = AB_J1939_OIL_PRESSURE

Collapse thee equation, you get

AB7645:I.Data[9] x 0.58015 = AB_J1939_OIL_PRESSURE

So when your displayed value is 75, the source value must be 75 / 0.58015 = roughly 129.

That's a value that sounds familiar. Consider the binary equivalents of numbers in that range.

127 decimal = 01111111 binary
128 decimal = 10000000 binary
129 decimal = 10000001 binary

What I think is happening is that the incoming data is in unsigned 8-bit format, but in ControlLogix, SINT values are 7 bit with a Sign bit.

When you use a MOV instruction, Logix preserves the value, including the sign. Your bit-by-bit copy failed because the MOV had already moved all 1's into the high byte of the target tag previously.
 
The way I'd handle this math is to clear the first target (a DINT) with a MOV 0, then perform a Masked Move to the target with an 8-bit mask. Then use a single CPT instruction (so that your math shows explicitly) into a target REAL tag.

Use DINT and REAL datatypes by default, and SINT or INT only where the data conversion requires them. INT actually uses up 32 bits of memory and requires a quick copy into a working register when performing math.

In Rung 1:

MOV 0 CAT_J1939_OIL_PRESSURE MVM AB7645:I.Data[9].0 2#11111111 CAT_J1939_OIL_PRESSURE

In Rung 3:

CPT AB_J1939_OIL_PRESSURE "CAT_J1939_OIL_PRESSURE * 4 | 6.8948"

Omit the step in Rung 2. Make the CAT_J1939_OIL_PRESSURE a DINT, and keep AB_J1939_OIL_PRESSUE a REAL.
 
Ken Roach for President '08! :)

Ken, I appreciate the response and assistance. I will have to try this first thing Monday.

I have a few questions, if you dont mind teaching me!
I think I messed up my math; thus the reason I didnt pick up on the 127/128.
Your right, I think the data is being sent unsigned; The input registers are fixed at SINT, they can be changed, but that would require rewriting a number of programs.
I guess I dont understand this;
If I move the 8th bit out of SINT into INT, how does it keep it signed? Does it "know" im moving a signed bit and shift it to the 16th bit? The bit-by-bit transfer is the first thing that happens to the incoming data. Then the arithmatic, then display. Are you referring to the COP instruction - from SINT to SINT?

As to your logic, the MOV command before the MVM, will this execute every scan, then move to the MVM every scan? Just curious, as I would think I needed 3 rungs, or, OR'ing the two together.

How does the MVM command work? Does this strip the sign bit?

Is there an advantage to the CPT command vs seperate commands?

Again - I really do appreciate the assistance. I cant wait to see this work Monday, and maybe it will help me understand the operation a little bit better.

NH
 
You are seeing the two-edged sword of how Allen-Bradley handles data types. Many PLCs, such as the Siemens family, require you to perform explicit type conversions if you are moving one data type to another. With AB PLCs, the firmware does this for you, both with moves (MOV) and with math. For example, you can directly multiply an integer times a real and send that to an integer with AB. The PLC automatically performs the data type conversions necessary for this to work. This is typically pretty nice since it prevents most programs from becoming cluttered with what many users consider useless instructions.

Secondly, and just as importantly, AB PLCs don't support an unsigned data type. I'm not sure why. It would certainly be useful sometimes, as you have seen.

So now we have your case. You receive an unsigned value from the outside world. Since the AB PLC interprets a SINT with bit 7 set as a negative number, any move of the SINT into any data type will result in a negative number. If you try to manipulate bit 7 of the INT after the move, it is too late. The value has already been sign extended into the INT so all bits above bit 7 are also set. In your case you may have been able to do this with bit manipulation if you have set an internal bit to the value of SINT bit 7, cleared SINT bit 7, made the move into an INT, then set INT bit 7 to the internal bit value. But that's alot of messing around to do the same thing that Ken proposed

A masked move will perform a bit-by-bit move of the source bits into the matching destination bits in any location the mask bit is 1. All other destination bits are left unchanged. This is different from a bitwise AND, where destination bits in line with zeros in the mask are set to zero. In your case, a bitwise AND would work just as well as the masked move, although they are not the same instruction. With the bitwise AND solution you wouldn't need to preload the DINT with a zero. The AND would set all the higher level bits to zero for you. I just don't know if you have a bitwise AND available to you.

Keith
 
Last edited:
Bitwise and is available in V16 (the only one I have on this laptop) & would function perfect for the MOV & MVM that Ken suggested.
 
Excellent errata, guys. I am just now calming down after watching both ND/Stanford and the Apple Cup. Go Irish !

As for the second issue of a 32-bit "long integer" being represented by two 16-bit Modbus Registers, your principal mistake was copying the bit pattern of a Two's Complement number into a tag whose datatype is IEEE 754 Single Precision Floating Point.

The other problem is the sequence of the High Order and Low Order Words that come from the MultiLin is reverse from the way they are copied from an array if INTs into a DINT in a Logix controller.

No problem, we'll use three instructions:

COP, SWPB (Swap Bytes), and MOV

The Copy will take two INT elements out of the MVI56-MCM's database array and copy them into a single DINT tag. At that point the two 16-bit Words will be in the wrong sequence.

That's what the Swap Bytes instruction takes care of. Set it for "Word" mode.

Then, to convert from a Two's Complement-style DINT to a IEEE 754 Floating Point-style REAL, use the MOV instruction.

Here's the cut-and-paste code from my test, using the tags

Modbus_Raw_Data INT[2]
Modbus_LongInt_Value DINT
MultiLin_Value REAL


COP Raw_Modbus_Data[0] Modbus_LongInt_Value 1 SWPB Modbus_LongInt_Value WORD Modbus_LongInt_Value MOV Modbus_LongInt_Value MultiLin_Value
 
Last edited:
I have a similar project coming up so I am reading this post with earnest.

Why is the displayed data correct until 75psi? I am having difficulty understanding this. I will have to accomplish the same thing using AB Micrologix 1200's. Will I encounter the same problems?

I am just now calming down after watching both ND/Stanford and the Apple Cup. Go Irish !
Amen Brother. I was at the ND vs. Duke game. My son is a student there.

I've attached some very good information for programmers working on Caterpillar equipment. The good stuff starts on page 104.
 
Why is the displayed data correct until 75 PSI ?

The 75 PSI value is a red herring; the raw value is in 1/4 kPa. It is multiplied by 4 and then divided by 6.8948 to get PSI.

The Caterpillar engine considers the 8-bit value to be an UNsigned Integer. The Logix considers the 8-bit value to be a Signed Integer, where the 8th bit is the +/- Sign.

The effect is seen when the source value exceeds 127.

01111111 binary = 127 decimal (unsigned) = 127 decimal (signed)
10000000 binary = 128 decimal (unsigned) = -128 decimal (signed)
10000001 binary = 129 decimal (unsigned) = -127 decimal (signed)
10000010 binary = 130 decimal (unsigned) = -126 decimal (signed)
10000011 binary = 131 decimal (unsigned) = -125 decimal (signed)

Logix doesn't use unsigned data types, so the easy way around this is to put those 8 bits into the low byte of a DINT datatype tag, where the Sign bit is safely up at Bit 31.

We can't use a MOV instruction because that performs automatic datatype conversion and will preserve the negative value.

Instead we use a mechanism that just moves the bits, such as Masked Move, Bitwise AND, or individual XIC/XIO pairs.
 
Kyle, thanks for the info. If your working on Caterpillar Gensets, and need anything feel free to email me - [email protected]

The only thing missing in that document is the FMI's - I finally got a list of typical FMI's from our Cat dealer, where im working this week.

Ken, looking at your provided examples - Im just curious, how does the masked move not take the signed bit with it, but a standard MOV will?
Is this because, prior to the MVM, you set the destination register to 0 (Zero) (this removing all signing/data) and then mask move the SINT into the destination? I think I know whats happening, im just trying to understand how the MVM does it vs the MOV not doing it correctly.

On the second issue - you mention swapping the words, in logix. Are you familiar with the Prosoft MVi56 card? In the MVI56 setup tags, under MCM.CONFIG.Port1MasterCmd[0], there is an option for swap. Could I use this to swap the words prior to entering Logix? I forgot the user manual at the jobsite.

Thanks again for all the assistance!

NH
 
Ken, just looking over the logic for the second issue;

Your first COP instruction, taking the raw data from the MCM, you have a length of 1. Does a length of 1 equate to copying two words? Considering the data comes in for example, MCM.DATA.ReadData[6] & [7] for A Phase current.

NH
 
One more question Ken, if you dont mind...
In your instruction:
MOV 0 CAT_J1939_OIL_PRESSURE MVM AB7645:I.Data[9].0 2#11111111 CAT_J1939_OIL_PRESSURE

You spec the MVM down to the bit level, is this accruate? I thought id move the whole word?
 

Similar Topics

Why does the controllogix redundancy modules use a single mode fiber vs multimode fiber?
Replies
1
Views
60
Hello, I have two 16 point input cards and 1 16 point output card showing module faulted on my IO tree in Logix Designer. The fault code is...
Replies
7
Views
207
Hello, My associate and I are trying to sync up two ControlLogix racks (7-slot chassis) with identical modules. We are able to see the secondary...
Replies
4
Views
185
Trying to setup a message read via Ethernet. I have the path setup as 1, 1, 2, 192.168.66.10 I get an error code 1, ext err 315. I am beating...
Replies
9
Views
226
I have a redundant ControlLogix being set up. This program reads a value from a remote site which happens to be SLC PLC. Rockwell mentions SLC...
Replies
2
Views
91
Back
Top Bottom