Modbus-RTU added to the Cet Open Toolbox

I should say that the spring is in the air, but honestly the weather here was never so strange.
As the sun gets the weekend warmer, I’d love to ride with my bicycle to the big park near my home. However, since this Easter has been pretty cloudy, I took advantage to add a missing piece to the Modbus library presented last time.

Modbus-RTU support.

First of all, I’d like to say that the library has been tested on the Fez board. Many thanks to the user offering his code, and his time for this project.
After this good news, I’d like to introduce the new kind of support for the library: the Modbus-RTU. In my past article I promised to make an attempt to interface the RS-485 to the Netduino, but I was unsure about it. That’s essentially because the RS-485 interface requires a particular driver, which is not easy to realize with the managed code.
What is the difference from the shown Modbus-TCP/UDP?
The very first edition of the Modbus protocol was targeted for the serial port (i.e. UART or USART), just because the Ethernet or any other “complex” transport was available about thirty years ago. So, the communication was based on a simple cable pair, and relying on a very easy-to-implement protocol.
By the way, since the Modbus is typically used in industrial automation, a requirement was the good noise immunity, as well as the relative ability to create long distances. That’s not achievable by simply wiring the microcontroller’s logic, nor using the well-known RS-232 protocol.

The EIA-485 (a.k.a. RS-485) protocol fits perfectly this needing:

  • a simple cable pair is enough, although for long distances a shielded twisted pair is required;
  • distance up to 1200 meters (0.75 miles);
  • differential line, on 120 Ohms of impedance;
  • offers several dozen of devices connected on the same cable;
  • many more features yielding a very good solution for long distance cable communication.

The transmit mode.

The RS-485 protocol allows a master-slave architecture, using the network as a half-duplex. So, only one device can issue its data over the whole network, and this task can be achieved by enabling the “transmission mode”.
The “transmission mode” is very similar to the “Slave-select” of the SPI, but it’s not the same thing. Basically the device has to enable its physical RS-485 driver just before issuing the outgoing data. Since this “enabling” covers any other device, the “transmission mode” must be cleared immediately after the outgoing data has been issued.

The differential signal on the RS-485 line (source Wikipedia)

For instance, consider a basic master-slave handshake for a simple command:

  • the master enables its “transmission mode” (TXDE hereinafter), so that it takes the complete control of the cabled network;
  • sooner, the outgoing stream begins, and continues up to the end;
  • the master, switches its TXDE off, so that any other device (the addressed one) can be place its answer;
  • the addressed slave device, once recognized the request, places its TXDE on;
  • the answer’s outgoing stream begins, up to the completion;
  • the slave device disables its TXDE off, thus another query can be initiated.

So, the problem is how to control this TXDE signal, considering the short timing involved in the handshake. To give an idea about the timing, consider that the TXDE should be disabled within one-two byte period immediately after the end of the outgoing stream. If you think to a 9600 bps, one byte takes about 1 ms to run, and that’s really hard to control with the Netduino.
You know, I’m hating C/C++, and I’d never want to hack the firmware of the board. Most of the times, an hardware solution could be simpler than hacking a complex framework. That is the occasion, once again.

The TXDE circuit.

Here is not included the small module used for the RS-485 physical driver. I’ve used one of our production, which offers an embedded opto-isolation, and it seems perfectly tailored for the Netduino. It requires two kinds of supplies, +3.3V and +5V, and it supports up to 32 devices on the same line.

This module requires a low-level on the TXDE pin, for placing the driver in the “transmission mode”. The extra circuit should only “generate” this signal from the only useful signal available outgoing the Netduino, which is the TXD (serial data out).
The trick is somewhat trivial. The circuit acts a monostable flip-flop, which is re-triggered on any low-level of the TXD. Since any UART protocol must include a “start bit”, which is signed as low, this is enough to re-trigger the flip-flop on every byte issued by the UART. Of course, there are many more “low-bits” in a byte, but it should be considered the worst case, when all of the bit are high.
The problem is much easier than expected. I’ve tested the circuit over two different baud-rates, 9600 and 38400 bps, and it’s not critical at all. However, it’s not a “professional” way to solve such a problem, but just an hack. For a small home-automation, whereas the distances are shorter than 100 meters, and there’s no so many noises, of sure is acceptable.

How is it working?
You should bear in mind how a capacitor behaves, because that’s the key of the circuit.
A capacitor could be dualized as a tank, and the current as the water. Finally, the voltage across the capacitor could be thought as the water level.
When the tank is filled, it keeps the water level until some pipe extract the fluid from within. Now, suppose that this “pipe” is a resistor in parallel to the cap. At this point the water level decrease, as fast as big is the pipe. Thus, the higher is the current through the resistor, the faster will decrease the voltage across the capacitor.
Let’s take a look at the circuit.
When a low-level signal is issued on the TXD, an inverter (74HC14) reverse this level bringing high its output. In this case, the diode is forward-polarized and a lot of current will flow into the capacitor, charging it in a very short time. The “short time” is due to the diode, which is almost a short.
As soon the TXD will go high back, the inverter outputs a low-level, and the diode acts as it were an open circuit. In this case the capacitor is losing its change through the resistor. This evolution take a certain time, so that this “delay” is used to generate the TXDE signal.

The software.

The library was almost inline with the Modbus-RTU protocol. That’s the heavy decoupling benefit!
The “bigger” modification was about the name of the classes involving the Modbus codec. In the initial release of the library, I did not care about the RTU possibility. This time the RTU support has been taken place, and most of the classes could be shared. That’s a great satisfaction!
Another interesting addition is the CRC-16 calculation. I’ve found a C routine, which looked very simple, yet performing fast.
Here is a preview of the algorithm:

        /// <summary>
        /// Define the look-up table for calculating the CRC16 algorithm
        /// </summary>
        private static readonly ushort[] CrcTable = new ushort[256]
        {
            0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
            // ...
            0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040 
        };


        /// <summary>
        /// Calculate the CRC16 over a byte-array segment
        /// </summary>
        /// <param name="buffer">The source byte-array</param>
        /// <param name="offset">The index of the first byte to be considered</param>
        /// <param name="count">The number of the bytes to be considered</param>
        /// <returns>The resulting CRC16 value</returns>
        /// <remarks>
        /// Ported from plain-C source found here: http://www.modbustools.com/modbus_crc16.htm
        /// </remarks>
        public static ushort CalcCRC16(
            byte[] buffer,
            int offset,
            int count)
        {
            ushort result = 0xFFFF;

            while (count-- > 0)
            {
                var temp = (byte)(buffer[offset++] ^ result);
                result >>= 8;
                result ^= CrcTable[temp];
            }

            return result;
        }

Conclusions.

With the support of the Modbus-RTU, this library could be considered complete. It’s not a full-featured library as it could be a desktop version, but of sure can solve several small projects we all dealing with.

The software is hosted in the Codeplex repository here.

27 thoughts on “Modbus-RTU added to the Cet Open Toolbox

  1. Alex

    Great post and great sample code! I am new to RS-485 and I have a quick question for you. The sample code that you have posted does it only act as the slave device or master? I noticed you didn’t put code in for ModBusRtuCodec.ServerEncode. Also, do you have any plans to make the code full duplex? Again, I am new to RS-485 so I am sorry if my questions are stupid. I am developing a system that has about 20 AVR microcontrollers(slaves), 2 Netduino (1 master, 1 slave) running over 4 wires in a series. I need the master to be able to send and receive data from each device. Any help would be greatly appreciated.

    Thank you very much,

    ~Alex

    • Mario Vernari

      Hello Alex. The library could be improved, and -yes- the RTU slave/server is planned to be added. We’re working (hard) on a pretty flexible system, which can use even a 2-wire connection (communication and power on a simple twisted pair).
      BTW, I don’t have plan about the 4-wires. Why do you need a full-duplex? In my experience the half-duplex is much simpler, and enough for most applications.

      • Alex

        I wanted to do full duplex to ensure that the master can always send commands to the slaves even in the scenario when a slave device goes crazy and broadcasts messages none stop. The slave devices respond with less than 2 bytes of data at any time, so I am now considering half duplex after researching half vs. full duplex today. I would love to be able to connect three Netduinos on RS-485 half duplex 1 master and 2 slaves. I wish I knew more about RS-485 and Modbus, so I could be of some help. I am a server/client/web developer/architect trying to get into firmware and hardware development. If you don’t mind can you please let me know when you might have the master and slave version complete? Thank you for your time and again sorry for being a newbie and bugging you about this.

        ~Alex

  2. Mario Vernari

    When a slave (i.e. a device) gets crazy, you also can’t be sure it understands any incoming command. Simply design and code a well product, and you won’t have troubles.
    However, bear in mind that a Netduino-like board is *not* reliable for mission critical systems: can hang and can fail. If you take a look at the picture above, you’ll mean that a highly-reliable device is somewhat complex (and also expensive). Our I/O device is targeted for mission-critical systems, for operations H24, 365/365, without any failure.
    Anyway, let me some time, and I’ll provide the remaining code for the RTU server/slave flavor. The master code is meant to be complete.

    • Alex

      I am just checking in to see if you have had any luck completing the RS-485 master/slave Modbus protocol?

      Thanks,

      Alex

      • Mario Vernari

        My apologies, but my home-lab PC is gone on last Saturday, so all my Netduino works are trapped into that HDD. This week-end I should be able to set up a brand new PC, so the “job” can go up…
        Anyway, the Netduino as “master-RTU” is already available. Are you seeking for the “slave-RTU”?

      • Alex

        I am looking for the Netduino to act as a master and a slave. The final project is going to have 2 Netduino devices connected over two 3-wire rs-485 cables and in between the Netduinos are 20 AVR microcontroller devices each with two TI SN65176B chips. Each Netduino acts as a master on one RS-485 and a slave on another. The Netduino like the AVR controllers will have their own two TI SN65176B, one for each RS-485 connection. All the Netduino needs to do is listen on one RS-485 for commands then respond when it is addressed and send commands on the other RS-485 cable. I am hoping that the final product will run off a custom built NETMF board, but I am not sure if that will happen or not.

        Thank you for all your help and time. I am sorry it takes me so long to respond back to you, I work all day and get only a few hours a night to work on this project.

        ~Alex

      • Mario Vernari

        I always think it’s uselessly complex. First off, you should use two UARTs for acting a device (Netduino or AVR) both master and slave. But also double hardware, double wiring, etc. So, what’s the benefit?
        Bear in mind that we’re selling RS485 modules opto-coupled, as in the picture above.

      • Alex

        We are actually going to be using 2 uarts on each Netduino and 2 uarts on every ATTiny AVR board that we use. We require the redundancy as there is a high likelihood that the connection between the 2 netduinos would be severed or the primary board will lose power, thus requiring the second Netduino to actively communicate on a separate line to the devices. It is a little crazy, but standards for the industry I am building this for is very old school and they love full redundancy. I hope you had a good weekend and were able to rebuild your computer without any issues. I look forward to the client & server version of RS-485 Modbus.

        ~Alex

      • Alex

        Just checking in to see how the progress on making the slave portion of the code is coming along. I hope all is well.

        ~Alex

    • Mario Vernari

      Hello David. Actually, I never tried the library on any GHI’s stuffs, but an user done that and it seems working: .
      BTW, the RTU-way uses just the UART, so I don’t see any reason for not working on the GHI as well.
      Cheers

  3. Per Cramer

    Hi Mario,

    great project. I have got several GHI devices overhere so i will test it. But it is not quite clear to me from your post if it does RTU slave also. Or just RTU master?

    Regards,

    Per

    • Mario Vernari

      As usual I must get ashamed for the delay. The library on the public repository allows only a master RTU, but the slave version is already written, and it needs only a brief testing.
      I really hope to post it as soon as possible.
      Thanks a lot and cheers

      • Doug Vaughn

        I would love to test the RTU Slave on some GHI boards if you’re interested.
        Great work so far!

  4. Jaime

    Do you have an estimator about how much program lines Netduino Go supports?
    It think it is a very relative question, perhaps could be answered in terms of complex operations like a Protocol build, Statistical calculationes, Waveform syntesis, and so on.

    • Mario Vernari

      Jaime, I really don’t know how many lines the Go! could contain. Anyway, talking about “lines” has a very limited sense, because a single line could take few bytes, as a large amount.
      The Modbus libraries has been tested on my Netduino Plus, having the “old” firmware 4.1.0.6, which is the largest. The new releases for the Plus, as well as the Go! have much more available space, both in term of Flash and of RAM.
      Sincerely, I don’t remember a single case where I got over of the available Flash. Most of the issues are related to the RAM, which is very few.
      Hope it helps.
      Cheers

    • Mario Vernari

      The main application must run from the Flash. When you upload the program from within the VS IDE, the created assembly will be deployed on Flash.
      As any normal .Net product, you may compile as many DLL you want, in order to extend the main application. Those DLL can be written on the SD, then loaded dynamically by the same application.
      However, there are at least two problems. First off, any additional assembly will be loaded on RAM, that’s because the loader can’t program its Flash, thus uses the available RAM. Secondly, the attached assembly will be “glued” to the main app, and you can’t detach it anymore (unless you reset the board).
      I guess there’s no way to extend the available program space over the actual rooms.
      Now a question to you: what’s your deal?

  5. Jaime

    A telemetry system is my actual project. Processor must 1) acquire data from an Electrical Power Meter via modbus 2) calculate some statistical 3) transmit data by DP3 protocol throught a cel modem. Up to 800 variables ought to be transmited. As you can see, this essue needs a lot of codes.

    • Mario Vernari

      IMHO, a Netduino (or any similar .Net MF product) is too small for such a project.
      I’d rather use a Windows Embedded board, or -if you like- any Android-enabled board, which can be programmed in Java. We also have on sale a Linux embedded board, but -for performance reasons- runs Lua or C++: no managed languages.
      We’ve created several systems like your’s, and there are many other reasons for switching to a bigger platform, such as reliability, certifications, etc.
      If you need some info about our products maybe matching your needs, feel free to send a mail to: rd (at) cet-electronics (dot) com
      Cheers

  6. KarpeDiemNow

    Great project!!

    I have tried to use ModBus MASTER_RTU in your example, Cet.IO.DemoModbus_MF42 and received always an exception in SerialPortClient.cs -> Query, because you try to set parameters port when the Serial port is open.

    I have fixed in SerialPortClient:

    public CommResponse Query(ClientCommData data)
    {
    lock (this.Port)
    {
    if (!this.Port.IsOpen)
    {
    try
    {
    //set the proper parameters to the port
    this.Port.BaudRate = this.Setting.BaudRate;
    this.Port.Parity = this.Setting.Parity;
    this.Port.DataBits = this.Setting.DataBits;
    this.Port.StopBits = this.Setting.StopBits;
    this.Port.RtsEnable = this.Setting.RtsEnable;
    }
    catch (Exception ex)
    {
    return new CommResponse(
    data,
    CommResponse.Critical,
    ex.Message);
    }
    this.Port.Open();
    }



    }

    and work like a sharm….🙂

    Regards

    • Mario Vernari

      You are absolutely right! I probably took the settings alive for the desktop release, which is the primary target. If you check the “V1” branch, the settings were commented out for the reason you found.
      In my mind it would be better keeping the port open and change its settings when needed. However, I believe it’s a big fault that in the MF the settings can’t be changed.
      Thanks again.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s