Reading registers from slaves

1,881 views
Skip to first unread message

Big Brian

unread,
Apr 12, 2011, 11:24:59 AM4/12/11
to NModbus
I am trying to read a register from a Socomec DIRIS A40 electricity
meter, which is a slave on an RS 485 network, which is "hanging off"
the same type of meter with a Gateway module, which is on an ethernet
network.

The Simple Modbus TCP Slave Example allows me to specify slave ID but
not start address or number of registers. The Modbus TCP master and
slave example allows me to specify a start address and number of
registers but not slave ID.

Am I missing something?

I suspect I am getting in a muddle with masters and slaves. Can
anybody point me in the right direction?

Code samples from old website listed below.

Thanks,

Brian.


The Simple Modbus TCP Slave Example

byte slaveID = 1;
int port = 502;
IPAddress address = new IPAddress(new byte[] { 127, 0, 0, 1 });

// create and start the TCP slave
TcpListener slaveTcpListener = new TcpListener(address, port);
slaveTcpListener.Start();

ModbusSlave slave = ModbusTcpSlave.CreateTcp(slaveID,
slaveTcpListener);
slave.DataStore = DataStoreFactory.CreateDefaultDataStore();

slave.Listen();



The Modbus TCP master and slave example

byte slaveID = 1;
int port = 502;
IPAddress address = new IPAddress(new byte[] { 127, 0, 0, 1 });

// create and start the TCP slave
TcpListener slaveTcpListener = new TcpListener(address, port);
slaveTcpListener.Start();
ModbusSlave slave = ModbusTcpSlave.CreateTcp(slaveID,
slaveTcpListener);
Thread slaveThread = new Thread(slave.Listen);
slaveThread.Start();

// create the master
TcpClient masterTcpClient = new TcpClient(address.ToString(), port);
ModbusIpMaster master = ModbusIpMaster.CreateTcp(masterTcpClient);

ushort numInputs = 5;
ushort startAddress = 100;

// read five register values
ushort[] inputs = master.ReadInputRegisters(startAddress, numInputs);

for (int i = 0; i < numInputs; i++)
Console.WriteLine("Register {0}={1}", startAddress + i, inputs[i]);

// clean up
masterTcpClient.Close();
slaveTcpListener.Stop();

// output
// Register 100=0
// Register 101=0
// Register 102=0
// Register 103=0
// Register 104=0


// prevent the main thread from exiting
Thread.Sleep(Timeout.Infinite);

Timothy Marin

unread,
Apr 12, 2011, 12:56:24 PM4/12/11
to nmodbus...@googlegroups.com
Brian,

Unless you are writing this (Gateway Module) and it does not sound
like you are, you simply need to create one Master and when you
request data put the slaveID all the Read Methods have an overide to
support 'slaveID' this is assuming you have a stup as follows.

[Your Master]---ethernet---[Device ID 1]----485---[Device ID 2]

Example

using (TcpClient client = new TcpClient("127.0.0.1", 502))
{
ModbusIpMaster master = ModbusIpMaster.CreateIp(client);

// read five input values NOTICE the 1(slaveID)
byte slave = 1;
ushort startAddress = 100;
ushort numInputs = 5;
bool[] inputsDEVICE01 = master.ReadInputs(slave,
startAddress, numInputs);
slave = 2;
bool[] inputsDEVICE02 = master.ReadInputs(slave,
startAddress, numInputs);
}

Hope this helps, just another quick note about addressing although I
assume you know this I always like to explain this when I give
examples on NModbus.

10000 or 100000 is implied by the [ReadInputs function] See Below:

In this example you are reading what would be documented as 10100 -
10105 or 10101 - 10106 Depending on how your device handles 0 offset.
Or possibly 100100 - 100101 for 6 digit although for NModbus the
request is the same.


Quick Info on Modbus Addressing-
[AKA 5 Digit Addressing]
0x Coil 00001-09999 Digital Output
1x Discrete Input 10001-19999 Digital Input [used in this example]
3x Input Register 30001-39999 Analog Input
4x Holding Register 40001-49999 Analog output

Translating references to addresses, reference 40001 selects the
holding register at address 0000. The reference 40001 will appear in
documentation and is used to define the Modbus register in the
location property of the functional block. The address 0000 will be
transmitted in the message packet. Addresses are often not directly
used by the application or the user.

On occasion, it is necessary to access more than 10,000 of a register
type. Based on the original convention, there is another defacto
standard that looks very similar. Additional register types and
reference ranges recognized by Babel Buster are as follows:

[AKA 6 Digit Addressing]
0x Coil 000001-065535
1x Discrete Input 100001-165535
3x Input Register 300001-365535
4x Holding Register 400001-465535

5 or 6 digit does not really matter just use the first number to
determine what method to call.


Tim-

> --
> You received this message because you are subscribed to the Google Groups "NModbus" group.
> To post to this group, send email to nmodbus...@googlegroups.com.
> To unsubscribe from this group, send email to nmodbus-discu...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nmodbus-discuss?hl=en.
>
>

David Harris

unread,
Apr 12, 2011, 12:43:30 PM4/12/11
to nmodbus...@googlegroups.com
If you are trying to read registers from a slave, you need to use the TCP Master sample. Here it is, copied below.

using (TcpClient client = new TcpClient("127.0.0.1", 502))
{
	ModbusIpMaster master = ModbusIpMaster.CreateTcp(client);

	// read five input values
	ushort startAddress = 100;
	ushort numInputs = 5;
	bool[] inputs = master.ReadInputs(startAddress, numInputs);

	for (int i = 0; i < numInputs; i++)
		Console.WriteLine("Input {0}={1}", startAddress + i, inputs[i] ? 1 : 0);
}

// output: 
// Input 100=0
// Input 101=0
// Input 102=0
// Input 103=0
// Input 104=0

On Tue, Apr 12, 2011 at 11:24 AM, Big Brian <brianh...@googlemail.com> wrote:

Timothy Marin

unread,
Apr 12, 2011, 1:00:21 PM4/12/11
to nmodbus...@googlegroups.com
Brian,

Also just a quick note I hope it is clear to you that "127.0.0.1"
should be replace by your ethernet devices IP address.

Tim-

On Tue, Apr 12, 2011 at 11:24 AM, Big Brian
<brianh...@googlemail.com> wrote:

Big Brian

unread,
Apr 12, 2011, 2:33:17 PM4/12/11
to NModbus
Hi Tim,

Thanks for this. I think this master.ReadInputs(slave,
startAddress, numInputs); override is the missing link that I was
looking for.

Thank you.

Brian.

Big Brian

unread,
Apr 12, 2011, 2:34:05 PM4/12/11
to NModbus
Hi David,

Thanks also for this. This also adds some clarity.

Thanks,

Brian.

On Apr 12, 5:43 pm, David Harris <da...@gtdavid.com> wrote:
> If you are trying to read registers from a slave, you need to use the TCP
> Master sample. Here it is, copied below.
>
> using (TcpClient client = new TcpClient("127.0.0.1", 502))
> {
>         ModbusIpMaster master = ModbusIpMaster.CreateTcp(client);
>
>         // read five input values
>         ushort startAddress = 100;
>         ushort numInputs = 5;
>         bool[] inputs = master.ReadInputs(startAddress, numInputs);
>
>         for (int i = 0; i < numInputs; i++)
>                 Console.WriteLine("Input {0}={1}", startAddress + i, inputs[i] ? 1 : 0);
>
> }
>
> // output:
> // Input 100=0
> // Input 101=0
> // Input 102=0
> // Input 103=0
> // Input 104=0
>

Big Brian

unread,
Apr 12, 2011, 6:47:39 PM4/12/11
to NModbus
Hi Tim,

If the register that I am interested in is 51288, should I use -

master.ReadHoldingRegisters(slave,startAddress, numInputs); instead?

with

byte slave = 1;
ushort startAddress = 51288;?
ushort numInputs = 1;


Thanks,

Brian.

On Apr 12, 5:56 pm, Timothy Marin <timothyma...@gmail.com> wrote:

Big Brian

unread,
Apr 12, 2011, 6:36:38 PM4/12/11
to NModbus
Thanks Tim,

Like the T Shirt - "There's no place like 127.0.0.1"

Thank you.

B.

Timothy Marin

unread,
Apr 12, 2011, 7:41:50 PM4/12/11
to nmodbus...@googlegroups.com
Brian,

Yes, I would say it is very likely a holding register I pulled up some
documentation and that appears to be 'Phase Current 1'

There is a couple things to keep in mind, since this is using extended
6 digit addressing IE most SCADA systems would expect 451288 it is
also possible this is greater than 16bit [does not appear to be since
there is a 512 89 Available] but you may need to read 2 registers and
use bitconverter to get yourself a Int32 and also you may need to
scale this number[Although many devices put prescaled numbers into
extended registers and raw numbers in the standard modbus address
range], you will need to check the documentation for all of these.

- just saw the warning for that set of addresses CAUTION : using this
table involves multiplying values by transformation ratios.

You might want 50532 instead and read 2 registers.

Somthing Like

ushort[] ret = new ushort[]{1,0};
byte[] B1 = BitConverter.GetBytes(ret[0]);
byte[] B2 = BitConverter.GetBytes(ret[1]);
byte[] B3 = new byte[4];
Array.Copy(B1, 0, B3, 0, 2);
Array.Copy(B2, 0, B3, 2, 2);
int Final = BitConverter.ToInt32(B3,0);

but watch out for swaped registers[or if i have the ushorts backwords
in my sample heh]

Regards,

Tim-

Big Brian

unread,
Apr 13, 2011, 3:07:01 AM4/13/11
to NModbus
Thanks Tim.

For your information (and anybody else who might come across this
thread) Socomec have informed me that the register addresses stated in
the manual are J Bus addresses so will be out by one! Which way I am
not sure yet but the advice I was given was to start by finding
Frequency, which should be readily identifiable and work it out from
there. This is also a little bit academic as the register addresses
stated in the PDF manual that is currently available on the internet
(DIRIS A40/A41 - Ref.:536 181 A GB) are wrong. Socomec have emailed
me a spreadsheet with the right addresses. Personally I would have
thought that it would be easier just to correct the manual and repost
it.

Thanks again for your help.

Regards,

Brian.



On Apr 13, 12:41 am, Timothy Marin <timothyma...@gmail.com> wrote:
> Brian,
>

Mark Hinds

unread,
May 24, 2011, 11:55:58 AM5/24/11
to NModbus
Hi there, I really hope you can help.

Im in the same position as the OP, trying to read values from the same
meter. With the help of the samples and documentation I have
successfully connected with the meter and read values from it from
random addresses. However I am unable to target the specific addresses
I need as I am still a bit confused about how to do it. I am looking
for active power, starting at 50544 - similar to the address discussed
above. I have implemented the above (I think) to read from two
registers, but I am still unsure how to target the one I want. You say
6 digit addressing would expect something like 450544? Is this what I
enter for the starting address? This value is too big for the ushort
variable, do I need to change this, or should I not be using the
number 450544 as-is? If reference 40100 selects the register at 100,
then how do translate a value beginning with 5? i.e. 50544

I would be extremely grateful for any help!

Much Appreciated,
Mark

Mark Hinds

unread,
Jun 1, 2011, 5:17:01 AM6/1/11
to NModbus
As it turns out, despite being told otherwise, the connected meter was
a pre-2009 model, using the old addressing system.
> ...
>
> read more »

Hongjun Niu

unread,
Aug 29, 2014, 12:37:12 AM8/29/14
to nmodbus...@googlegroups.com, brianh...@googlemail.com
Dear Brain, i am facing the same problem for reading data from A40, can u forward me the correct address which got from Socomec? thank u very much! nhj99...@gmail.com.
Reply all
Reply to author
Forward
0 new messages