ГлавнаяАкадемияОсновы умного дома → RS-485 и Modbus RTU

RS-485 и Modbus RTU

Урок 1 · Основы умного дома · 30 мин · theory
id: COURSE-01-M04-L02

title: "RS-485 и Modbus RTU"

level: foundation

tags: [protocol, rs-485, modbus, wiring, node-red, integration]

prerequisites: [COURSE-01-M04-L01]

version: 1.0

status: published

---

# Урок: RS-485 и Modbus RTU

В предыдущем уроке мы обсудили, зачем в системах автоматизации нужны протоколы и как они обеспечивают структурированное взаимодействие между устройствами. Сегодня мы углубимся в одну из самых надежных и распространенных связок в промышленной и коммерческой автоматизации: физический интерфейс RS-485 и протокол Modbus RTU. Эта комбинация является стандартом де-факто для подключения счетчиков электроэнергии, модулей реле, климатического оборудования и множества других периферийных устройств.

📋 Ключевые понятия:

🎯 Цели обучения:

По завершении этого урока вы сможете:

Что такое RS-485? Физический уровень.

Часто начинающие инженеры путают RS-485 и Modbus, считая их одним и тем же. Крайне важно понимать их разделение. RS-485 — это не протокол, а стандарт физического уровня (Physical Layer, L1). Он описывает, как электрические сигналы передаются по проводам, но ничего не говорит о том, что эти сигналы значат.

Представьте, что RS-485 — это телефонная линия между двумя людьми. Линия обеспечивает возможность голосу дойти от одного абонента к другому, но она не определяет язык, на котором они будут говорить (русский, английский или китайский). Этим "языком" в нашем случае выступит протокол Modbus, который мы рассмотрим далее.

> 💡 Подсказка: Для построения шины RS-485 всегда используйте специализированный кабель или витую пару (например, UTP Cat5e). Это минимизирует влияние помех и обеспечит стабильность связи на больших дистанциях.

Ключевые характеристики RS-485:

  • Дифференциальная передача данных: В отличие от интерфейсов, использующих один сигнальный провод и землю (как RS-232), RS-485 использует два провода, которые принято называть A и B. Сигнал передается разностью потенциалов между этими линиями. Если на линию А подается высокий уровень, то на линию B одновременно подается низкий, и наоборот. Приемник "слушает" именно эту разницу. Такой подход обеспечивает極めて высокую помехоустойчивость: любая внешняя электромагнитная помеха (от силовых кабелей, двигателей) воздействует на оба провода одинаково, но разница потенциалов между ними остается неизменной.
  • Топология "шина" (Bus): Устройства подключаются к общей двухпроводной линии параллельно друг другу. Это позволяет значительно экономить кабель по сравнению с топологией "звезда", где к каждому устройству нужно тянуть отдельный провод от контроллера.
  •     ┌───────────┐      ┌───────────┐      ┌───────────┐      ┌───────────┐

    │Контроллер │ │Устройство 1│ │Устройство 2│ │Устройство N│

    │ (Client) │ │ (Server) │ │ (Server) │ │ (Server) │

    └─────┬─┬───┘ └─────┬─┬───┘ └─────┬─┬───┘ └─────┬─┬───┘

    | | | | | | | |

    A o───┼─┴──────────────┼─┴──────────────┼─┴──────────────┼─┴──o A

    B o───┴────────────────┴────────────────┴────────────────┴────o B

    ▲ ▲

    │ │

    Терминатор (120 Ом) Терминатор (120 Ом)

  • Терминаторы: Длинная шина ведет себя как линия передачи. Сигнал, дойдя до ее физического конца, может отразиться и пойти обратно, создавая помехи для других сигналов. Чтобы "поглотить" сигнал в конце линии, устанавливаются согласующие резисторы — терминаторы — номиналом 120 Ом. Они ставятся только на двух крайних устройствах шины. Наш контроллер имеет встроенный переключаемый терминатор, так как он часто является одним из концов шины.
  • Полудуплексный режим: Поскольку для передачи данных используется всего одна пара проводов, в каждый момент времени устройство может либо передавать данные, либо принимать их (говорить или слушать). Одновременная двунаправленная передача невозможна.
  • Масштабируемость: Стандарт RS-485 позволяет подключать до 32 устройств к одному сегменту шины длиной до 1200 метров. При использовании специальных повторителей (репитеров) количество устройств и длину шины можно значительно увеличить.
  • Modbus RTU: Протокол поверх RS-485

    Если RS-485 — это физическая среда, то Modbus — это протокол прикладного уровня, определяющий правила и формат общения. Он был создан в 1979 году для промышленных контроллеров и благодаря своей простоте и открытости стал одним из самых популярных протоколов в мире. Мы будем рассматривать его самую распространенную реализацию — Modbus RTU (Remote Terminal Unit), которая предназначена для работы поверх последовательных интерфейсов, таких как RS-485.

    > ⚠️ Внимание: Адрес устройства '0' в Modbus RTU является широковещательным (broadcast). Команды, отправленные на этот адрес, получат все устройства в сети, но ни одно из них не отправит ответ. Используйте эту функцию с особой осторожностью, например, для одновременной отправки команды на выключение всех реле.

    Ключевые аспекты Modbus RTU:

  • Модель Client-Server: Исторически эта модель называлась "Master-Slave" (Ведущий-Ведомый). В сети всегда есть одно и только одно клиентское устройство (Master), которое инициирует все обмены данными. В нашей архитектуре эту роль выполняет главный контроллер. Все остальные устройства на шине (модули реле, счетчики, диммеры) являются серверными (Slave) и только отвечают на запросы клиента. Они никогда не начинают передачу данных по своей инициативе.
  • Адресация устройств (Slave ID): Каждое серверное устройство на шине должно иметь уникальный адрес (Slave ID) в диапазоне от 1 до 247. Клиент, отправляя запрос, указывает в нем адрес целевого устройства. Только устройство с этим адресом обработает запрос и отправит ответ. Если два устройства будут иметь одинаковый адрес, возникнет конфликт на шине (оба попытаются ответить одновременно), и связь будет невозможна.
  • Структура кадра Modbus RTU: Каждый пакет данных (кадр) в сети Modbus RTU имеет четкую структуру:
  • * Адрес устройства (1 байт): Тот самый Slave ID (1-247).

    * Код функции (1 байт): Указывает, какое действие должен выполнить сервер (например, прочитать данные, записать данные).

    * Данные (N байт): Содержимое зависит от кода функции. Это могут быть стартовый адрес регистра и количество регистров для чтения, или адрес и значение для записи.

    * Контрольная сумма CRC (2 байта): Значение, рассчитанное по специальному алгоритму на основе всех предыдущих байт кадра. Приемник выполняет тот же расчет и сравнивает результат с полученной контрольной суммой. Если они не совпадают, пакет считается поврежденным и отбрасывается.

  • Основные коды функций (Function Codes): Хотя кодов функций довольно много, на практике для 95% задач достаточно знать четыре основных:
  • * `0x03 (Read Holding Registers)`: Чтение одного или нескольких 16-битных регистров хранения. Это наиболее часто используемая функция для получения данных состояния, измерений (температура, напряжение) и уставок.

    * `0x04 (Read Input Registers)`: Аналогично `0x03`, но читает регистры "только для чтения". Обычно используется для данных, которые нельзя изменить (например, показания счетчика электроэнергии).

    * `0x06 (Write Single Register)`: Запись значения в один 16-битный регистр хранения. Используется для управления, например, включением одного реле или установкой целевой температуры.

    * `0x10 (Write Multiple Registers)`: Запись значений в несколько регистров хранения подряд. Удобно для одновременного управления группой реле или обновления нескольких настроек за один запрос.

    Практика: Чтение данных с устройства в Node-RED

    Теперь перейдем от теории к практике. Наш контроллер с установленным Node-RED предоставляет мощные и удобные инструменты для работы с Modbus.

    🔗 Связанный материал: Подробно о принципах работы и установки Node-RED мы рассказывали в модуле `COURSE-01-M03`.

    Задача: Настроить опрос гипотетического датчика температуры и влажности, подключенного по Modbus RTU. Предположим, у него Slave ID = 15, и он отдает температуру в регистре 100, а влажность — в регистре 101. Шаг 1: Установка палитры `node-red-contrib-modbus`
  • Откройте веб-интерфейс Node-RED.
  • В правом верхнем углу нажмите на меню "гамбургер" (☰) и выберите "Manage palette".
  • Перейдите на вкладку "Install".
  • В строке поиска введите `node-red-contrib-modbus` и нажмите "Install". Дождитесь завершения установки.
  • Шаг 2: Настройка клиента Modbus
  • После установки в левой панели появятся новые узлы с префиксом "Modbus". Перетащите любой из них на поле (например, `Modbus-Read`).
  • Дважды щелкните по узлу, чтобы открыть его настройки.
  • В поле "Server" нажмите на значок карандаша, чтобы добавить новую конфигурацию Modbus-клиента.
  • В окне настройки клиента заполните поля:
  • * Name: "Шина RS485-1" (или любое понятное имя).

    * Type: `RTU` (для работы через последовательный порт).

    * Serial Port: `/dev/ttyRS485-1` (это типовой путь к порту RS-485 на нашем контроллере; если вы используете внешний USB-адаптер, путь может быть `/dev/ttyUSB0`).

    * Serial Type: `RTU-BUFFERD`.

    * Baud Rate: `9600` (или другая скорость, указанная в документации к вашему устройству).

    * Data Bits: `8`.

    * Parity: `None`.

    * Stop Bits: `1`.

    * Unit-ID: Оставьте это поле пустым здесь. Оно будет задаваться в каждом узле чтения/записи индивидуально.

  • Нажмите "Add", а затем "Done" в окне узла `Modbus-Read`. Конфигурация клиента сохранена и может быть переиспользована в других узлах.
  • Шаг 3: Настройка узла `Modbus-Read`
  • Еще раз откройте настройки узла `Modbus-Read`.
  • Заполните поля в соответствии с нашей задачей:
  • * Name: "Чтение T/H датчика".

    * Unit-ID: `15` (адрес нашего датчика).

    * FC: `0x03: Read Holding Registers`.

    * Address: `100` (адрес первого регистра для чтения).

    * Quantity: `2` (мы хотим прочитать два регистра подряд: 100 и 101).

    * Poll Rate: `5 seconds` (опрашивать устройство каждые 5 секунд).

  • Нажмите "Done".
  • Шаг 4: Разбор ответного сообщения
  • Добавьте узел `Debug` и соедините его с выходом узла `Modbus-Read`.
  • Разверните (Deploy) flow.
  • Перейдите в панель отладки (справа, значок жука). Каждые 5 секунд вы будете видеть новое сообщение от `Modbus-Read`.
  • Его `msg.payload` будет выглядеть примерно так:

    {
    

    "data": [ 255, 480 ],

    "buffer": ""

    }

    Узел `modbus-contrib` удобно преобразует сырые данные из буфера (`buffer`) в массив чисел (`data`). В нашем примере:

    Часто производители кодируют значения. Например, "температура = значение / 10". Тогда реальная температура будет 25.5°C, а влажность — 48.0%. Для таких преобразований идеально подходит узел `Function`.

    Реальный кейс: Управление реле

    Рассмотрим, как управлять реальным устройством. Возьмем для примера популярный модуль реле Wirenboard WB-MR6C. Он имеет 6 релейных выходов и управляется по Modbus.

    > 💡 Подсказка: Всегда начинайте работу с новым Modbus-устройством с внимательного изучения его карты регистров (Modbus Register Map). Это самый важный документ для успешной интеграции.

    Шаг 1: Изучение карты регистров

    Открыв документацию на WB-MR6C, мы находим информацию:

    Шаг 2: Создание flow для управления
  • Добавьте на поле два узла `Inject` и один узел `Modbus-Write`.
  • Настроим первый `Inject`:
  • * Payload: `number` (число) `1`.

    * Topic: `relay/1/on`.

    * Name: "Включить Реле 1".

  • Настроим второй `Inject`:
  • * Payload: `number` (число) `0`.

    * Topic: `relay/1/off`.

    * Name: "Выключить Реле 1".

  • Настроим узел `Modbus-Write`:
  • * Name: "Управление Реле 1".

    * Server: Выберите ранее созданную конфигурацию "Шина RS485-1".

    * Остальные параметры оставим пустыми, так как мы будем передавать их в сообщении.

  • Соедините выходы обоих `Inject` со входом `Modbus-Write`.
  • Шаг 3: Формирование управляющего сообщения

    `Modbus-Write` ожидает на вход `msg.payload`, содержащий значение для записи. Но как ему узнать адрес и код функции? Для этого мы можем передать их в объекте `msg`. Добавим узел `Function` между `Inject` и `Modbus-Write`.

    // Function node
    

    // Предположим, у модуля WB-MR6C адрес (Slave ID) = 10

    // Регистр для Реле 1 = 128

    // Получаем значение (0 или 1) из входа

    const value = msg.payload;

    // Формируем объект для узла Modbus-Write

    msg.payload = {

    'value': value,

    'fc': 6, // 0x06: Write Single Register

    'unitid': 10,

    'address': 128

    };

    return msg;

    Теперь, при нажатии на `Inject` "Включить Реле 1", узел `Function` сформирует правильный объект, и узел `Modbus-Write` отправит команду на запись `1` в регистр `128` устройства `10`. Реле щелкнет и включится.

    Диагностика проблем на шине RS-485/Modbus

    Ничто не работает с первого раза. Сети Modbus могут быть капризны, и умение диагностировать проблемы — ключевой навык инженера. Вот мини-runbook для отладки.

    1. Программные ошибки (самые частые): Неверные параметры порта: Проверьте трижды скорость (Baud Rate), четность (Parity), количество бит данных (Data bits) и стоп-биты (Stop bits). Они должны быть абсолютно одинаковыми* на контроллере и на всех устройствах на шине. 2. Физические ошибки: 3. Анализ ошибок в Node-RED:

    Узлы `node-red-contrib-modbus` при ошибках отправляют сообщение на второй выход. Подключите к нему `Debug` узел.

    4. Диагностика из консоли Linux:

    Иногда полезно проверить связь, минуя Node-RED. Наш контроллер на базе Debian позволяет использовать утилиту `mbpoll`.

    Установите ее: `sudo apt-get install mbpoll`

    Пример: опросить 1 регистр, начиная с адреса 128, у устройства с ID=10 на порту `/dev/ttyRS485-1` со скоростью 9600.

    mbpoll -a 10 -b 9600 -P none -t 4 -r 128 -c 1 /dev/ttyRS485-1
    

    Если `mbpoll` показывает данные, а Node-RED — нет, проблема в настройках Node-RED. Если `mbpoll` тоже не работает, проблема на физическом уровне или в настройках порта.

    Резюме и ключевые выводы

    В этом уроке мы сделали глубокое погружение в мир RS-485 и Modbus RTU — фундаментальных технологий для построения надежных систем автоматизации.

    Освоив связку RS-485/Modbus, вы открыли для себя возможность интеграции огромного парка промышленного и инженерного оборудования в экосистему нашей платформы.

    ---

    Что дальше:

    В следующем уроке мы познакомимся с другим мощным протоколом, который является сердцем многих современных IoT-систем и ключевым элементом нашей платформы.

    ➡️ Следующий урок: COURSE-01-M04-L03: Введение в MQTT