Our full technical support staff does not monitor this forum. If you need assistance from a member of our staff, please submit your question from the Ask a Question page.


Log in or register to post/reply in the forum.

Convert ASCII String to Hex


bKlippert Dec 17, 2010 12:49 AM

Hello,

I've got GetRecord pulling the last record from an event driven table and storing the data into a single variable 'As String * 256'.

"2010-11-26 19:41:56",32,27,0.005,0.005,0.006,0.003,20.34,0.053,0.123,0.053


I want to convert the ASCII string into it's Hex equivalent.

22 32 30 31 30 2D 31 31 2D 32 36 01 31 39 3A 34 31 3A 35 36 22 2C 33 32 2C 32 37 2C 30 2E 30 30 35 2C 30 2E 30 30 35 2C 30 2E 30 30 36 2C 30 2E 30 30 33 2C 32 30 2E 33 34 2C 30 2E 30 35 33 2C 30 2E 31 32 33 2C 30 2E 30 35 33


Is there a 'easy' way of doing this?

I think I may be able to specify GetRecord to store each field to an array, then convert each field to Hex. But then does GetRecord store the TimeStamp when data is pulled to an array (like it does to a single variable)?

Any help is greatly appreciated!


Dana Dec 17, 2010 01:02 AM

The CRBasic Editor has a Hex instruction. I think this will do what you need.

Dana


bKlippert Dec 17, 2010 01:21 AM

Not exactly.

Because the variable which Hex is trying to convert is declared 'As String * 256' it won't work.

Unless there's a way I can store the string below, to a variable that Hex can work with I will have to go a different route.

"2010-11-26 19:41:56",32,27,0.005,0.005,0.006,0.003,20.34,0.053,0.123,0.053

This is the response I get when trying to compile (where paramater 1 is the ASCII string I'm trying to convert):

line 206: Parameter 1 cannot be STRING type


IslandMan Dec 17, 2010 12:18 PM

There may be a simpler way to do this but I'm a brute force kinda CRBasic guy:

'CR1000 Series Datalogger

'Declare Public Variables
Public PTemp, Batt_Volt
Public TableString As String * 200
Public HexString As String * 200
Public RecLength
Public Dec As String
Public AsciiVal
Public x

'Define Data Tables
DataTable (Test,1,1000)
DataInterval (0,15,Sec,10)
Minimum (1,Batt_Volt,FP2,0,False)
Sample (1,PTemp,FP2)
EndTable

'Main Program
BeginProg

Scan (1,Sec,0,0)
PanelTemp (PTemp,250)
Battery (Batt_Volt)
CallTable Test

'If table written
If Test.Output(1,1) Then
HexString = ""
GetRecord (TableString,Test,1)
'Get length of string
RecLength = Len(TableString)
'Trim the CR/LF off the end
TableString = Left(TableString,RecLength-2)
'Get length new length of the string
RecLength = Len(TableString)

For x = 1 To RecLength
' Get the Ascii valuse for the character
AsciiVal = ASCII(TableString(1,1,x))
' Convert to hex
Dec = Hex(AsciiVal)
'Add a zero to keep things neat if required
If Len(Dec) = 1 Then Dec = "0" & Dec
' Create the hex string
HexString = HexString + Dec + " "
Next x
' Lop off the trailing space
HexString = RTrim(HexString)
EndIf

NextScan
EndProg


aps Dec 17, 2010 12:27 PM

Dave, I had just written exactly the same thing and was validating the result! I was confused though as there is an error. However this seems to be a fault in the original post as BKlippert says:

"I want to convert the ASCII string into it's Hex equivalent.

22 32 30 31 30 2D 31 31 2D 32 36 01 31 39 3A 34 31 3A 35 36 22 2C 33 32 2C 32 37 2C 30 2E 30 30 35 2C 30 2E 30 30 35 2C 30 2E 30 30 36 2C 30 2E 30 30 33 2C 32 30 2E 33 34 2C 30 2E 30 35 33 2C 30 2E 31 32 33 2C 30 2E 30 35 33"

There is a hex value in there of 01, that is clearly spurious!

It may also be worth mentioning, that whatever the reason for this, the output string needs to be 3X bigger than the max input string length because that is a consequence of this conversion.

* Last updated by: aps on 12/17/2010 @ 5:29 AM *


IslandMan Dec 18, 2010 10:30 AM

Andrew,
Great minds think alike :-)
I had trouble putting his original string in as a string variable due to the " " around the time stamp so I thought this example was good enough.

The Hex string adds at least one extra character in the string for each original character, then the additional space in the string between hex values is what makes it 3 X bigger, no?

* Last updated by: IslandMan on 12/18/2010 @ 3:35 AM *


bKlippert Dec 21, 2010 11:45 PM

Re: Surpious Hex. You're right 01 is incorrect.

Re: Brute Force Approach. This is what I ended up doing. Thanks!


Now; however, I need to transmit the same Hex string as Binary using SerialOutBlock.


I'm unsure how to format the string in a way which SerialOutBlock() can use it.

CR1000.pdf hints at using an Array of Type Long.


Using the Terminal Emulator I can watch as the string gets transmitted incorrectly.

I'm using SerialOutBlock(ComRS232,TX_String,TX_String_Length); where TX_String is a string of Hex pairs (without the whitespaces), and String_Length is the string length + a two byte checksum (also in Hex).

When SerialOutBlock goes to transmit based on the TX_String_Length is acts on each nibble as though it were a complete byte.

ie: "hello" as Hex = 68656C6C6F (TX_String_Length = 5)
"hello" + checksum = 68656C6C6F(0214)

On the Terminal Emulator "68656c6" is all that gets through in ASCII and "36 38 36 35 36 43 36" is all that gets through otherwise.

I've tried accommodating the TX_String_Length so that the entire message goes through, but that doesn't appease my modem.

Any help is much appreciated.


IslandMan Dec 22, 2010 11:47 AM

Here is a hex string I make up to Poll a sensor:
PollString1 = CHR(254)&CHR(65)&CHR(99)&CHR(96)&CHR(01)&CHR(53)&CHR(232)&CHR(83)
Here is the SerialOutBlock:
SerialOutBlock (Socket,PollString1,8)
This works fine for me.

I believe the string length is the total of all the characters, not the hex pairs. Also, what length do you have TX_String dimensioned for? It has to accommodate all of your characters plus your checksum characters.

* Last updated by: IslandMan on 12/22/2010 @ 4:47 AM *


bKlippert Dec 22, 2010 04:50 PM

TX_String As String * 1000
TX_String_Length

The above should suffice...


Would your PollString1 work if it had the Hex value for A/CHR(65): &h41, in your string?

Judging by your success I'm guessing not. I may have to convert each Hex back into Dec for SerialOutBlock to work.


Going off topic now. The modem I'm using has the ability to accept a Binary string as with SerialOutBlock, it also has the ability to accept an ASCII string as is. With the Binary string the modem requires a checksum be applied but with the ASCII string it does not.

I'm struggling to see the benefits of one or the other. With the ASCII string each transmission seems to go through without error and the code is 'easier'. With the Binary string it involves extra effort (in code) to massage the string and calculate the checksum. I can see the need for one or the other based on the format of data you have initially, but if you've got the option what's best? Anyone with experience is welcome to comment.


aps Dec 22, 2010 09:25 PM

I think we need to take a look at terminology here as there is a lot of scope for confusion.

1) An ASCII string is a string comprising of a series of characters. Each character is in fact a single byte which has a value which can be expressed in decimal terms (0-255). Some people, when they say ASCII, often mean just printable characters, i.e. common text characters, in the range of 32-125'ish in decimal terms. However, there are non-printing ASCII characters too, so an ASCII character, according to the original definition can be in decimal terms any character from 0 to 127 (decimal). Some extend the definition up to 255 for 8 bit data.

2) A binary string is actually no different to an ASCII string. The term binary is more often used when there is a significant chance of non-printing characters being included and characters which in decimal terms can be >127.

3) A hex string is not so well defined. Usually it is a representation of a string of binary characters where each byte is represented by a two character hex representation, in the range from "00" to "FF". In some cases, either spaces or some other characters are used as delimiters. This makes the string at least twice as long as original, but the hex string itself is an ASCII string comprising only of printable characters. Hex is commonly used at it has the advantage that is can be transmitted as 7-bit characters through modems, etc, that are limited to 7-bit transmissions. There are some other types of hex strings, for instance those that directly represent binary numbers, e.g. a four byte IEEE4 float, but the end result is the data is encoded as a series of ASCII characters limited to 0-F.

One big area of confusion is in the documentation for the some sensors which either input or output non-printing binary characters. Often that documentation represents those transmissions in hex simply because you cannot print the non-printing characters in a book. It is quite common for people to think the sensor outputs the hex shown rather than binary messages because of poor explanation of the hex representation.

As far as the dataloggers are concerned, there is no difference in terms of receiving or sending printable ASCII or true HEX data. You can use the standard serialin and serialout commands to send the strings. In the case of serialout the instruction will send the full length of the string without you needing to tell it the length.

Where you need to be careful is with binary data where the binary data may include null (decimal zero) characters. This is because the logger uses that character as a terminator for its string variables. If the string you need to send or receive could include a null, then you need to be careful and use Serialinblock or Serialinrecord for input and Serialoutblock for output as all of those instructions do not try to determine the end of the string by the presence of nulls. Instead those instructions rely on you giving the length of the data or delimiters that surround the data you want. Preparing a string for transmission or processing received data which includes nulls also needs care, but that is another story.

I hope this makes some issues clear and may help you resolve whether you need to encode the data in hex and if you do the easiest way to transmit it.


IslandMan Dec 23, 2010 11:12 AM

bKlippert:
The second character in my poll string is CHR(65) So I'm not sure why you think it wouldn't work.

Andrew:
thanks for the terminology clarification, I've copied it off for future reference.


bKlippert Dec 23, 2010 05:18 PM

aps, thanks for clarifying.

Focussing on SerialOutBlock; will this function only work on ANSI characters? From what I've seen this is the case.

Whether you feed it A or CHR(65) it would see this as string length of one and work as expected.

I was feeding it Hex 41 which to SerialOutBlock is ANSI 4, and ANSI 1 (string length 2). I would have to convert Hex 41 to Decimal, then pipe that into CHR.

Please correct if I'm wrong.


aps Dec 23, 2010 09:38 PM

I am a little confused as to what you are trying to do with all these conversions, but to answer your specific questions presuming, you mean ASCII not ANSI, "A" / chr(65) if assigned to a string would give you a string of length one and could be sent by Serialoutblock or Serialout.

If you have a string "41" which is a hex representation of a single byte/character, this is still a string of length 2, which is the length you would specify to send it with Serialoutblock or you can send with the Serialout with no length specified.

If you want to convert it back to the decimal equivalent you can use the HextoDec function which will convert it to an integer, i.e. if hxtring holds the two byte string, use result=hextodec(hxstring). IF you want to convert it all the way to a single character use chr(hextodec(hxstring)).

Log in or register to post/reply in the forum.