Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

Simulation of Modbus TCP/IP - Small Program for Fetching Data

Status
Not open for further replies.

rotw

Mechanical
May 25, 2013
1,143
0
0
CA
Hello All,

First of all, apologize for my ignorance on the topic but my problem is as follows:

I am trying to create a small program that fetches data from Modbus e.g. TCP/IP;
I've used a Modbus simulator available for free in internet. Now I try to make sure I can read the Modbus data from program directly by connecting to the correct port, address, etc.

The concept is as follows:

Sensors A (say a pressure transmitter) sends an analog output 4-20 mA to control system.
The control system pass the same signal to DCS via Modbus protocol. We know the Modbus address of the subject Analog output.

What I've been able to do so far is read via the correct port and settings from host Modbus (simulated) the value of register (0,1,2 etc.) based on address, directly with the program. Whatever the value format is, I can fetch it as is.

Suppose (virtually) that my pressure transmitter outputs 10 mA (say this corresponds to 10 bar pressure just to put things into context).

My question,

Knowing the address (say it is '30001'), how will 10 mA value typically / usually be passed/written by DCS to register?
Is it as floating 32 bit? If this is so, can I read then the value from the register directly (which will get me the value=10) in which case I would convert it to 10 bar knowing the calibration range afterward? Is this how it works?

It would be then 'relatively easy' to simulate 10 bar, just by typing in '10' as value in the simulator register and then read the data in my program.

Can someone help me and provide some pointers... thanks!



Life is not about waiting for the storm to pass. It's about learning dance in the rain.
 
Replies continue below

Recommended for you

MODBUS doesn't have data types. Each register is simply 16 bits. You decide how to store the number into the register. You may want to convert to 0-100% an then send it that way = 0-100. Or, send it as 4-20mA with a decimal = 40-200.

There is a program called MODSCAN that can read registers from a device. Pretty handy for testing.
 
LionelHutz,

Thanks for the hint. Do you know if MODSCAN is capable of passing data to a third party program (like a program in VB or C#)?

Another question, If I have to fetch data that is static but noisy (as it is the case in real applications).
I would like to reduce the random uncertainty and for this I would read a number of samples and make an average; for example 10 sample per second and average them.

Is this something that Modbus can tolerate? I mean is there some sort of latency that would prevent me from reading above and beyond a certain sampling rate for example?

Thanks

Life is not about waiting for the storm to pass. It's about learning dance in the rain.
 
Modbus is a protocol for transferring 16 bit data words from one device to another. The format of the slave's data is defined by whomever provides the device. For Modbus slaves (field instruments), there is a table in the documentation the defines whether the bits in the data word are a signed integer or an unsigned integer or a 32 bit floating point value (requires 2 adjacent 16 bit registers) or a 64 bit floating point value (requires 4 adjacent 16 bit registers) or some bit packed value like a time stamp or a firmwawre version or an ASCII message. It's up to the master/client to decode the bits appropriately. Modbus doesn't know or care what the data represents, it just sends or receives registers of 16 bits back and forth. It's up to the implementer to interpret the data correctly. Modbus does NOT send engineering units as part of the value - Eng units should be described in the documentation. Sometimes there's a multiplying factor that needs to be applied to an integer value.

Modbus master/clients do not have value tables because the master/client decides what happens to the data that comes in. Which is how and where you produce code to average multiple values before doing whatever with the averaged value.

Modbus doesn't care if you average values, it has nothing to do that. I'm not sure where 'latency' comes into play. There are throughput issues with Modbus as there are with every non-deterministic protocol.
 
Thank you all for your info, most appreciated.

Therefore, I will add to the program a drop down list that selects the format depending on the ICD or IDD.

In the Modbus list document (project spec. of control system) that I want to use as 'real life' example, it is specified in protocol settings:

================
Modbus Types Type Address Ranges Format
Coil Register Discrete Read/Write 00001 – 09999 Boolean (Bit)
Input Status Register Discrete Read 10001 – 19999 Boolean (Bit)
Input Register Analog Read 30001 – 39999 16 Bit Unsigned Integer
Holding Register Analog Read/Write 40001 – 49999 16 Bit Unsigned Integer
================

In regard to the analog output, I am picking another one here just for example sake; it is specified in Modbus list section:

================
address min / false max / true unit
30001 0 100 mbar
================

Does this mean that the control system is passing the 4-20mA data, it receives from field, to DCS using the 0 - 100 values (as mbar)?

Back to protocol settings, on the simulator side, the following options are available:
decimal +/-
hex
word 16+
dword 32+
long 32+/-
float 32
char string

So for simulation purpose, since Modbus list specified '16 Bit Unsigned Integer', I will select word 16+ (correct?) then pass it as 0-100; I will not convert it further in program since its already pressure (is this correct?).

For average, I will average the pressure over a certain number of samples. For a supposed static signal, is there any rule of thumb or usage in order to make an average (e.g. 10 reading/sec?), or there is no such a magic formula :)?

I also noticed in Modbus simulator, that user can (or should?) specify a station (these range from 0 to 255). That I can I do, its no problem. But just to understanding it correctly; this would mean that I can address two sensors in the field by using same address but selecting different stations? for example:

Sensor A (station 0) ; Address 30001
Sensor B (station 1) ; Address 30001

We could agree by convention that that 30001 is for pressure, 30002 is for temperature etc.
So station 0, 1, 2 would be machine 0, 1 ,2 respectively.

Am I on the right track?
If I understand correctly how this works, I could add the right parameters and enough of them in my program to fetch data from Modbus correctly.

Thank again!


Life is not about waiting for the storm to pass. It's about learning dance in the rain.
 
I'm not sure if I'm repeating something already commented on.
A Modbus command (register read for example) will simply return the data that the device stores there. You need to know the mapping assignments particular to the device. That data might be a temperature, flowrate, density, or the like. I am using flowmeter related parameters in my example as that is what I usually use Modbus protocol for. What data is stored in a particular register is a matter of the configuration of the device itself (e.g. it may be degrees C or F, lb/min or kg/sec, etc). The data format may be signed or unsigned integer, floating point or other. When reading a parameter that spans more than one word (such as floating point), the word order from the slave may be different than what your master is expecting so there should be a selection to allow you to set or swap the word order. The bit order may also be reversed.
So, for your example in order to read a parameter, you would query register 30001 and if floating point usually specify 2 words long. Then you sort out the word and bit order and store the value somewhere. The result will be whatever your slave is configured to store in that (those) registers.

Brad Waybright

It's all okay as long as it's okay.
 
That simulator your using has added stuff if it includes things like units and scaling. Modbus is just a way to transmit 16-bit unsigned integers. How you encode different information inside those 16-bits is up to you and outside of the Modbus standard.

Yes, you can access multiple devices using the same register on each device.
 
thebard3 & LionelHutz

Noted. Maybe one more confirmation;

If the data type is integer-16 not signed, is it correct to select 'word 16+'? I do not see any option for 'integer' in the simulator, thus my question.

Thanks!!


Life is not about waiting for the storm to pass. It's about learning dance in the rain.
 
No-one here can tell you how to use the simulator program since you didn't share any useful detailed information about it. None of the below is defined in the Modbus specification.

Back to protocol settings, on the simulator side, the following options are available:
decimal +/-
hex
word 16+
dword 32+
long 32+/-
float 32
char string

To make it simpler, The raw Modbus data for every register is a number between 0 and 65535. How you make that number represent something else is up to you.


To give a simple example, you could do any of the following to pass the value of 90 through Modbus:
- pass 90, so the number sent in the 16 bit holding register via Modbus would be 90.
- pass 90.0, so the number sent in the 16 bit holding register via Modbus would be 900.
- pass 90.00, so the number sent in the 16 bit holding register via Modbus would be 9000.

In the last 2 cases, the master device would have to be programmed to divide either by 10 or by 100 to get back to the correct value.

I would likely use the middle example to transmit something as simple as a percentage number.

 
Hello,

I tried to dig out more on the simulator.
Seems I was on the wrong track for tool documentation (was looking out here but resources are apparently still located here:
on a side note, I even found code samples on how to use scripting to fetch data from the simulator

now with this information on simulator provided (most of it is 'chinese' to me), say I want to proceed with integer-16 signed and opt for:

- pass 90.0, so the number sent in the 16 bit holding register via Modbus would be 900.

Which one option would you pick [x]:
[] long
[] hex
[] word
[] dword
[] decimal
[] float
[] char string

thank you !

Life is not about waiting for the storm to pass. It's about learning dance in the rain.
 
Dear experts,

In parallel to the original question, I have some more...

If I am (personally) attending at customer DCS room (distributed control system) and need to access their MODBUS for a certain industrial equipment. How this would be done?
I currently have a 'classic' DELL laptop E-6400 with windows 7 on it which I would bring in to DCS room.

If I am to access Modbus TCP/IP will I need to plug to my laptop an Ethernet cable from the customer system to mine (is it same one as we use for LAN connection, do I need adapter)?
If this would be a Modbus RTU, would I need to plug instead an RS 485 cable to my laptop.
I am not so sure my DELL is equipped with such a connector. Is there something like RS485 to USB adapter which I would need to use?

When the connection is made to DCS system, where exactly is it made, I mean are there racks with ports that we connect to, same as the ones we found in control cabinets?

Thanks again

Life is not about waiting for the storm to pass. It's about learning dance in the rain.
 
1. data value interpretation
>I will select word 16+ (correct?) then pass it as 0-100; . . .

Given the limited description, I would say that your interpretation is probably correct until you try it and see what really happens.

2. station (slave node ID address on the bus)
A slave's node ID address can be 1 through 247 decimal (Modbus spec).

Node ID address 0 is reserved for broadcast, which all slaves receive but to which none are allowed respond. So your proposal for
Sensor A (station 0) ; Address 30001
Sensor B (station 1) ; Address 30001

Should be:
Sensor A (station 1) ; Address 30001
Sensor B (station 2) ; Address 30001

or
So station 0, 1, 2 would be machine 0, 1 ,2 respectively.
should be:
station 1, 2, 3 would be machine 1, 2, 3 respectively.

Master/clients have no Node ID address.

3. Register addresses:
>Modbus Types Type Address Ranges Format
Coil Register Discrete Read/Write 00001 – 09999 Boolean (Bit)
Input Status Register Discrete Read 10001 – 19999 Boolean (Bit)
Input Register Analog Read 30001 – 39999 16 Bit Unsigned Integer
Holding Register Analog Read/Write 40001 – 49999 16 Bit Unsigned Integer

Neither the leading numeral 3 for Input registers (3)0001 or 4 for Holding registers (4)0001 is part of the Modbus message. The leading numerals are to help human beings identify which 'memory area' the registers are in. A legacy from the 1970's.

4. Typically a value like 90.0 saved as 900 would be a signed or unsigned integer, with a specified "divide by 10" factor.

Long is typically a long 4 byte, 2 register 32 bit integer
hex is ?
word is typically 16 bits, 1 register
dword is typically a double word, like a long integer
decimal is ?
float is also called a real, typically a 2 register 32 bit IEEE 754 floating point, occasionally 64 bit floating point, with four possible but two commonly used word/byte orders
char string is typically ASCII character packed into Modbus registers.

5. Access modbus in a DCS kingdom? The questions about DCS Modbus on this and other fora typically go unanswered. DCS documentation is generally proprietary, unpublished and unaccessible for those outside the DCS kingdom. I wish you the best! Plenty rain to go around in the DCS kingdom.

6. The dreaded one offset.
Modbus starts it addresses at 0000 (zero bases), which is sometimes documented as (4)0001. So those register addresses with memory area references (leading numerals) are typically one offset higher than the indexed zero based register.

It get dicey when one specifies the Function Code and then have to enter the register. zero based? one based without the leading numeral? One based with the leading numeral? Sometimes you gotta try them all to see what finally works.
 
danw2,
Cannot say thank you enough; your input helps a lot.

When you wrote:
5. Access Modbus in a DCS kingdom? The questions about DCS Modbus on this and other fora typically go unanswered. DCS documentation is generally proprietary, unpublished and unaccessible for those outside the DCS kingdom. I wish you the best! Plenty rain to go around in the DCS kingdom.

I supposed there are few DCS manufacturers out there (exp. Yokogawa) and also that probably one of the feature of Modbus is to give the ability to fetch data from there. I found some documentation on internet, for example:

At some point, I am also wondering if fetching data from client Historian Laptop would not be a better practical option.
But it's a different story.

Anyway, I appreciate I could have obtained here some hints on Modbus; I know ...I know ...I just scratched the surface :)

Life is not about waiting for the storm to pass. It's about learning dance in the rain.
 
rotw said:
I am not so sure my DELL is equipped with such a connector. Is there something like RS485 to USB adapter which I would need to use?
I use Microflex RS-485 converter 101-0020
It is available from a number of sources.

Brad Waybright

It's all okay as long as it's okay.
 
Status
Not open for further replies.
Back
Top