How: Convert Real No to Hex No in Simatic?

RPax

Member
Join Date
Feb 2004
Posts
125
Hi, I was wondering is it possible to convert a real number to a Integer number in Siemens Simatic s7 (so that the word can be read in Hex).

I've tried the following.
-Converted the Real Number to DI (Double Integer) using the Floor command.
- As the actual number was small I split the double Integer number i.e say DI Number was DB1.DBD100 but only used DB1.DBW102
- This DBW112 was then used in a calculation.

From Monitor Mode everything seems fine and I get the answer that I require. However from Monitoring the DB I get the Hex Format but in the FB Monitor I get the Dec format.

My problem is that I am sending this result down to a drive unit which only reads in the Hex format. The Format that is going down is the Decimal which the Drive unit interprets to be Hex and then gives a wrong result. Is there any way to ensure that the Hex number is sent or is it not possible due to the conversions that I have done previous. Appreciate anyones help. thanks
 
Yes, you can convert a real to a dint. Try this (I'm listing the STL code, but I imagine the same instructions are available in Ladder):

L RealNumber (load the real number that you wish to convert)
RND (Converts a real to a dint)
T DB1.DBW102

There is no specific conversion from DINT to INT, because by definition if a number is greater than 16 bits, it must be used as a DINT anyway. If the DINT, after the conversion, is greater than 32767, then you will have to do some clamping or scaling to be able to work with it. Also, in case it is important, you can also round up or down with teh RND+ and RND- instructions.

I'm not sure what you mean about converting it to Hex. If DB1.DBW102 has the value 1500, the drive will still get the binary equivelent anyway. It won't know or care about the origins of the value.

If it turns out that your DINT is larger than an INT, let us know and we'll see what we can do about scaling it so it can be usable to the drive.
 
He needs the REAL value coded in BCD format (some calls it HEX).

I thought that there would be an INT-to-BCD converter block in the standard library, but I cant seem to locate such a thing.
 
OK, its a standard instruction (not in a library):

ITB (16-bit integer to BCD). The range is limited to -999 to +999.
DTB (32-bit double integer to BCD) The range is limited to -9.999.999 to +9.999.999.

edit: Damn, S7guy, you beat me to it :( :)
 
JesperMP said:
He needs the REAL value coded in BCD format (some calls it HEX).


Are you sure?
I've never heard of BCD being called HEX.
I've always defined and understood it to be the Hexadecimal (base 16) number system where each digit can have one of 16 values (0-F).

Hexadecimal is a nice shorthand for binary as each byte is reduced to 2 hex digits.
 
I have seen it quite often that BCD coded numbers are called HEX numbers (even though it is thematically incorrect).

Anyhow, I assume that this is the problem because otherwise it could not explain RPax' difficulties with the drive.

"Binary", "Octal", "Decimal" and "Hex" is just different ways to represent a number coded in the same way (binarily).
So it would make no difference if RPax sends a decimal number to the drive and it needs a hexadecimal number. But it would make a difference if RPax sends a decimal number and the drive needs a BCD number.
 
Hi, firstly many thanks for your relyies. I'am not at this game to long but I have to say my initial understanding would of been on the same lines as Jimbo's.

My Understanding
Example: If I had the following
Binary Number: 0001 0001 1101 0111

The Conversions would be
Hex Number: 11D7
Decimal Number: 4567
BCD:11?7 (that the BCD could not be represented by such a binary number)
So I never thought of converting to BCD. Am I of track with the above?.

With Ref to my Drive: Initial Problem:
Calculated Int number that is to be sent is 4567
Drive Format (in Hex):11D7 (should be sent as Drive reads in Hex)
However, if 4567 is sent then the Drive would see this as a Int number of 17,767.

When I seperated out my calculations i.e if my answer was in DB1.DBW100 and then moved my answer to a new DB1.DBW? area before doing my next calculation (same done for the final answer) then it allowed me to send the Hex format to the drive. Which solved the problem???. I'll go through what your were saying and try it out sometime today. Again, thanks for taking the time to reply.
 
Hi RPax,

to pick up your example:
Binary: 0001 0001 1101 0111
Hex: 11D7
Decimal: 4567

BCD: 4567
Binary representation of the BCD number:0100 0101 0110 0111
HEX representation of the binary number would look like 4567
Decimal representation of the binary number would look like 17767

Are you saying that "4567" is sent to the drive, and it arrives as "17767" ? Are you seeing this value on a display on the HMI ?

What does the manual say about the required data format ?
Exactly what type is the drive ?

edit:
You say "The Format that is going down is the Decimal which the Drive unit interprets to be Hex and then gives a wrong result."
Where do you get the information that it "interprets in Hex" ?
 
Last edited:
Hi Jesper,
I am using a Mitsubishi E500 drive but I am communicating to this drive via a Profibus DP FR-E5NP Card (http://www.mitsubishi-automation.de/download_english.htm) although I am working from a FR-E500 Communications manual(Profibus DP Section) where all communication examples are done in Hex format \ not sure where I got this from on net.

This card is a slave and I am preforming my control in Simatic S7. It is this card that requires the Hex format and the card requires 6 words to be sent for every command.

What I was trying to do is change the frequency of an inverter. (The value that I used above weren't my exact values). I had a feedback from my inverter linked to WinnCC and I was monitoring the speed on a Graph.

When I sent down my frequency I could see the graph climing above what I expected and I would then switch off the motor just incase it got to a dangerous speed as I wasn't exactly sure what was happening. I then presummed that the inverter was receiving the Dec Number thinking that it was a Hex Number thus giving the increased speed.

I should of been more clear with what I was trying to do so sorry about that. Again thanks
 
Hi RPax,

I have had a look at that manual, NOT easy to navigate or understand !
(well, I have never seen a manual for a VFD that was easy).

1. I have seen one place that you can read the set frequency in increments of 0.01 Hz/bit.

2. Another place the formats "AUs16" and "Us16" are mentioned. I cant find an explanation of what they mean, but I would guess that Us16 is an Unsigned 16-bit integer.

Both 1. and 2. indicates the same, namely that the data is unsigned 16-bit integers. No mentioning of BCD or HEX.

The S7 dataformat INT is signed . As long as you only have values between 0 and 32767. If that interprets as 0-327.67 Hz and you dont have to exceed that, then you should be in the clear.

I can see two pitfalls:

1. S7 to EF200 to WINCC, there are three places where the format must conform (and can go wrong). If the drive has a display where you can read the frequency, then I would check this display and compare with S7 and WINCC. Trust that the display will indicate the real thing.

2. There is something called "byte swapping". It has something to do with the idiotic way Siemens packs two bytes into one word. It means that in order to be compatible with other manufacturers devices, byteswaping must be set or must not be set.
In the manual there is a place where byte swapping is explained.

I cant promise you that this will solve your problems, its only a few suggestions that you could look into.
 
Let me clarify a couple of things. The range of that drive is 0.00 to 400.00 Hz, represented by a decimal 0 to 40000. In the Siemens world, I can still transfer 40000 to the drive, even though if we look at the value in a VAT table it will appear negative.

For instance, let's say that MW50 is the value we want to send to the drive, and I want to run it at 380Hz. I could write this code:

L L#38000
T MW50

Then, I could pass MW50 to the Drive Output area, and the drive would see a decimal 38000 (or Hex 9470).

The confusion arises when I want to monitor MW50 online. If I write this code in OB1 and set the representation to Decimal, I will see 38000 in accumulator 1. If I switch it to hexadecimal, I will see 9470. But if I open a VAT table, and choose DEC format, I will see -27536, which of course is still 9470 in Hex. In fact, I can even transfer a -27536 to MW50 instead of the L#38000, and the drive will run at the same speed, because the bits that the drive sees are ultimately the same.

Of course, this can cause a lot of confusion once an HMI gets involved, or if you want to monitor blocks online. So, even though you can work with unsigned INTs within S7, it truly makes my head hurt even thinking about it, so I always do all the math with DINTs, represent the feedback and setpoints on the HMI with DINTS, and keep the unsigned INTs at the local machine control level. To oversimplify RPax's example, we could do something like this:

L L#38000
T MD40 (This will be displayed on an HMI)
T MW50 (This will be sent to the drive)

This will work up to L#65535, but the drive peaks out at L#40000 anyway.
 
This issue of data types is one of the beneficial things that came out of IEC1131-3.

That standard quite clearly defines an INT data type (integer) as being a 16-bit numerical value scoped between -32768 and +32767. Strictly, any value outside that range should not be regarded as an INT. This means +32768, +32769 ... +38000, and all the way up to 65535 are not valid INT values.

One of the other 16-bit data types defined by IEC1131-3 is the WORD. The key thing here is that it is a logical bit pattern, not a numerical value. According to IEC rules you can not perform arithmetic operations on a WORD variable, just as you can not perform logic operations (like AND, OR) on an INT.

This is why a value of +38000 should be regarded as a DINT. What your first two lines of code do are to load +38000 in to a 32-bit accumulator (so no problem there), but then to transfer it back out to a 16-bit MW address. The net result is that the 16 least-significant bits of the accumulator get copied to MW50. Of course, you then find that interpreting MW50 as an INT (or decimal) uses the most-significant bit as a sign indicator, hence you see -27536. If you want to experiment, try viewing MD48 (assuming you have no other data in MB48, MB49 or MW48). Here, you will be viewing a 32-bit register in which the most significant bit is again used as the sign. The MSB here is M48.7 and given the previous assumption of MW48 being all zeroes, you should see the display of 38000.

Ultimately your own solution seems to work, but I thought this might help explain why.

Regards

Ken.
 
This issue of data types is one of the beneficial things that came out of IEC1131-3.

That standard quite clearly defines an INT data type (integer) as being a 16-bit numerical value scoped between -32768 and +32767. Strictly, any value outside that range should not be regarded as an INT. This means +32768, +32769 ... +38000, and all the way up to 65535 are not valid INT values.

One of the other 16-bit data types defined by IEC1131-3 is the WORD. The key thing here is that it is a logical bit pattern, not a numerical value. According to IEC rules you can not perform arithmetic operations on a WORD variable, just as you can not perform logic operations (like AND, OR) on an INT.

This is why a value of +38000 should be regarded as a DINT. What your first two lines of code do are to load +38000 in to a 32-bit accumulator (so no problem there), but then to transfer it back out to a 16-bit MW address. The net result is that the 16 least-significant bits of the accumulator get copied to MW50. Of course, you then find that interpreting MW50 as an INT (or decimal) uses the most-significant bit as a sign indicator, hence you see -27536. If you want to experiment, try viewing MD48 (assuming you have no other data in MB48, MB49 or MW48). Here, you will be viewing a 32-bit register in which the most significant bit is again used as the sign. The MSB here is M48.7 and given the previous assumption of MW48 being all zeroes, you should see the display of 38000.

Ultimately your own solution seems to work, but I thought this might help explain why.

Regards

Ken.
 

Similar Topics

Hi all. Me again still learning Rockwell. So I'll be polling an INT data array from a Modbus SE power meter with a L82 (with a Modbus ProSoft in...
Replies
56
Views
1,384
Hello, First, please excuse my question I am new to Modbus. I have a CX-5140 control unit from Beckhoff and an instrumentation device that...
Replies
3
Views
3,114
Greetings fellow PLC programmers, I know there is a simple way to get the system date time of the RSLogix system. But, is there then a way to...
Replies
12
Views
8,585
Hi Guys, i'm begginer and i'm trying to convert a real value (not fix value) to BCD. It works if i put fix real value but when i put variable...
Replies
2
Views
1,940
I converted 2 consecutive Ints to a Real using a Copy instruction. So now I need to reverse this process. Convert a Real into 2 consecutive Int's...
Replies
9
Views
2,448
Back
Top Bottom