Project - Master/Slave Modbus (RTU/TCP) Library for NETMF and Windows

I just posted Master/Slave Modbus (RTU/TCP) Library for NETMF and Windows on Codeshare. Feel free to discuss and make suggestions here.

6 Likes

Very cool project
Do you have plans to support MODBUS ASCII mode?

I was looking to make a MODBUS Slave Device using a Cobra II
This will save allot of time

Very cool, indeed.

Could you also share any code usage example? Maybe for different master/slave and TCP/RTU modes too? :-[

Also, are you using any kind of Modbus emulator for library testing you can suggest? At this time I’m aware only of non-free tools.

Thanks!

Currently I have not planned to support ASCII mode.
Message encoding is done in the core library, wich works fine for TCP and RTU because it’s identical.
Only the framing with checksum, address, … is done in the interface implementation.
I have never ever seen an ASCII device, and the ASCII protocol is out dated.

The usage samples shows all 4 variants Master/Slave/RTU/TCP as a brief sample.
I’m working on a windows app that con be all 4 variants for quick testing.
If I remember right, there was some tool on sourceforge for simulating devices.
So far I have only tested against real slaves and my own implementations on windows, NETMF and Arduino (for Medusa, also on code share).
Not all functions are tested, and also not all are implemented.
I have also planned to integrate a Modbus TCP Master to RTU Slave Gateway.
So you can connect a RTU bus to a TCP slave and access the RTU slaves via the TCP master by specifying the the RTU address when communicating to the TCP. The TCP slave is then also a RTU master.
As always, progress is slow an my hobbyish projects.

Reinhard, would you be able to provide any more information on how to use your library?
Namely, the RTU mode to enable communication for a Cobra || board.

If possible, do you have any other examples on how to use your library? :-[

Currently it’s only what you see in the usage example.
I know a fully working sample project is needed, but I’m quite busy at the moment.
But I will use this library in my current project, and therefor there might drop off a usage sample in near future.

Thanks for your response Reinhard.

I included my one line modification below.

I did get it working with the Cobra ||, RTU, using your library. However, sometimes when I receive data over serial from the cobra, it would throw a CRC exception.

I temporarily solved this by including a 10 ms delay in the ModbusRTUInterface class, ReceiveTelegram method.

This is probably not the best approach, but for now, I can run your usage example without throwing.

 buffer, short desiredDataLength, int timeout, out short telegramLength)
        {
            short desiredLength;
            if (desiredDataLength >= 0)
            {
                desiredLength = (short)(desiredDataLength + 4);
            }
            else
            {
                desiredLength = -1;
            }

            int n = 0;
            var tOut = DateTime.Now.AddMilliseconds(timeout);
            long nextRead = 0;
            bool errorChecked = false;
            while (true)
            {
                if ((desiredLength > 0 || n == 0) && DateTime.Now > tOut)
                {
                    // timeout
                    break;
                }

                Thread.Sleep(10); //////////////////////THIS DELAY//////////////////////////////////////////////

                if (_Serial.BytesToRead > 0)
                {
                    if (desiredLength > 0)
                    {
                        n += _Serial.Read(buffer, n, desiredLength - n);
                    }
                    else
                    {
                        n += _Serial.Read(buffer, n, buffer.Length - n);
                    }
                    // a delay of more than 1.5 chars means end of telegram /////, but since this is a extreme short time, we extend it by factor 2
                    nextRead = DateTime.Now.Ticks + 6 * _HalfCharLength;
                }
                if (!errorChecked && n >= 2)
                {
                    errorChecked = true;
                    if ((buffer[1] & 0x80) != 0)
                    {
                        // modbus error, so desired length is 5
                        desiredLength = 5;
                    }
                }
                if (desiredLength > 0 && n == desiredLength)
                {
                    telegramLength = (short)n;
                    return true;
                }
                if (desiredLength <= 0 && n > 0 && DateTime.Now.Ticks > nextRead)
                {
                    telegramLength = (short)n;
                    return true;
                }
            }
            telegramLength = 0;
            return false;
        }
  

Hi Reinhard Ostermeier !!!

I really liked your library! Once I have a problem reading data from the function 3. He throws me an error illegal funсtion. Help solve the problem.


using System;
using System.IO;
using System.IO.Ports;
using Microsoft.SPOT;
using Osre;
using Osre.Modbus;
using Osre.Modbus.Interface;
namespace MFConsoleApplication1
{
    public class Program 
    {
        public static void Main()
        {
            Debug.Print(
                Resources.GetString(Resources.StringResources.String1));
            SerialPort ser = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
            ModbusRtuInterface mdb = new ModbusRtuInterface(ser);
            
            DeviceSlave dv = new DeviceSlave(mdb, 1);
           
            ser.Open();
            dv.AddInterface(mdb);
            dv.Start();

            while (true)
            {
                System.Threading.Thread.Sleep(200);
            }
        }
    }
}


using System;
using Microsoft.SPOT;
using Osre;
using Osre.Modbus;
using Osre.Modbus.Interface;

namespace MFConsoleApplication1
{
    class DeviceSlave:ModbusDevice
    {
        public DeviceSlave(IModbusInterface intf, byte deviceAddress, object syncObject = null)
            :base(intf,  deviceAddress,syncObject ){

        }



        protected override ModbusErrorCode OnReadHoldingRegisters(bool isBroadcast, ushort startAddress, ushort[] registers)
        {
            registers[0] = 3;
            return base.OnReadHoldingRegisters(isBroadcast, startAddress, registers);
        }

        protected override ModbusErrorCode OnWriteSingleRegister(bool isBroadcast, ushort address, ushort value)
        {

            return base.OnWriteSingleRegister(isBroadcast, address, value);
        }
        
        protected override ModbusConformityLevel GetConformityLevel()
        {
            return ModbusConformityLevel.Extended;
        }

        protected override string OnGetDeviceIdentification(ModbusObjectId objectId)
        {
            switch (objectId)
            { 
                case ModbusObjectId.ProductName:
                    return "dgfgdf";
                  
                case ModbusObjectId.VendorName:
                    return "gfgfjk";

                case ModbusObjectId.ProductCode:
                    return "fgfgdf";
                default:
                    return "";
                    break;
            }

            
            
            }
        }

    }






Illegal function usually means the device does not support that function.

Are you sure that it is a valid function code your device can accept?

@ Anton_Capiton -
I see the problem, you call the base class implementation of OnReadHoldingRegisters in your implementation.
But the base class only returns “Invalid function” so your device does not support this function if you don’t override the function.
You should just return ModbusErrorCode .NoError instead of calling the base function.

What do you guys recommend if someone wants to learn modbus? And what devices I can but to try it out?

@ andre.m - not sure I understand.

Using my library you don’t need to know much about Modbus.
To get an overview look at the documents I have linked in the project page.

For the devices: I know only industrial devices that use Modbus, but there are others as well I think.

But using my library you can make any NETMF device also an Modbus device (slave) or an Modbus Master.

As interface you can use TCP or RTU, where anything that uses a SerialPort can be used:
RS232, null Modem, RS485, …

@ Gus - If you are looking for commercial devices you can get a low cost micro-plc or I/O base from http://www.automationdirect.com/ Their low cost PLCs (http://tinyurl.com/3bv66q7) have Modbus RTU standard. Their DL05 - DL405 series and T1H terminal I/O have Modbus TCP options. They have Ethernet remote masters that will put a whole rack of I/O on Ethernet.

On the computer side I use Modbus Poll from http://modbustools.com/ to test Modbus clients. They also have Modbus Slave software so you can test a master device. Both support serial and Ethernet.

Most industrial stuff is quite expensive but you might find something on the likes of eBay to play around with. VSD’s are a good choice as there are loads of them on there.

I needed to develop software to talk to a VSD (Variable Speed Drive) and the unit was designed to run a 43kW 3 phase motor so hooking one up in my home was out of the question and I didn’t really fancy heading out to the clients workshop every day as it was.

I bought a small version of the big unit which happens to use the same Modbus protocol. An Atlivar ATV312 and a small 1HP 3 phase electric motor to connect it up to. The power input is single phase 220V and the drive,being an inverter, creates the 3 phase to drive the motor.

It’s neat as you can configure the drive to listen on Modbus and you can control the motor speed. The full live system controls a downhole pump where we control the speed to maintain the fluid height.

Oh, there is another option to test with and that is this software. I have both the master and slave versions and it is an invaluable tool for testing and checking your code works before you roll out to a real device.

PS… Modbus is dead easy once you have code to drive it and you figure out the addressing used. The protocol just works.

You might try checking out Homann Designs
They produce a MODBUS Slave device for $98 +SH that might be good to play with
They specialize is hobby equipment.
this is the link to the MODBUS device

http://www.homanndesigns.com/store/index.php?main_page=product_info&products_id=4

1 Like

@ smgvbest - exactly what I was looking for, thanks.

@ Gus -
In that price range you might also be interested in the ICP DAS M-7000 series:
http://www.icpdas.com/root/product/solutions/remote_io/rs-485/i-7000_m-7000/i-7000_m-7000_selection.html

Be sure to get the M, not the I models. The I models use a different protocol.

I was able to find out, it’s great. I just forgot to include this base class function :slight_smile: