Convert Hex to Binary

Declare three variables, Final_Number, Temp_Hex and Character_Pos.

CLR Final_Number and Character_Pos

Do this while Character_Pos < String_Length
MOV String_Data[Character_Pos] to Temp_Hex (*)
Subtract 48 from Temp_Hex (*)
If Temp_Hex > 15 then subtract 6 from Temp_Hex (*)
Multiply Final_Number by 16
Add Temp_Hex to Final_Number
Add 1 to Character_Pos
You should end up with Final_Number being equal to the string representation.



We are starting from the leftmost character of the string, getting its ASCII value, converting that to 0-15, left shifting Final_Number by 4 bits and adding in the converted character. We continue until we have processed the last character.

By the way - if you only want the value from one position then the starred (*) instructions are all you need.


I can work with each position and break it down. This will give me what I need, but I want to understand everything you explained above. I get the -48 to get the decimal # and -7 if over 15 to break down the letter. I am a little lost on the X 16 and add to shift 4 positions. I can't seem to wrap my head around it.

Thanks for the lesson

Kevin
 
The starred instructions (*) get 1 character ('0' thru '9' or 'A' thru 'F') and adjusts it to become a number (0-F hex).

Wrapped around these three are the necessary commands to:

1. Step through the entire string, picking off one character at a time starting with the leftmost character.

2. The conversion as noted above

3. Then assembling a full DINT which will end up with the value as represented in the string. We do this by:
    1. Starting the DINT at zero
    2. With each pass multiplying by 16 which has the effect of shifting its bits over 4 places to the left.
    3. Adding in the result of that character conversion.
Thus the routine has to loop through each character position in the number string that you receive.

Again, if you only want one character from the string then don't worry about all this looping stuff and just use the starred steps. The 'Temp_Hex' is the number you want in this case.
 
Hey Kev,

I think you are confused about the data types. Regardless of whether you are viewing a SINT or DINT as Decimal, Binary, Octal, or Hexidecimal, the PLC is storing it in memory as a binary number. Changing the way you view them in RSLogix doesn't change them from Hex to Binary. It simply changes they way you are seeing them. It's mearly a convenience feature for us humans.

If you are starting with the ASCII value "00520000" stored in a string variable, you can convert this ASCII string to a number that the PLC can use via the STOD command.

Since it's a hexidecimal number, each number represents 4 bits. There are 8 hexidecimal characters. So...

8 x 4 = 32bits

A SINT is only 16 bits, so you should store the resulting value of the STOD command to a DINT since they are 32 bits.

Now that you've converted, you can address the individual bits using the MyTag.Bit convention discussed above.
 
Oops... yeah you're right Bernie.

Kev - After actually reading the thread, Bernie's approach is the way to go. Just make sure you are working with uppercase ASCII characters before you start the conversion algorithm.

Code:
Binary   Hex   ASCII
0000     0     48
0001     1     49
0010     2     50
0011     3     51
0100     4     52
0101     5     53
0110     6     54
0111     7     55
1000     8     56
1001     9     57
1010     A     65
1011     B     66
1100     C     67
1101     D     68
1110     E     69
1111     F     70
 
I will post a screen shot on how I have it set up now in the morning. It seems to work good but it looks ugly. I am sure there is a cleaner way to write it and I would like anyones thoughts. Currently I have a rung with (8) SUB instructions, one for each position.

Example:

Rung 1

string[0] - 48 = temp[0]

string[1] - 48 = temp[1]

string[2] - 48 = temp[2]

and so on...

Rung 2


string[0] GRT 15, SUB 7 to Binary 0 (SINT I think)
string[1] GRT 15, SUB 7 to Binary 1
string[1] GRT 15, SUB 7 to Binary 2

and so on...

Rung 3

string[0] LES 15, MOV string [0]to Binary 0
string[1] LES 15, MOV string [1]to Binary 1
string[2] LES 15, MOV string [2]to Binary 2

and so on...

I am going to try Bernie's total number solution in the morning. Thanks for all the suggestions.

I first contacted Rockwell last week and they we no help. They could not find a way to get it done. At first they thought I was crazy until they tried to convert ASCII 5 and got 53. I guess I should have gone here first! Thanks all...


Kevin đź“š
 
I will post a screen shot on how I have it set up now in the morning. It seems to work good but it looks ugly. I am sure there is a cleaner way to write it and I would like anyones thoughts. Currently I have a rung with (8) SUB instructions, one for each position.

Example:

Rung 1

string[0] - 48 = temp[0]

string[1] - 48 = temp[1]

string[2] - 48 = temp[2]

and so on...

Rung 2


string[0] GRT 15, SUB 7 to Binary 0 (SINT I think)
string[1] GRT 15, SUB 7 to Binary 1
string[1] GRT 15, SUB 7 to Binary 2

The "string[0]" be "temp[0]" and the "7' should be a "6"

and so on...

Rung 3

string[0] LES 15, MOV string [0]to Binary 0
string[1] LES 15, MOV string [1]to Binary 1
string[2] LES 15, MOV string [2]to Binary 2

and so on...
I can't figure out what this section is doing

I am going to try Bernie's total number solution in the morning. Thanks for all the suggestions.

I first contacted Rockwell last week and they we no help. They could not find a way to get it done. At first they thought I was crazy until they tried to convert ASCII 5 and got 53. I guess I should have gone here first! Thanks all...


Kevin đź“š
I shortened your steps eliminating a variable

string[0] - 48 -> Binary 0 (at this step Binary 0 is correct if the original character was "0" through "9"

if Binary 0 GRT 15 then Binary 0 SUB 6 -> Binary 0 (SINT I think)
this step corrects if the original character was "A' through "F"
 
Ok I suck at explaining what I did so I have attached screen shots to give a better picture.

As for the -6 instead of -7, when I get an "A" I thought I should see "1010". So if I break it down as stated above I get;

"A" = 65

65-48 = 17

Because it is over 15, -6

17-6 = 11

11 = "1011"



If I use -7;

"A" = 65

65-48 = 17

Because it is over 15, -7

17-7 = 10

10 = "1010"

Am I missing something?

Thanks for the response
 
Kev - Since you seem to have your head wrapped around converting the individual characters from ASCII to INTEGER, here's an explanation of what you were calling Bernie's whole number solution. The example uses a 16 bit SINT for clarity, but the algorithim works just fine for a 32 bit DINT.

Pre-requisites

ASCII String to Be converted = "FEDC"
temp_hex = 2# 0000 0000 0000 0000
final_number = 2# 0000 0000 0000 0000


STEP 1

Code:
FEDC
^
Convert first character from ASCII to INTEGER, and store it in temp_hex

temp_hex = #2 0000 0000 0000 1111 (0x000F)

Multiply Final_number by 16 and end up with

final_number = #2 0000 0000 0000 0000 (0x0000)

Add temp_hex to Final_number

final_number = #2 0000 0000 0000 1111 (0x000F)


STEP 2

Code:
FEDC
 ^
Convert second character, and store it in temp_hex

temp_hex = #2 0000 0000 0000 1110 (0x000E)

Multiply Final_number by 16 and end up with

final_number = #2 0000 0000 1111 0000 (0x00F0)

Add temp_hex to Final_number

final_number = #2 0000 0000 1111 1110 (0x00FE)


STEP 3

Code:
FEDC
  ^
Convert third character, and store it in temp_hex

temp_hex = #2 0000 0000 0000 1101 (0x000D)

Multiply Final_number by 16 and end up with

final_number = #2 0000 1111 1110 0000 (0x0FE0)

Add temp_hex to Final_number

final_number = #2 0000 1111 1110 1101 (0x0FED)


STEP 4

Code:
FEDC
   ^
Convert fourth character, and store it in temp_hex

temp_hex = #2 0000 0000 0000 1100 (0x000C)

Multiply Final_number by 16 and end up with

final_number = #2 1111 1110 1101 0000 (0XFED0)

Add temp_hex to Final_number

final_number = #2 1111 1110 1101 1100 (0xFEDC)

final_number now contains the converted version of your ASCII encoded hexadecimal string.

[I also was using -7 on the conversion of the A-F characters. I'm not sure why Bernie's insisting on using -6.]
 
Last edited:
Thanks monkeyhead - I have recanted my -6 fixation. It seems that every time I recreate this sequence in my head for the various processors I've done it on I somehow think about the six digits after 9 in the hexadecimal system. Of course the distance between '9 and 'A' in the ASCII table has nothing whatsoever to do with the 6 digits. If they had designed it with 'A' 23 positions after '9' I probably wouldn't get confused but the closeness misleads me when I look at the table and my mind just snaps on to the 6 figure. As if I can't count. Next I'll probably start doing things like hanging around PLC forums all day. Oh - wait - that's what I do!!! Oh no!
 
Note that this algorithm fails if a non-hex character is in the string. I am working on an AOI for ControlLogix to perform this with appropriate fault detection and graceful exit. (And I will subtract 7 instead of 6)
 
Last edited:

Similar Topics

Hi I need to convert a DINT with HEX value e.g A0F15663 to a string with the same value 'A0F15663'. Any tips of good instructions to use ...
Replies
11
Views
3,452
I actually solved this, but I thought this info may help others. Condition which prompted this need: I was using a function provided to me by...
Replies
13
Views
3,774
Hey All, i have been fortunate enough to play around with an Applied Motion Products Servo Drive SV200 with 100 watt/ 24vdc congif. I managed...
Replies
2
Views
1,910
I'm trying to display a Allen Bradley Controller Serial Number that's in HEX to String for my SCADA to display. Any ideas?
Replies
3
Views
2,906
Hi All. I have a PLC connected to citect by modbus.I need to transfer a value in HEX from the PLC to the Citect, and to convert it to Time value...
Replies
12
Views
4,330
Back
Top Bottom