Transmit Hex String via RS-232

Hi,

I’ve set up a chart in PAC Control that sends and receives strings using the SNAP-PAC-R1 RS-232 port. I’ve tested it between the R1 and a PC with simple text/string messages, but now I need to communicate with a piece of equipment that expects to receive hex strings (Example: 0xCA 0x00 0x01 0x70 0x00 0x8E). If sent as a string, it doesn’t work since I’m assuming it’s being sent as ASCII characters. Would someone be kind enough to point me in the right direction?

Thanks,
-Tom

If “hex string” means binary then you can use the append character to string command to add the binary value to the string that you are going to transmit.

In OptoScript you can piece together what you listed like this:

sTransmit = Chr(0xca) + Chr(0x00) + Chr(0x01) + Chr(0x70) + Chr(0x00) + Chr(0x8e);
This can just as easily be written in decimal as well:
sTransmit = Chr(202) + Chr(0) + Chr(1) + Chr(112) + Chr(0) + Chr(142);

That basically builds a binary string of CA000170008E (6 bytes).

That is a pretty brute force way to do it and there are likely better ways, but it would depend on what you are trying to do.

1 Like

Thanks! I had a feeling that was the direction I needed to go and yes, I meant binary hex. You say it’s “a pretty brute force way to do it”, what would you suggest?

I’d like to poll the equipment at regular (1 sec?) intervals for temperature, pressure, flow, etc. and use the returned values to change gauges in my display. I’ve got it doing exactly that with your help above, but I’d be open to suggestions.

Thanks again,
-Tom

Typically you are sending out the commands based on some sort of protocol with a rigid format. For instance, you may need an address, a command, and a checksum. These value will likely be integers that you would store in variables that can be passed to a subroutine to create (pack) the “buffer” to send out on the wire.

The idea being when complete, you would build your transmit string like this:

BuildProtocolTxString(sTransmit, nDeviceAddress, nGetStatusCommandNumber);

and the subroutine would calculate any required checksums and pack the string together. This makes it easy to add additional commands.

There would be a separate routine to parse the response.

Whether this is a worthwhile effort or not really depends on the scope of the project and skill levels.

If you have time, take a look at pages D-2 through D-10 of the below linked manual to better understand what I’m working with. The string I originally asked for help with was “REQ TEMP1”. I’m now trying to work with “REQ STATUS” to manipulate the visible/invisible state of small indicators in Display for certain parameters in the Status Table provided on page D-9. I’ll also ultimately need to continuously poll “REQ FLOW1” and “REQ ANALOG1” to display their values in Display gauges.

Would you consider this a “protocol” per se? I do feel like I’m kind of “stabbing” with these transmit & receives right now as opposed to a more streamlined transmit/receive “dance”, if that makes sense.

Yes, that is a protocol. Doesn’t look too bad.

If you are only sending "REQ’ commands your transmit command is very similar for all of them, the only change is the command number and the checksum.

How are you calculating the checksum? It would be good to have the strategy calculate this. This way you can verify a good checksum on the response.

The response processing will be more difficult than the request since it can have a variable amount of bytes and you may want to handle some unit conversion.

On a quick look, I would create subroutines for the following:

Calculating the checksum
Building the command string
Transmit the command and return response payload (this would validate the response checksum and return just the n d-bytes through d-byte n values)
A process response subroutine for each command type you want to handle - so one to handle temperatures, one to handle status, one to handle flow, etc.

Each of these subroutines would be fairly small and helps break down the problems into smaller steps. Don’t forget that subroutines can call other subroutines. The basic rule for subroutines is that if you find yourself creating the same flow logic multiple times, then you probably can use a subroutine.

Let me know if you need any specific help.

1 Like

I’ve hit a bit of a snag in the parsing of the status coming from the chiller. It’s spread over 4 bytes and each bit indicates a state of a particular status point (high temp, low temp, etc). How can I convert between hex and binary to extract and use the single bit states for my status indicators?

I truly appreciate the help getting past these hurdles.

-Tom

You want to use bit masking for this. If you only need to check a single bit, check out the IsBitOn command. You can also use the bitand command/operator. Below are some examples of both.

If you need to check if the bit in position 2 (least significant bit is position 0) is on:

If the status bytes are in an integer:

StatusOn = Status bitand 0x04; //0000 0100 binary

or you can do this

StatusOn = IsBitOn(Status, 2);

If your status is still in a big endian string buffer, sStatus of four bytes, and you want the 10th bit (least significant bit is the 0th bit):

StatusOn = IsBitOn(sStatus[3], 2); //Get this bit: 0x00000400

or you can do this

StatusOn = IsBitOn(Status[3], 2);

1 Like