BITS N BYTES

Data Types for MAM instruction

19 posts in this topic

I have inherited a program to work on using MAM motion commands on a CompactLogix 5370 processor.

The MAM variables for some parameters state that REAL data type is required.

However in looking at the the code those REAL variables are actually declared as DINT.

Is this OK. Does Logix somehow accept DINT for these parameters even though REAL is specified.

So if parameter is 5600 DINT it somehow interprets this as 5600.00 REAL.

Confused!

Share this post


Link to post
Share on other sites

There are several different operands in a MAM instruction and depending on the controller, the data types for the various operands can be DINT, REAL, UINT, AXIS_CIP, AXIS_VIRTUAL, etc. Within the code, if you right click on the instruction and click on Instruction Help, it'll lay out exactly which data type goes with which operand within the instruction. 

If somewhere in your code the original programmer is moving DINT values into a REAL data type, or vice versa, you might have some rounding or truncating going on, but it could still be workable. Mixing and matching data types is never ideal but if a programmer has no choice, they can often account for those decimal point issues by offsets, buffering, or other tricks of the code writing trade. I've had to play with this myself when I realized the REAL 60.0Hz my controller was sending was being read by the drive as 60, since the drive only had INT available and apparently didn't recognize decimal points. 

Share this post


Link to post
Share on other sites

Moving a data type into a different one will treat it as such. So a DINT 60 will be treated as 60.0 real. However. If you do a copy COP command, logix will do an IEEE 754 conversion from float to dint or vice versa

Share this post


Link to post
Share on other sites

@VFD Guy according to Rockwell literature and my personal experience, mixing and matching data-types always carries the possibility of rounding or truncating errors. So while moving a a DINT value of 60 into a REAL will produce a REAL value of 60.0, moving a REAL value of 60.5 into a DINT will produce 60. When a rounding error occurs, ControlLogix tends to round to the nearest even number, just like the manuals say it will. If you're always dealing in whole numbers and never going outside of data type value boundaries, you can get away with a lot. Unfortunately, my life has not been quite so sheltered, lol.

I'm not sure how COP applies to this situation, since in ControlLogix the COP instruction is used to move a contiguous array of data, not a single value. Can you COP a single value with a length of 1 and get a conversion? If so, please explain how. I've just now tried it and got some crazy results. 

Share this post


Link to post
Share on other sites

My understanding of the COP instruction is that it does a bit-by-bit copy of the raw data in the registers. So, using it to copy a REAL into a DINT will result in gibberish. Likewise the reverse.

1 person likes this

Share this post


Link to post
Share on other sites

Copying a real to a dint isn’t gibberish. It’s an IEEE 754 conversion. I agree with you on the rounding error from float to dint when you mix data types. However a copy will convert the data type. I’ve had to do this for drives on devicenet. Get the reference I want as a real, copy to a DINT, send the DINT to the drive, the drive (750 in this case) would convert back to a real. You can look on knowledgebase. Many technotes on it. Or just look up the IEEE conversion. I probably went on a tangent from your question but just wanted to say I’ve had to convert before. In your specific case, if you put a DINT tag into a tag looking for a real, I believe it just adds .00 to it. Devicelogix does that. And vice versa, I believe logix would truncate a real if put directly into a dint 

Share this post


Link to post
Share on other sites

Posted (edited)

11 hours ago, VFD Guy said:

Get the reference I want as a real, copy to a DINT, send the DINT to the drive, the drive (750 in this case) would convert back to a real.

I understand the confusion here. This is not a conversion. The DINT to DINT here is the transport only via your DeviceNet. If you monitor them in the DINT state, they will actually appear to be gibberish as they are actually REAL. No bits were changed during the process you describe here.

Edited by IO_Rack
My mistake. See panic mode's post below.

Share this post


Link to post
Share on other sites

Do you use the COP instruction or the MOV instruction?

I know MOV will round/truncate and type-cast it properly but, in my experience, the COP instruction does a bit-by-bit copy. I understand the IEEE floating point format, but if the same bit pattern is COP-ied into a DINT register, it will NOT be a meaningful value.

Share this post


Link to post
Share on other sites

I started doubting myself and my memory, so I threw together a quick comparison test in my testbench CompactLogix:

60782ae6522a1_COPvsMOV.PNG.c865d23f88630

The MOV instruction properly rounds the REAL value and converts it to a DINT before storing it in the DINT register. The COP instruction does a bit-by-bit copy of the bits in the REAL register to the DINT register. Since the DINT register is expecting a signed integer value instead of IEEE floating point, it interprets the bit pattern differently and incorrectly. As mentioned above, it rounds x.5 to even, not always high or low.

Share this post


Link to post
Share on other sites

of course...

MOV is doing implicit casting (data conversion) when source and destination are not the same type. basically it tries its best to figure out how to fit data from source into target and still represent (in target format) as close as as possible resemblance of source... which can involve rounding etc. but result  here may not be always what you wanted - after all you are not handling the conversion, you are passing it down to MOV to do the "figuring out" for you. and like anything unchecked, that can go wrong... 

COP does not interpret data... result is a bit-by-bit copy. but REAL type is encoded. so placing encoded value into a variable that is not associated with the encoding process, will lead to display of something in wrong format and hence appear as gibberish...but it is not. the meaning can be recovered by treating it correctly (applying decoding process) as outlined in IEEE754.

 

5 and 5.0 are two very different values. 

first one is an integer, and in case of DINT it is stored in memory as

2#0000 0000 0000 0000 0000 0000 0000 0101 or 16#00000005

the later one is REAL and it is stored in memory as

2#0100 0000 1010 0000 0000 0000 0000 0000 or 16#40a00000

viewing 5.0 as integer will show up as 1084227584 because data format is ignored. this is not gibberish... it is interpreted as wrong format and hence displayed incorrectly.

same goes the other way. displaying DINT value 5 as REAL will show up as 5.877475E-39 because data format is ignored again.

MOV appear to be a "better" choice since to uninformed result looks more like the source. and that may be the case in some cases. But reality is that such data conversion is very limited and produces data loss or could even lead to program hang when you least expect it (after all it "used to work", at least for some values...).

using COP or equivalent is common in data transmission since channel often can only handle (stream of) bytes. it is irrelevant if they represent inputs or outputs or REAL or array or ENUM or JPG or text or anything else...

original (whatever) > COP > transfer > COP back > correct replica of original

but whatever the case is one need to restore the correct format... and view/interpret as correct data type.

2 people like this

Share this post


Link to post
Share on other sites

Getting back to the OP's question:

Sending a DINT to a REAL (or vice versa) via a MOV instruction is ok if you're not worried about losing the fractional value (anything to the right of the decimal point) of the data. REAL to DINT, the DINT truncates the decimal data and rounds. DINT to REAL adds the decimal point, but the fractional value is 0.

@panic mode 

On 4/15/2021 at 8:18 AM, panic mode said:

viewing 5.0 as integer will show up as 1084227584 because data format is ignored. this is not gibberish... it is interpreted as wrong format and hence displayed incorrectly.

If that's the case, in a practical sense, how is the COP data then useful in controller code? If it is the correct value that is merely displayed incorrectly due to formatting, will a controller or drive still respond correctly to that value in that format? 

Let's say I COP a REAL value of 45.5Hz from controller to drive via Ethernet. The COP instruction is going to send 1110835200, yes? I don't have a drive available to test this, but I'd be blown away if it actually went to 45.5Hz.

Have I been missing the bigger picture this whole time? If so, please show us the magic worm hole that would allow skipping the additional code I'm currently having to write to re-scale and drop decimal points whenever I'm forced to mix and match data types. 

Share this post


Link to post
Share on other sites

When I said "gibberish", I just meant that it's not being interpreted correctly, not that information is "lost" or meaningless. Just that a DINT tag is "normally" interpreted as a signed integer and that the bit pattern of a REAL is therefore not going to be readable as a DINT. A lifetime ago, I actually wrote a subroutine once in a MicroLogix (I think...) that deciphered the IEEE Floating Point bit pattern to generate an ASCII string of the decimal number.

@ElectronGuru: The COP is useful when you're transferring a large number of tags (like an array) or when you need to "re-pack"/"unpack" the data when transmitting it between devices. In other words, you could COP an INT array into a DINT array to transfer it, then COP it back into an INT array at the destination. Note that the Length parameter of the COP instruction is the number of destination registers to transfer. So if you want to pack 20 INTs into 10 DINTs, the length would be 10. The Length would be 20 to go the other direction. I've also had to use it to copy STRING tags. Another trick is to use it to copy within an array. You can say "COP Array[1] Array[0] {length}" to shift the contents of an array up one position. It's a powerful instruction for moving data around. I've also had to use it to shift and pack INTs into larger arrays (or into smaller arrays) for legacy HMIs or to replace legacy HMIs with newer ones.

As I recall, the Powerflex drives I've worked with expect the speed reference to be an integer scaled to 0.1Hz. In other words, you would "send" the value of 455 to get 45.5Hz. In this case, you can MUL your REAL register by 10 with the destination the speed command. If your REAL only ever has a single decimal place, you won't lose any data or precision at all. Any remainder will be rounded.

It's quite possible that simply using the MOV instruction will do what you need as long as you don't mind rounding x.5 to even when going from REAL to INT/DINT.

Share this post


Link to post
Share on other sites

@Joe E. I didn't intend to misrepresent your remarks. I, too, would've used the word gibberish to describe data that I can't use because the formatting is incorrect, and I believe that's what you were saying.

When teaching I often describe COP colloquially as "a more powerful MOV". I had responded above to @VFD Guy that since COP is used to move arrays of data around, I don't understand how it's used to convert Float or REAL to DINT and have meaningful results.

My question to @VFD Guy and @panic mode remains; how do you use COP to successfully convert a REAL to a DINT and have the result be useful, since the resulting data looks nothing like what we'd want it to? I've also run into the decimal point thing with PowerFlex drives and have always just used the MUL to get rid of the decimal point so the drive will respond as desired.

 

On 4/15/2021 at 8:45 PM, VFD Guy said:

Get the reference I want as a real, copy to a DINT, send the DINT to the drive, the drive (750 in this case) would convert back to a real. You can look on knowledgebase.

Are you using the COP in lieu of MUL? If so, is that the only application for this method, or is it something can be used anywhere you're converting REAL to DINT? Or is the drive truly taking a controller's REAL value of 45.5Hz COP'd to the DINT value 1110835200 and converting it back to REAL?

I hate to sound like I'm slitting hairs or beating a dead horse, but I feel like there's something fundamental I might be missing here.  

Share this post


Link to post
Share on other sites

SO after running MAM instruction with live application here's my take.

If move parameter tags associated with the MAM instruction are declared as DINT's, the MAM will accept them and tries its best to convert the DINT tag values as close as possible to REAL values. Indeed the DINT to REAL values may NOT be completely accurate. BUT in the user application I am working they appear to be acceptable.

Thanks all for GREAT feedback.

Share this post


Link to post
Share on other sites
Quote

My question to @VFD Guy and @panic mode remains; how do you use COP to successfully convert a REAL to a DINT 

That's the thing... as already mentioned, COP does not do any conversion....

COP output is just a bit-by-bit copy of the source... possibly to a variable of different type. that's it...

Source value would have to already be in a correct format (bit-by-bit). If that is the case, one can use COP to simply transfer the value to REAL (from some other data type...).

When format is not the same, one need to do a conversion. For some conversions there are built in instructions. For others, one may may have to roll-up the sleeves and write own conversion code. 

 

Share this post


Link to post
Share on other sites

@panic mode that's what I thought, but appreciate you making the effort to be sure I hadn't misunderstood. 

Share this post


Link to post
Share on other sites

i know, they don't call Missouri "show me state" for no reason...   :kewl:

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now