Просто о NModbus (RTU)

  • Tutorial
Данная статья рассчитана на новичков.

Теория


Modbus — коммуникационный протокол, основанный на архитектуре ведущий-ведомый (master-slave). Использует для передачи данных интерфейсы RS-485, RS-422, RS-232, а также Ethernet сети TCP/IP.

NModbus – большая библиотека на C#, включающая в себя реализацию всех режимов работы с протоколом. Модель реализации классов этой библиотеки позволяет работать с любым Modbus-устройством, но только с одним, поскольку классы библиотеки инкапсулируют в себе порт, не позволяя реализовать синхронизацию между несколькими Modbus-объектами. Данный протокол достаточно популярен при разработке разной периферии для умного дома, а так же интернета вещей.

Команды
Руководство, с перечнем всех команд можно найти в официальном мануале, там так же есть примеры кода для TCP/IP соединений.

Итак, для того, чтобы управлять чем-либо, нам необходимо знать, что и куда отправлять. Значит нам нужна карта регистра.

Уточню, что ячейки регистра бывают:
1. Только для чтения
2. Для чтения и записи
3. Только для записи(подтверждение записи допустимо выдавать кодом ошибки)

Самая простая карта, выглядит примерно таким образом:
Скриншот


Так же, там присутствуют разные пояснения, о том например, какое максимальное/минимальное значение может быть передано по адресу и тд.

Практика


Я пользуюсь пробной версией симулятора из Modbus Tools и COM портами от MOXA с RS-485 интерфейсом.

COM порт


После того, как вы создали проект, необходимо интегрировать в него NModbus. Я рекомендую использовать VisualStudio, поскольку сделать это в нем достаточно просто с помощью NuGet, как показано ниже:

Шаг 1-й


Шаг 2-й


В ModbusTools нам необходимо задать параметры соединения(для Вас они могут отличатся, для моих COM-портов подходят эти):

Открываются параметры на F3, либо по вкладке «Connection».

Для Master и Slave настройки должны совпадать, за исключением пункта с COM портами.

Скриншот


После настройки можно нажать «OK» и устройства подключатся друг к другу. Либо этого не произойдет и появится надпись о том, что соединение прервано N секунд, либо отсутствует вовсе. В таком случае, проверьте настройки и соединение, убедитесь в том, что драйвера для COM портов установлены верно и работают корректно.

Пример простой программы
using Modbus.Device;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Modbus
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialPort serialPort = new SerialPort(); //Create a new SerialPort object.
            serialPort.PortName = "COM1";
            serialPort.BaudRate = 9600;
            serialPort.DataBits = 8;
            serialPort.Parity = Parity.None;
            serialPort.StopBits = StopBits.One;
            serialPort.Open();
            ModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);

            byte slaveID = 1;
            ushort startAddress = 0;
            ushort numOfPoints = 1;
            ushort[] holding_register = master.ReadHoldingRegisters(slaveID, startAddress,
            numOfPoints);
            Console.WriteLine(holding_register);
            Console.ReadKey();
        }
    }
}


Скриншот


Важно: если вы разрабатываете, что то сложнее, чем пример выше — необходимо следить за тем, чтобы пакеты не терялись. Возникает необходимость подсчета контрольных сумм, об этом можно почитать здесь.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 18

    +1
    Или я совсем не в теме, или автор меня запутал. Есть протокол modbus rtu который работает через последовательный порт, и есть modbus tcp который работает через ethernet.
    А в конце статьи оказывается nmodbus это не протокол, а библиотека на C# которая реализует протокол modbus.
      0
      Да, это библиотека, которая поддерживает:
      Modbus/RTU Master/Slave
      Modbus/ASCII Master/Slave
      Modbus/TCP Master/Slave
      Modbus/UDP Master/Slave

      Автор скорее всего автор не силён в протоколе и их вариациях и решал просто поделится информацией, что есть такая библиотека.
      Мне вот другое интересно.
      Насколько сильно она будет грузить ПК при интенсивном обмене?
      Есть ли возможность посылать широковещательные посылки?
      Что делать с остальными командами? Их куда больше чем 4.
      Как добавить свои команды?

      Ну как-то так.
      Если судить чисто по мануалу, то да, это такая примитивненькая библиотечка, но она настолько примитивная, что я бы её не рекомендовал даже новичкам.
        +1
        она умеет широковещалки
        она умеет все стандартные катушки/регистры в том числе 3x/4x (input/holding)
        она умеет вроде все стандартные команды официального модбаса, по крайне мере я её использую и ни разу не натыкался что она чего-то не поддерживает.
        когда я её ставил, боялся что она не умеет чтени- записись нескольких регистров подряд, зря боялся умеет.

        по загрузке не могу ответить у меня не сильно интенсивный обмен.
      +1
      А как насчёт того, что в протоколе modbus паузы интерпретируются как конец пакета. И без реализации пакетного обмена может случиться так, что какой-либо другой процесс займёт CPU и не даст передать следующий байт в COM порт. И пакет прервётся.
      Лично я выбираю длы modbus'а именно USB-com свистки с размером пакета в USB endpoint больше или равно моим пакетам modbus и пишу библиотеку modbus через libusb, гарантировано засовывая весь пакет в буфер целиком. Но это тоже грязно, потому что максимальный пакет в modbus 247 байт, а пакет USB для таких свистков ограничевается 64 байт. Выход есть — FTDI, которые FT232H, работают в честном hight-speed и там пакеты до 1024 байт. Но это уже хорошие, дорогие свистки.
      Или можно воспользоваться аппаратным COM-портом и драйвером уровня ядра. В Linux он есть, например.
        0
        Есть ещё вариант использовать Modbus ASCII. Там конец пакета по символам 13, 10 определяется. Но избыточность данных двойная.
          0
          Всё, что я написал, относится к случаям, когда приходится поднимать скорость modbus выше 38400, какой уж там ASCII. На 9600 нам на перетачу одного байта уходит порядка 1мс. Чтобы приложение заснуло на такое время это надо постараться. Другое дело, 115 200, там уже пауза 250мкс. Это сопоставимо с интервалами у USB
          +2
          Самая большая неприятность с дешевыми свистками не в буфере. Часто они просто нестабильно работают и периодически отваливаются. Длинну ответа RTU можно рассчитать по запросу(вы же знаете сколько регистров вы запросили, и что ожидать в ответ). Но на случай modbus-ошибки нужно прочитать первые 2 байта ответа. Многие slave сами не выдерживают нужные интервалы — приходится «сшивать» ответ из нескольких частей.
          +1

          Кстати, Modbus Poll нифига не бесплатное ПО. Лицензия $129 стоит.

            0
            Уточнил про Trial-версию :)
            Можно так же пользоваться Modbus PLC Simulator, это опенсорс проект, вроде. Он даже лучше, по моему мнению, но интерфейс несколько сложнее.
              0
              Интересная штука, надо будет глянуть на досуге.
            0
            Маленькое замечание. В стандарте Modbus 2012 года я не находил упоминания о том, что регистр для записи обязательно делать доступным для чтения. Вполне допустимо подтверждение записи выдавать кодом ошибки.
            Поэтому, я полагаю что строго говоря
            "… ячейки регистра бывают:
            1. Только для чтения
            2. Для чтения и записи
            3. Только для записи"

            Более того, я такое экзотичное устройство даже видел.
              0
              Спасибо, исправил
                0
                а можно ссылку на стандарт? на modbus.org я не видал такого?
                я не хочу никого обидеть, я хочу узнать, может это я где проглядел?.. я в том числе слейвы делаю по этому хочу узнать…
                можно какбы записать одно а прочитать другое… это да…
                  +1
                  конечно, я имел ввиду именно это место.
                  MODBUS APPLICATION PROTOCOL SPECIFICATION V1.1b3
                  от 2012 года
                  modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf

                  страницы 19 и 20. Figure 16: Write Single Register state diagram
                  и в этой диаграмме ничего про Чтение не написано.

                  Читать Весть документ надо Очень Внимательно. Там есть достаточно интересные вещи, которые можно понять ровно наоборот от того, как они написаны.

                  можно записать одно, читать другое, можно отправить запрос на чтение и содержимое регистра будет меняться как угодно от момента именно чтения.
                  можно записать что-то и ждать статус как часть ключа шифрования.

                  это не регламентировано, строго говоря. И да, играться так — удел достаточно странный для многих(((
                    0
                    Читать Весть документ надо Очень Внимательно

                    с этим полностью согласен. у них там вобще прелесть в документации…

                    благодарю! действительно интересн.
                      0
                      Я бы немного дополнил, что
                      Сталкивался(юсь) часто с тем, что бывают устройства(в том числе под моей ответственностью), которые работают как описано мной выше:
                      Выставил записью запрос и жди (неизвестно сколько от этого интрегующе) пока в другом регистре что то поменяется.
                      Или в двух регистрах записанные флаги, текущие значения, пороги и настройки(уже не моё).

                      С родной программой на ПК это живёт достаточно хорошо,
                      А со сторонними орс\modbus серверами и ПЛК — далеко не всегда.
                      Хотя и позволяет на некотором уровне дополнять систему и Modbus, в том числе и самопальным шифрованием и прочими прелестями)

                      А пару раз сталкивался с тем, что фразу
                      "… больше не надо discret input регистры только с 10000 выбирать, это легаси мы отменили в 1996 году, не делайте так больше "
                      читают как
                      "...discret input modbus это только начиная с 10000 по индексу..."
                      соответственно обращаться к ним с 0. т.е. discret input с физическим номером скажем 5 не может существовать, может только 10005 и к нему мы обратимся как к 5. К примеру Delta таким грешит и Advantech ( habr.com/ru/company/advantech/blog/450234 )
                      Правда я эту проблему пытаюсь обойти тем, что прошу разработчиков в РЭ указывать прямо примеры посылок, чтобы не было неоднозначности.
                        0
                        К примеру Delta таким грешит и Advantech

                        солидарен — эти ребята вобще модбас трактуют по своему… также сталкивался…

                        ещё был weintek, но они вроде в последнее время исправились…
              • НЛО прилетело и опубликовало эту надпись здесь

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое