Modbus - String Data Type

I am trying to get some data from an Electrical Energy Meter and the data type is listed as a String.
There is no data type for String Variables in the address settings for a device. KepwareEX supports strings. How can I do this with the Modbus Module?

Hi

Modbus protocol does not support string as real variable.
Only string support inside modbus I have seen on Char values on 8-bit or 16bit registers.
So basically you have to make small code/decode both end if want to swap strings.

I am quite sure that Energy meter is sending values on Chars.
And often they send 2 chars in one 16 register.

I have not use this with Ignition but I am sure that there is method to do this and if not you can make table comparision which will do this.

Br
Tommi Vahtera
THT Control Oy

I can use KEPSeverEX and read String data types.

String Support
The Modbus model supports reading and writing holding register memory as an ASCII string. When using holding registers for string data, each register will contain two bytes of ASCII data. The order of the ASCII data within a given register can be selected when the string is defined. The length of the string can be from 2 to 240 bytes and is entered in place of a bit number. The length must be entered as an even number. Appending either an "H" or "L" to the address specifies the byte order.
Note: For more information on performing block read on string tags for the Modbus model, refer to Block Sizes.
String Examples
1. To address a string starting at 40200 with a length of 100 bytes and Hi-Lo byte order, enter:
40200.100H
2. To address a string starting at 40500 with a length of 78 bytes and Lo-Hi byte order, enter:
40500.78L

The Electric meter Modbus Map indicates that the data is in ASCII.

I just havent figured out how to do it with the Modbus OPC driver.

KepServeEX is doing translation to characters.
After that you can see characters in OPC client instead of register values.

Like I wrote before , havent tested this in Ignition but in basic solution is to compare values to know ascii character codes; example if you can read first register value in decimal format 49, it means character 1.

Check example ascii table from cs.utk.edu/~pham/ascii_table.jpg

There is character codes in different formats.

At least in Python gives you Chr function which will return character, example Chr(49) returns 1.

Maybe this give you idea.

Have you checked that can you read values in integer or float formats?

BR
Tommi

Yes, I can read integer and floats.

In the Electric Meter (a Shark 100), The address I am needing to read is 8 different address (Address 1 thur 8) that contain a total of 16 Characters. I am still trying to fgure out how to break down the result from each address to combine it to the string I am seeking. Doing this was alot easier in Kepware.

Got any ideas on the script?

You would read each 16-bit value into a SQLTag, then use a script like the following to separate out the 2 characters:value1 = system.tag.getTagValue("value1") #Character in upper 8 bits. char1 = chr(value1 / 256) #Character in lower 8 bits. char2 = chr(value1 % 256) print char1, char2 You could then concatenate the characters together to reform the string.

I’m still looking at how to do this in SQLTags without any scripting…

Ok…. Now I guess I have to show my true ignorance. How/Where do I place this code. I tried to do it in the Scrip editor in the Event Handler but that didn’t work at all. I have read on many post here where people are using code to do fancy things…. I just haven’t got into the need (that I know about) where I needed to do special things until now. Guess its time to learn something else new which is fine for me.

Thanks for everyones help. This FORUM is the best I have seen.

I’d make it a Timer Event Script. Put it in the Gateway if you need to massage the string and log it, or the Client if you just need to display it.

Here’s the script I came up with:

[code]
v=[] # empty Value list

for i in range(3): #Number if Tags to read.
input=‘Path/InputTag(’+str(i)+’)’ # I named each tag as InputTag(0), InputTag(1), etc.
v.append(system.tag.getTagValue(input)) # puts each tag Value in a list

t="" # empty string

for i in v:
t= t + chr(i/256) #Gets the upper byte and converts to an ASCII character, than adds it to the result.
t= t + chr (i%256) #Gets lower byte and does the same thing

system.tag.writeToTag(“Path/OutputTag”,t) # writes result to a tag
[/code]

Although a String Data type in the OPC driver would be a lot easier. :laughing: