ГлавнаяАкадемияCOURSE-16: Основы Интернета Вещей и практическое применение → IoT в промышленности (IIoT): от теории к практике на платформе HI

IoT в промышленности (IIoT): от теории к практике на платформе HI

Урок 2 · COURSE-16: Основы Интернета Вещей и практическое применение · theory

COURSE-16-M05-L03 — IoT в промышленности (IIoT): от теории к практике на платформе HI

Введение в промышленный IoT (IIoT)

Промышленный интернет вещей (Industrial Internet of Things, IIoT) — это применение технологий IoT для кардинального улучшения производственных и технологических процессов. В отличие от потребительского IoT (умные часы, бытовая техника), IIoT фокусируется на повышении эффективности, надежности и безопасности промышленных систем: от отдельных станков до целых производственных линий и инфраструктурных объектов.

На платформе HI контроллер выступает в роли шлюза и локального центра обработки данных, позволяя реализовать полноценные IIoT-решения для малых и средних промышленных объектов, таких как насосные станции, котельные, системы вентиляции и небольшие производственные участки.

Компоненты IIoT в экосистеме HI

Абстрактные компоненты IIoT находят прямое воплощение в аппаратных и программных возможностях контроллера HI.

* Сбор данных: Контроллер HI напрямую работает с промышленными датчиками через:

* Универсальные входы (UI): Для датчиков с выходом "сухой контакт" (аварии, концевые выключатели), аналоговых датчиков 0-10В (давление, уровень), а также цифровых датчиков температуры/влажности (1-Wire).

* Шина RS-485: Для подключения промышленных устройств по протоколу Modbus RTU (счетчики электроэнергии, частотные преобразователи, модули ввода-вывода).

* Шина CAN: Для связи с автомобильным или промышленным оборудованием, требующим высокой скорости и надежности.

* Управление: Встроенные реле контроллера используются для коммутации силовых цепей (включение/выключение двигателей, насосов, освещения) через контакторы и пускатели.

* Node-RED: Основная среда для создания логики. Потоки (flows) в Node-RED позволяют визуально программировать сценарии: опрос датчиков, обработку данных, принятие решений и отправку команд.

* Функция ПЛК (PLC): Для критически важных, детерминированных задач контроллер HI использует выделенное ядро ARM32, обеспечивающее предсказуемое время реакции и переход в безопасное состояние (safe-state) при сбоях основной системы.

* Локальное хранилище: Встроенная база данных MySQL и EEPROM используются для надежного хранения сценариев, уставок и журнала событий (audit log), обеспечивая автономность объекта даже при потере связи с "облаком".

* MQTT: Основной протокол для передачи телеметрии в облачные платформы или на центральный диспетчерский пульт. Контроллер HI выступает в роли MQTT-клиента, публикуя данные и подписываясь на команды.

* Резервные каналы: Опциональные модули GSM/LTE обеспечивают передачу данных при отказе основного интернет-канала.

* Сетевая безопасность: Использование защищенных протоколов (MQTT с TLS), сегментация сетей, настройка файрвола на Debian.

* Контроль доступа: Защита интерфейса Node-RED паролем, разграничение прав доступа.

* Физическая безопасность: Установка контроллера в запираемый электротехнический шкаф.

Практический пример: Мониторинг и управление небольшим насосным агрегатом

Рассмотрим типовую задачу для небольшого промышленного объекта — мониторинг состояния и базовое управление насосом, который откачивает воду из резервуара.

Задача:
  • Считывать ток, потребляемый двигателем насоса (для косвенной оценки нагрузки и обнаружения заклинивания).
  • Считывать температуру корпуса двигателя (для защиты от перегрева).
  • Обеспечить возможность удаленного включения/выключения насоса.
  • Реализовать аварийное отключение при превышении пороговых значений тока или температуры.
  • Всю телеметрию отправлять на MQTT-брокер.
  • Необходимое оборудование:

    Схема подключения (WIRING-PUMP-001)

    📋 Чеклист подключения:

  • [ ] Силовая линия насоса проходит через контактор.
  • [ ] Управляющая катушка контактора (230V) подключена к одному из релейных выходов контроллера HI (например, `RL-10`).
  • [ ] Modbus-счетчик подключен к шине RS-485 контроллера (`A` к `A`, `B` к `B`). Адрес счетчика (Slave ID) выставлен, например, на `15`.
  • [ ] Датчик температуры DS18B20 подключен к универсальному входу контроллера, настроенному как 1-Wire (например, `UI-05`).
  • [ ] На концах шины RS-485 установлены терминирующие резисторы 120 Ом.
  • //=============== WIRING-PUMP-001: Pump Monitoring & Control ===============
    
    

    // LEGEND:

    // CTRL:HI-Core - Контроллер HI

    // CONTACTOR-01 - Силовой контактор насоса

    // PUMP-MOTOR-01 - Двигатель насоса

    // METER-MODBUS-01- Modbus-счетчик (Slave ID: 15)

    // T-SENS-01 - Датчик температуры DS18B20

    // Relay Control (Contactor)

    [CTRL:HI-Core] (CONTACTOR-01)

    RL-10 (C) ---- ~L~ (от автомата)

    RL-10 (NO) --- A1 (катушка контактора)

    A2 ---- ~N~

    // Power Line

    ~L~ (от автомата) --- (METER-MODBUS-01) --- 1/L1 (CONTACTOR-01) --- (PUMP-MOTOR-01)

    ~N~ --------------------------------------- 3/L2 (CONTACTOR-01) --- (PUMP-MOTOR-01)

    // Modbus RTU (RS-485) Connection

    [CTRL:HI-Core] (METER-MODBUS-01)

    RS485-1 (A) ----A---- (зеленый) ---- A

    RS485-1 (B) ----B---- (белый) ------ B

    RS485-1 (GND) --GND-- (черный) ----- GND

    // 1-Wire Sensor Connection

    [CTRL:HI-Core] (T-SENS-01: DS18B20)

    UI-05 (Data) --- (желтый) --------- Data

    GND ---------- (черный) --------- GND

    +5V ------------ (красный) -------- VDD (если не паразитное питание)

    Логика в Node-RED (FLOW-PUMP-MONITOR-001)

    ASCII-схема потока:
    // Flow: Опрос датчиков
    

    [Inject: 10s] -> [Modbus-Getter: Ток] -> [Function: Формат] -> |

    |-> [Join] -> [Function: Проверка] -> [MQTT Out]

    [Inject: 30s] -> [ds18b20 in: Темп.] -> [Function: Формат] -> |

    // Flow: Управление

    [MQTT In: cmd] -> [Switch: ON/OFF] -> [Function: Команда] -> [GPIO Out: Реле] -> [MQTT Out: Статус]

    // Flow: Обработка ошибок

    [Catch: All] -> [Function: Лог ошибки] -> [MQTT Out: /errors]

    Реализация ключевых узлов:
  • Опрос тока (`Modbus-Getter`):
  • * Настраивается на опрос регистра тока с устройства с `Unit-ID: 15`.

    * 💡 Изучите карту регистров вашего счетчика, чтобы найти правильный адрес. Например, для WB-MAP12E ток фазы 1 — это регистр `128`.

  • Форматирование данных (`Function`):
  • * Критически важно: Все данные в системе должны соответствовать единому контракту сообщения.

    * Этот узел преобразует "сырые" данные от датчиков в стандартный JSON-формат.

        // Пример для узла после Modbus-Getter

    // msg.payload от узла = { data: [156], buffer: <...> }

    // 156 -> 1.56 A (согласно документации на счетчик)

    let currentValue = msg.payload.data[0] / 100;

    // Формируем сообщение по контракту

    msg.payload = {

    value: currentValue,

    unit: "A",

    source: "METER-MODBUS-01",

    ts: Date.now()

    };

    msg.topic = "telemetry/pump-01/current";

    // Паттерн "Визуальный статус"

    node.status({fill:"green", shape:"dot", text: `Ток: ${currentValue} A`});

    return msg;

  • Проверка порогов (`Function`):
  • * Этот узел реализует логику конечного автомата (FSM). Он получает объединенные данные о токе и температуре и принимает решение.

    * Состояние насоса (`ON`/`OFF`) хранится в переменной контекста (`flow.pump_state`).

        // Получаем данные из контекста

    let current = msg.payload.current; // Предполагаем, что узел Join собрал данные

    let temperature = msg.payload.temperature;

    let pumpState = flow.get("pump_state") || "OFF";

    const MAX_CURRENT = 5.0; // Аварийный ток, А

    const MAX_TEMP = 85.0; // Аварийная температура, °C

    if (pumpState === "ON" && (current > MAX_CURRENT || temperature > MAX_TEMP)) {

    // АВАРИЯ! Отключаем насос

    node.warn(`Аварийное отключение насоса! Ток: ${current}A, Темп: ${temperature}°C`);

    // Отправляем команду на отключение реле

    // Это сообщение пойдет на узел управления реле

    return { payload: "OFF", topic: "commands/pump-01/set" };

    }

    // Если все в норме, просто пропускаем сообщение дальше (на MQTT)

    // В реальной системе здесь будет более сложная логика

    return null;

  • Обработка ошибок (`Catch`):
  • * На вкладке должен быть узел `Catch`, настроенный на перехват ошибок со всех узлов.

    * Он ловит ошибки связи (например, таймаут Modbus), ошибки в коде и т.д.

    * Пойманная ошибка форматируется и отправляется в специальный MQTT-топик `telemetry/system/errors` и/или пишется в локальную MySQL базу для аудита.

    План тестирования и сдачи объекта

    После монтажа и настройки необходимо провести комплексное тестирование.

  • Проверка физических подключений: Визуальный осмотр соответствия схеме `WIRING-PUMP-001`, проверка затяжки клемм.
  • Тест ручного управления: Отправить MQTT-сообщение `ON` в топик `hi/pump-01/set`. Убедиться, что контактор сработал, и насос включился. Проверить команду `OFF`.
  • Проверка телеметрии: При работающем насосе проверить в MQTT-клиенте, что в топики `telemetry/pump-01/current` и `telemetry/pump-01/temperature` приходят адекватные, регулярно обновляемые значения.
  • Тест аварийного отключения (Имитация): Временно в узле "Проверка порогов" занизить `MAX_CURRENT` до значения ниже текущего рабочего. Убедиться, что насос автоматически отключился, а в логе появилось предупреждение. Вернуть порог к нормальному значению.
  • Тест на отказ связи: Отключить Modbus-счетчик от шины RS-485. Убедиться, что в MQTT-топике `telemetry/system/errors` появилось сообщение об ошибке связи (таймаут Modbus).
  • ---

    Лабораторные работы

    COURSE-16-M05-LAB01: Настройка мониторинга промышленного датчика

    * (30%) `Modbus-Getter` корректно настроен и считывает данные.

    * (40%) Узел `Function` корректно преобразует данные в JSON-формат по контракту сообщения.

    * (20%) Узел `Status` отображает актуальное значение и единицу измерения.

    * (10%) Данные успешно публикуются в заданный MQTT-топик.

    COURSE-16-M05-LAB02: Реализация логики аварийной защиты

    * (40%) Логика проверки порогового значения реализована корректно.

    * (30%) При превышении порога команда на отключение корректно отправляется на узел `GPIO Out`.

    * (20%) После отключения в MQTT-топик статуса отправляется сообщение `OFF`.

    * (10%) В поток добавлен узел `Catch` для перехвата возможных ошибок.

    Квиз по модулю

    COURSE-16-M05-QUIZ

  • Какой протокол является стандартом де-факто для подключения промышленных датчиков по шине RS-485?
  • * a) MQTT

    * b) CAN

    * c) Modbus RTU

    * d) DALI

  • В схеме `WIRING-PUMP-001` для чего используется контактор?
  • * a) Для измерения тока насоса.

    * b) Для коммутации силовой цепи двигателя насоса с помощью слаботочного сигнала от реле контроллера.

    * c) Для защиты от короткого замыкания.

    * d) Для преобразования протоколов.

  • Что такое "контракт сообщения" в контексте Node-RED?
  • * a) Лицензионное соглашение на использование узлов.

    * b) Стандартизированный JSON-формат объекта `msg.payload` для обеспечения предсказуемости данных.

    * c) Документ, описывающий физические подключения.

    * d) Настройки MQTT-брокера.

  • Какой узел Node-RED используется для перехвата ошибок связи или выполнения кода?
  • * a) `Inject`

    * b) `Switch`

    * c) `Catch`

    * d) `Link Out`

  • На схеме подключения `WIRING-PUMP-001` экран кабеля RS-485 подключается к GND:
  • * a) С обеих сторон (у контроллера и у датчика).

    * b) Только со стороны датчика.

    * c) Только со стороны контроллера.

    * d) Не подключается совсем.

  • Вам нужно сохранить состояние насоса (`ON`/`OFF`) так, чтобы оно не сбрасывалось при перезагрузке контроллера. Где его следует хранить?
  • * a) В глобальной переменной (`global.context`).

    * b) В `msg.payload`.

    * c) В переменной потока (`flow.context`) с настроенным персистентным хранилищем (filesystem или MySQL).

    * d) В имени узла.

  • Что означает ошибка "Off-by-one" при настройке Modbus?
  • * a) Перепутаны провода A и B.

    * b) Адрес регистра в документации (например, 40001) не совпадает с адресом в запросе (который должен быть 0).

    * c) Не установлен терминирующий резистор.

    * d) Неверно указан Slave ID.

  • Для чего в IIoT-системах используется протокол MQTT?
  • * a) Для прямого управления реле.

    * b) Для опроса Modbus-устройств.

    * c) Для легковесной и надежной передачи телеметрии от контроллера в облако или на пульт диспетчера.

    * d) Для программирования логики контроллера.

  • Какой паттерн Node-RED позволяет быстро оценить состояние узла без подключения `Debug`?
  • * a) Паттерн "Конечный автомат".

    * b) Паттерн "Визуальный статус" с использованием `node.status()`.

    * c) Паттерн "Обработка ошибок".

    * d) Паттерн "Субпоток".

  • Вы видите в логах ошибку `Modbus-Read: Timed out`. Какова наиболее вероятная причина?
  • * a) Неправильный формат данных в узле `Function`.

    * b) Физическая проблема на линии RS-485 (обрыв, неверный Slave ID, отсутствие питания у устройства).

    * c) Ошибка в MQTT-брокере.

    * d) Недостаточно оперативной памяти у контроллера.

    Мини-runbook: "Что делать, если не работает?"

    * Диагностика:

    1. Проверьте физическое подключение: не перепутаны ли клеммы A/B? Есть ли питание на устройстве?

    2. Проверьте настройки в узле `Modbus-Getter`: правильный ли `Unit-ID` (Slave ID)? Правильные ли параметры порта (скорость, четность)?

    3. Проверьте шину: есть ли на концах терминаторы 120 Ом? Нет ли на шине устройств с одинаковыми адресами?

    * Диагностика:

    1. Перечитайте документацию на устройство. Скорее всего, вы неверно интерпретируете формат данных (например, значение нужно делить на 100, или это 32-битное число с другим порядком байт).

    2. Проверьте на ошибку "Off-by-one": для регистра `40001` в запросе должен быть адрес `0`.

    * Диагностика:

    1. Проверьте силовую цепь: есть ли напряжение на входе контактора?

    2. "Прозвоните" катушку контактора. Возможно, она неисправна.

    3. Убедитесь, что автомат, питающий насос, включен.

    * Диагностика:

    1. Подключите узел `Debug` к выходу предыдущего узла. Посмотрите, в каком формате приходят данные.

    2. Скорее всего, вы пытаетесь обработать свойство, которого нет в `msg.payload` (например, `msg.payload.data[0]`, когда `msg.payload.data` не является массивом). Добавьте в код проверки: `if (msg.payload && msg.payload.data) {...}`.