Modbus with C#: libraries, code, utilities and examples

Social Share Toolbar

In this post you will find how to use nModbus with C# and how to create a simulation enviroment to test your program with Modbus.
Other useful resources that you can find in this post are:

  • using a Modbus simulator
  • Creating virtual Com ports
  • Using sniffer tools to debug the transmission
  • A Modbus TCP Client in C# with another library

Getting NModbus

The C# library that i use the most when i need Modbus communication between pc and plcs or other components is nModbus.
nModbus manages both Modbus TCP and RTU protocols, it’s well tested and sources are available. The site for nModbus is http://code.google.com/p/nmodbus/and here you can get the latest sources.

Once you extract the sources you can open the solution file, located in the src folder.

Sample code

NModbus contains many samples included in the source code. Once you open it, you can watch at the MySample project that contains many examples on how to read and write using different devices:

The two examples that i use the most are Modbus TCP and RTU, and an example of the code to use the library is this:

Modbus TCP

/*
 *  Reading
 */
TcpClient client = new TcpClient("127.0.0.1", 502);
ModbusIpMaster master = ModbusIpMaster.CreateIp(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);

/*
 *  Writing
 */
ushort startAddress = 1;
// write three coils
master.WriteMultipleCoils(startAddress, new bool[] { true, false, true });

Modbus RTU


SerialPort port = new SerialPort("COM1");

// configure serial port
port.BaudRate = 9600;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.Open();

// create modbus master
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port);

byte slaveId = 1;
ushort startAddress = 1;
ushort numRegisters = 5;

// read five registers
ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);

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

byte slaveId = 1;
ushort startAddress = 1;

// write three coils
master.WriteMultipleCoils(slaveId, startAddress, new bool[] { true, false, true });

Depending on the registers that you are going to read and write you have different methods, that will call the different functions of the protocol, and that will return the results in 2 formats: ushort or bool (if you are reading multiple registers you will get array of ushorts and bools).

ITDONOTWORK

NModbus is supported by thousands of users, and you can find help on the NModbus google Group.

Testing your program with a simulation:

The most common Modbus simulator is located at http://www.plcsimulator.org/

This simulator provides both Modbus TCP and RTU protocols, and shows the content of the registers in the main windows so you can analyze the behaviour of your program directly in the tables of the simulator.

Creating Virtual COM Ports to test Modbus RTU:

While it’s easy to use TCP to analyze the Modbus TCP on the host (just create a socket with a 127.0.0.1 ip), testing Modbus RTU or ASCII may require some hardware, like a null-modem cable and 2 COM Ports.
To avoid this you can download a null modem emulator called Com0Com (open source, located at http://sourceforge.net/projects/com0com/) to create a pair of virtual com ports wich you can use to connect your simulator and software.

Sniffer tools available for free:

If you need to analyze the traffic between the 2 devices, to see what’s going on with your communication, there are 2 useful tools:
Wireshark is used to sniff ethernet packets and to decode the protocol. This tool can decode Modbus TCP protocol quite good and it’s useful to debug the transmission.
Free Serial Port Monitor is a serial port sniffer that can analyze the transmission between 2 COM Ports.

Other Modbus TCP libraries:

a good Modbus TCP library is available at http://www.codeproject.com/Articles/16260/Modbus-TCP-class

This library offers a client with some interesting features and it’s also useful when debugging devices.

Social Share Counters

, ,

48 Responses to Modbus with C#: libraries, code, utilities and examples

  1. Rick September 6, 2012 at 18:31 #

    Nice!

  2. Sam Pearson (@xofz) October 26, 2012 at 23:20 #

    Great article, thanks!

  3. Derek December 12, 2012 at 04:29 #

    Great article, are you familiar enough with NModbus (or the modbus protocol in general) to know if it has the ability to be event-driven. That is, to not have to user a timer or manually poll for data from a client PLC?

    I know an OPC Server is the ideal solution, but for only a couple PLCs, it’s too expensive.

    Finally, I know that the NModbus site was hacked and the documentation was lost. However, the author said the documentation could be recovered if rebuilt from the Nant task in the source code. (https://groups.google.com/d/topic/NModbus-discuss/BfQz-po8OiM/discussion) Perhaps you could re-host the documentation, or that could be another article! I know a LOT of developers are looking for it.

    Cheers and keep up the good work

  4. mesta December 12, 2012 at 20:01 #

    Hi Derek, there are no problem in hosting the documentation of nmodbus, but it just consists in 8 examples that can be found inside the source code (“MySample” folder).
    About the event-driven communication, it’s just a layer above the syncronous communication.
    To develop an asyncronous communication you need to have a thread dedicated to polling the modbus device. This thread listen to external calls from the application and executes reads and writes to the plc. When data are ready it fires a “DataReady_Event(EventArg data)” to all subscribers.
    The problem of this architecture is that it requires a lot of code that add no value to the application itself, because once you can write a multithreaded application, you can just extract your data from the communication thread, saving yourself from the pain of event-handling, subscription and memory leaks. There is an example of hmi in my last article that shows a basic structure of multithreaded app.

  5. Marco M. January 22, 2013 at 16:15 #

    Great article and blog! Thank you for sharing all this information, it’s very appreciated!

    Cheers!

  6. Marian February 5, 2013 at 18:27 #

    Hi, I’ve problem using nmodbus library with plcsimulator. When i’m trying to read data in intervals ~10sec, all slots in simulator becoming full in 10 secconds.

    I don’t know if it’s problem with code or simulator ( refreshing is not fast enought) ?

    Maybe someone had this problem ?

  7. mesta February 8, 2013 at 21:29 #

    Never had problems with plc simulator. Probably you need to check the plc simulator configuration, or to check with a sniffer what packets you are sending and receiving.
    There are some videos on youtube on how to use wireshark, if you are using modbus tcp.

  8. Cavaleiro March 22, 2013 at 12:18 #

    Hello.

    Your library is great and many thanks for share it.
    I have one question about using your library.
    When I configure the serial port with a wrong Baudrate the code block because the stream don’t receive the expetc number of bytes.
    You don’t have the Timeout funcionalitie implemented or I’m missing something?

    Best regards, and thanks again

    • Cavaleiro March 22, 2013 at 12:45 #

      Hello again.
      The solution is simple and is implemented.
      My mistake.

      To use Timeout communication, just have to configure the Serial port ReadTimeout and WriteTimeout, like this:

      port.ReadTimeout = 1000; //1 second
      port.WriteTimeout = 1000; //1 second

      Best regards

      • mesta March 22, 2013 at 13:24 #

        Thanks for sharing it.

  9. Erik March 25, 2013 at 10:13 #

    Hi,

    I’d like to rephrase Dereks question above regarding event-driven. I stumbled upon S7.net (originally hosted at: http://s7net.codeplex.com/ which is dedicated for Siemens PLC and is now continued at: https://github.com/killnine/s7netplus

    I belive this library uses modbus (but not sure). However it also lacks the event driven communication. I understand that you can create a thread that polls the PLC and generates the event when it detects that data is changed. However the optimal solution would be that the PLC (or modbus device) sends the data itself upon change. Does such mechanism exist for the modbus protocol?

    • Cavaleiro March 25, 2013 at 11:45 #

      Hello.

      If your PLC (or another modbus device ) is a master, so your PC application will be a slave. In this case the PLC(master) can share is information when ready to do it, and the PC(slave) only have to receive it.

      The NModbus supports this “kind of feature”, it can be configured as Slave or Master (ASCII, TRU and TCP/IP).

      I think you must read something about the Modbus Protocol first. The Modbus protocol is very simple to understand, so you don’t need so much time to do it.
      After that you will use the NModbus library mutch better.
      (sorry for my bad english :) )

      Best regards

      • Erik March 26, 2013 at 08:16 #

        Hi,

        Thanks for your answer. I Read about the protocol for about 5 minutes now :)

        So from what I understand you have a master and a slave configuration. The master sends out requests which the slave node(s) reply to. Typically a polling scenario. In order to get data upon events I have to set up the PLC as a master which writes to the PC as a slave. This would require some kind of extra logic (PLC program) set up in the PLC which I want to supervise. With TCP-modbus it is possible to setup the PC and PLC as both master and slave (on different connections). Not the general simple solution I was looking for so I think if I want an event driven communication it’s better to go with some OPC-solution which has already solved what I’m looking for.

        Do you know how this is solved under the hood of the OPC-server? Is the OPC server polling the device?

        • mesta March 27, 2013 at 13:37 #

          Hi Eric, probably you are confusing the two libraries, but S7.Net use S7 protocol, nModbus use Modbus protocol (that depending on the physical cable can be Modbus TCP (ethernet) or Modbus RTU (RS 422 – RS 485).
          S7.Net use Profinet (or Industrial Ethernet, don’t remember that good) and it’s derived from LibNoDave that can communicate both with Profinet and MPI.
          To use nModbus you need to add the Modbus libraries to the plc program.
          About Master and Slave, think like internet: a website is the Master and your pc that browse the site is the Slave.
          The master choose who and when a slave can talk, but it’s up to the slave to choose what he needs from the master, so you need no extra-coding on the plc part if you just need to read/write values on a DB.
          Both MPI, Profibus and Profinet are multi-master protocols, this means that when a master did what he needs, he pass the token to the other master, and so on.
          Modbus RTU is not multi-master, Modbus TCP is multi-master.
          About S7.Net, you can check a working hardware configuration sample in this thread:
          http://www.mesta-automation.com/nettoplcsim-how-to-connect-step-7-plc-sim-to-scadas/
          this has been tested.
          About the event-driven architecture:
          or you implement your own in your polling thread, or you use it as is with an OPC Server.

      • Erik March 27, 2013 at 16:07 #

        Hello again,

        I’m greatful that you are answering my newbie questions. The background for the question is that I found the S7.net library. Tried it and worked well. Since there are no real support for this library I wanted to find more information regarding how it worked under the hood (which protocol was used and so on). I found this discussion:

        https://github.com/killnine/s7netplus/issues/3

        Which to me indicated that the library used modbus TCP for communication. I kind of doubt that it is derived from LibNoDave after reading this discussion:

        http://www.plctalk.net/qanda/showthread.php?t=65768

        And by looking at the source it seems like it’s really implemented in C# all the way down to the byte communication. But it may very well use another protocol than modbus and I’m quite eager to find out which protocol. We did not set up anything (if I remeber correctly) on the PLC side to be able to access it using S7.net

        • mesta March 27, 2013 at 20:42 #

          Hi Eric, the protocol is a reverse engineering of the s7 protocol used by Step7.
          A similar code can be found inside libnodave and also inside prodave, the official Siemens library.
          I was wrong about S7.net, because the project that is derived from libnodave is Siemens plc toolbox.
          http://siemensplctoolboxlib.codeplex.com/releases
          This is more dvanced than S7.net.

  10. David April 14, 2013 at 16:56 #

    I think this may be the best article to start with modbus, really nice work.

  11. Vanderley Maia April 26, 2013 at 21:04 #

    Hi Mesta, thank you so much for your help!

    unfortunately I’m having problems with my device and not getting the values that I would like to read.
    I have always a timeout problem. :/

    This is my code:

    private void button1_Click(object sender, EventArgs e)
    {
    // create modbus master
    IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(PortaEmulada1);
    ushort[] registers = master.ReadHoldingRegisters((byte)1, 80, 2);
    }

    The device that I’m trying use is this:
    http://www.ciberdobrasil.com.br/pdf/mp_upd200.pdf

    Do you have any idea that what is happning?

    Thank you for your great work!
    Best regards!

    • Anonymous April 29, 2013 at 12:36 #

      Problem solved guys.

      Basically the problem was that my device CIBER needs that you set the Date Terminal Ready parameters as TRUE. After that, the protocol works just perfectly :D

      Thank you for your wonderfull work Mesta.
      Best regards.

    • Vanderley Maia April 29, 2013 at 12:37 #

      Problem solved guys.

      Basically the problem was that my device CIBER needs that you set the Date Terminal Ready parameters as TRUE. After that, the protocol works just perfectly

      Thank you for your wonderfull work Mesta.
      Best regards.

      • mesta April 30, 2013 at 14:53 #

        Thanks for sharing it!

  12. Deepak May 17, 2013 at 06:25 #

    Hello Mesta,

    I have very little knowledge of this field and your articles have given me great information.

    For one project, I want to control a servo motor/drive (Delta ASDA B2) though c# program. I want the motor to be controlled directly through the software code using Modbus/RS 232. The drive supports both protocols. I do not want to use a PLC. Is it possible? Please advise.

    Best Regards and thanks a lot for such a nice work.

    • mesta May 17, 2013 at 12:43 #

      Yes you can use C# and NModbus to control your drive, if the serial port is a RS232. If it is a RS422 or 485 you need extra-hardware.
      To communicate with Modbus through the serial port you need the Modbus RTU protocol, already included inside NModbus.
      You just have to know what register you need to read/write, and write the values that you need.
      Probably you need to do this independently if you use a PLC or a PC.
      However It is reccomended to use real-time OS to control motors, and Windows is not such OS.

  13. bingshanxuelian May 29, 2013 at 11:17 #

    Hi Mesta,

    Thanks so much for your information. I am new to Modbus, and have been read myself like one week about it.
    I am working one one project which needs to realise the Modbus RTU master function in C#, in order to read the data value from the slaves. I found that your library is the best, but ..my problem is that: Can you explain to me the structure of your library? In fact I do not know which parts are the library excatly. It has so 6 projects when I open it in Visual C# 2010… some other I can not even open…
    Thanks a lot. Hope you understand what I mean!

    BR
    Emma

    • mesta May 29, 2013 at 12:21 #

      Open MySample project, uncomment the sample that you want to execute and run it. It should work and get you started.

  14. bingshanxuelian May 30, 2013 at 10:05 #

    Sorry mesta,

    I still did not figure out how to add your library to my C# project. Is that I add all the projects to my solution, then I can use the library? When I done like this, it still does not work. Is that MySample is a sample folder only to show how to programming with Modbus? MySample is not a library? Sorry for my questions, I really could not make it work!

    BR
    Emma

    • mesta May 30, 2013 at 11:30 #

      If your problem is to add an external library to your C# project you should:
      1- Create new project
      2- In solution explorer right click on solution and “Add” -> “Existing project”
      3- After adding the modbus library go under your project, right click on “References”, “Add Reference”.
      4- In the left tab, under solution, you will find NModbus project, so add it.
      5- You can now use the library.

      Here the msdn link: http://msdn.microsoft.com/en-us/library/7314433t(v=vs.80).aspx

      • bingshanxuelian May 30, 2013 at 13:21 #

        Thanks so much mesta,

        It turned out that my “target frameWork” is not fit for this library. I have it .Net 4 client, and it should be .Net 4….
        Now I can use it :)

        BR
        Emma

  15. bingshanxuelian June 3, 2013 at 09:50 #

    Hi mesta,

    Sorry for bothering you again. I would like to ask that, I want to make one software application which will read and display the Modbus RTU communication register values. How can I do it? should I create a IModbusSerialMaster first, then send message to slave? I want to display all the regoister values when I connect my software and PLC. Which is the function to read from RTU slave? Thanks a lot. Please even give me a general hint is also very appreciated. As I am new to this field, but need to get the work done still.Thanks!

    BR
    Emma

    • mesta June 3, 2013 at 12:29 #

      You should take the example of RTU communication and try to connect to the plc or the Modbus RTU simulator.
      Once you can read or write a register you can make a thread that keeps reading the registers from the plc.
      Something like this: http://www.mesta-automation.com/writing-your-first-hmi-project-in-c-wpf/

      • bingshanxuelian June 4, 2013 at 11:39 #

        Hi mesta,

        thanks for answering . but they are too much for me I do not understand what do you mean. Can you explain little bit in detail? In fact what I want is: user enter slave ID, comport number, and baudrate then I have one button which will connect to the corresponding port automatically. Then the value of the registers should be displayed in datagrdiview…I get got stuck in this connect button….You gave is a very good library, but I do not know where should I start to do. Hope you understand, Also you know any Modbus RTU slave simulator?

        Thanks !

        • mesta June 7, 2013 at 12:49 #

          If you have problems with the connection of your device, you should ask help to the device’s manifacturer. Using NModbus implies that you know what is modbus and that you can debug the connection, and also you should have all the hardware needed for the communication.
          As you can imagine, i don’t know/can’t test your hardware, so this part is up to you.

  16. sachin singh June 22, 2013 at 10:44 #

    hello everybody , i have just download the NModBus library to read some Holding Registers of a device , in my c# 2010 express solution explorer added the reference to the modbus.dll from binary/net of the extracted folder , added all namespaces from modbus ie using modbus.data , using modbus.io and so on . then also added ftdAdapter.dll and wrote a small code to read holding registers using modbus RTU as explained by mesta at this page . But my project is not able to build .
    it says namespace name ‘Modbus’ could not be found (are you missing a using directive or an assembly reference? u guys are way ahead this issue , please drop me a line of advice .
    Thanks

    • mesta June 22, 2013 at 22:22 #

      You need the full .Net framework 4.0, not just the client profile.

  17. sachin singh June 23, 2013 at 10:17 #

    Hi Mesta I managed to get it right , actually I did not know before that u can add many projects under one solution , I have just had added DLLs before . when project of different .Net framework are added in one project , each individual project needs to be pointed to the frame work it was created on through the property of that project and then one project is required to be set as the start up project . This is the trick I was missing .
    Thanks for ur help !!

  18. sachin singh June 23, 2013 at 12:37 #

    Got out of obstacle but stuck at the next . well , I have a Modbus tester from namely “Modbus tester ” http://modbus.pl , this is something I have used for years . I have made some usual settings inside this software (protocol = Modbus RTU , pairity = even as per my device and so on) . starting address address = 3901 , no of registers = 2 , type of reg = holding and so on . This Modbus tester software reads my device correctly and also sets the display correctly in binary / hex / float etc . This is perfect . but when I run the same settings using same converter same device with Modbus RTU holding register read (start address = ushort 3901 and no of reg = ushort 2 , device address = 1) , my c# code throws an exception saying “Function code 131 , exception code 2 , the data address received in query is not an allowable address ” .
    For the time being this is beyond me , how come NModbus driver is interpreting the same working address as wrong ? anybody has any clue ? Please drop me a line .

    • sachin singh June 28, 2013 at 08:12 #

      hello everybody . i managed to fix my issue , any new starter having hickups in the begining like i had drop me an email i`d b glad to help . thanks to u all …sachin.jugnu@gmail.com

  19. bingshanxuelian July 1, 2013 at 12:00 #

    Hi Mesta,
    I have been in one problem for weeks, and can not get it work.
    My program works well with ReadHoldingRegister and ReadInputs, but not with the rest: ReadCoil and ReadInputsRegister. it always gives some error says: the combination of reference number and transfer length is invalid. Even I tried with only 1 register. It still gave the same error. You have any idea? Thanks so much. this is the last part of my app, I really want to figure it out…thanks

    • mesta July 1, 2013 at 12:20 #

      The only way to solve those errors is to check what packets you receive by using a Sniffer.
      Depending on the Modbus, you can sniff the packets with Wireshark if is Modbus TCP, or with SerialPortMonitor if is Modbus RTU (check the download links in the article).
      Then you can check the unit’s reply and understand what’s happening.
      The modbus protocol is quite simple and you will be able to decode it in not much time.

      • Sachin Singh July 1, 2013 at 16:12 #

        Mesta u r very correct . memory I was reading were meant to be read as a block but I was trying to read only 4 locations from top out of 20 , which was giving me a CRC error . Next , a location named 3901 in the manual = address 3900 in the c# code . I was able to fix the problem by looking at the response in the serial port monitor software . Then I hooked my Oscilloscope in Rtx of com port , that too was helpful . now NModBus C# API is ROCKING in my shop floor , thanks a lot for ur expert advice .

      • bingshanxuelian July 2, 2013 at 11:41 #

        Hi Mesta,

        thanks for replying. It turned out my PLC is configured with those addreses.
        I want to ask another thing, how can I get the port disconnected? I have 2 buttons, one for connect one for disconnect..In connect click function, I create port and let it connect, but I can not get it disconnected…can you tell me how this could be done? Thanks so much!!

        • sachin singh July 4, 2013 at 11:42 #

          port.close(); closes the port and disposes the memory resources.There is no PING command for COM port , best way to check connection is that u write some known value to some location and when ever u need to test connectivity , u read the same location and then check for the content u received .

          • bingshanxuelian July 17, 2013 at 08:11 #

            Thanks sachin singh,
            My problem still did not get solved yet.
            In my disconnect button click, I did it like this:

            port.Close();
            ConnectBu.Enabled = true;
            Dispose();

            But the result is the whole application exits. What I want is I can connect and disconnect manually, not exits. Is there anything related to the Modbus 485 cable I amusing now? Please help, so long time suffering from this problem. Thanks so much!

  20. mesta July 17, 2013 at 09:06 #

    Dispose(); is related to the port or to the application ? because it should be "port.Dispose()";
    But also i think that Dispose it’s not needed, port.Close() it’s enough.

    • bingshanxuelian July 17, 2013 at 20:43 #

      Thanks mesta,

      I do not know why I use port.close(), it does not work. I do not know what is wrong. When I press disconnect button, then later press connect again it says: can not access port and it points to port.open() with this error.

      Also I want to display the connection status in the StatusStrip …it does not work as well…
      Thanks for helping.

      BR

      • mesta July 18, 2013 at 10:26 #

        You probably need to learn how to use the SerialPort class.
        Check some examples like this:
        http://www.codeproject.com/Articles/75770/Basic-serial-port-listening-application

        • bingshanxuelian July 23, 2013 at 11:31 #

          Hi, mesta.

          Thanks so much for replying, that is similar with what I want.
          my problem is that I can not connect to the slave all the time, only few seconds it will disconnect automatically. I have been trying for few monthes. It does not work still, so tired with this.
          I think my program is right, but it does not work. is it possible you can check my code little bit? I really need some help with this. Thanks a lot!

  21. Pablo January 24, 2014 at 14:43 #

    How i can read and write only one bit of a register with this library?

    I have the register Modbus RTU and the description of bits….

    Use a conversor Rs-232 (added USB) to Rs-485

Leave a Reply