ГлавнаяАкадемияДатчики и входы: нормализация сигналов → Физический сигнал, логическое событие, состояние системы: фундаментальные различия

Физический сигнал, логическое событие, состояние системы: фундаментальные различия

Урок · Датчики и входы: нормализация сигналов · 30 мин · theory

Введение: от физики к логике

В современной системе автоматизации мы постоянно работаем с данными, которые поступают от сотен датчиков и устройств. Чтобы построить надежную и предсказуемую систему, критически важно понимать путь, который проходят эти данные — от физического мира до логических операций внутри контроллера. Весь этот путь можно разложить на три фундаментальные составляющие: физический сигнал, логическое событие и состояние системы.

> ℹ️ Информация: В рамках этого курса мы будем использовать термины «сигнал», «событие» и «состояние» в строго определенном контексте, который является стандартом для инженеров сертификационной академии. Четкое разделение этих понятий — залог успешного проектирования и безошибочной диагностики.

Представьте себе простую аналогию:

  • Физический сигнал — это как прикосновение к горячему предмету. Нервные окончания на вашей коже (датчики) регистрируют изменение температуры. Это сырая, необработанная информация.
  • Логическое событие — это нервный импульс, который доходит до мозга и интерпретируется как «Опасно! Горячо!». Мозг отфильтровал незначительные колебания температуры и сгенерировал осмысленное предупреждение.
  • Состояние системы — это ваше знание: «Плита сейчас горячая». Вы можете не прикасаться к ней постоянно, но ваша внутренняя «память» хранит эту информацию. Если кто-то спросит вас, можно ли трогать плиту, вы ответите, исходя из сохраненного состояния, а не будете ждать нового «события» от прикосновения.
  • В экосистеме контроллера HI этот поток данных выглядит следующим образом:

    Понимание этой триады позволяет инженеру-инсталлятору корректно настраивать обработку данных от любого, даже самого сложного датчика, и создавать автоматизацию, которая работает не только «здесь и сейчас», но и будет стабильной, масштабируемой и простой в обслуживании в будущем.

    ---

    Физический сигнал: язык датчиков

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

    | Характеристика | Аналоговый сигнал | Дискретный сигнал |

    | ------------------------ | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |

    | Природа | Непрерывно изменяющаяся величина в определенном диапазоне. | Имеет только два или несколько фиксированных состояний. |

    | Примеры на объекте | Датчик температуры (NTC/PT1000), датчик освещенности (0-10В), датчик давления (4-20мА). | Кнопка, геркон на двери, датчик протечки, выход "сухой контакт" другого устройства. |

    | Физическое проявление | Изменение напряжения (e.g., 0-3.3В), изменение сопротивления. | Замкнутая или разомкнутая цепь (сопротивление близко к 0 или бесконечности). |

    | Роль контроллера HI | АЦП (Аналого-цифровой преобразователь) измеряет напряжение и преобразует его в число. | Универсальный вход в режиме DI (Digital Input) определяет, замкнута цепь или нет. |

    | "Сырые" данные | Число, пропорциональное напряжению. Например, `1532` (из диапазона 0-4095 для 12-битного АЦП). | `0` (разомкнуто) или `1` (замкнуто). |

    Аналоговый сигнал на примере датчика температуры NTC

    Датчик температуры NTC (Negative Temperature Coefficient) — это, по сути, резистор, сопротивление которого уменьшается при увеличении температуры. Контроллер HI подает на него опорное напряжение через делитель и измеряет результирующее напряжение на входе. Это напряжение напрямую зависит от сопротивления NTC-датчика, а значит, и от температуры.

    АЦП контроллера замеряет это напряжение и выдает "сырое" (raw) цифровое значение. Например, для 12-битного АЦП, работающего с напряжением от 0 до 3.3В, мы получим:

    В Node-RED, из специализированного узла для чтения аналоговых входов (например, гипотетического `HI-AI`), придет сообщение `msg` с `payload`, содержащим это сырое число: `1532`. Это и есть физический сигнал в его цифровом представлении. Он еще не несет для нас никакого смысла, кроме как "напряжение на входе составляет примерно `1532/4095 * 3.3В`".

    Дискретный сигнал на примере геркона

    Геркон (герметизированный контакт) на окне — это классический пример источника дискретного сигнала. Когда окно закрыто, магнит рядом с герконом замыкает его контакты. Когда окно открывается, магнит удаляется, и контакты под действием упругости размыкаются.

    Универсальный вход контроллера HI, настроенный как дискретный, постоянно проверяет состояние этой цепи.

    В Node-RED от узла `HI-DI` придет сообщение с `msg.payload`, равным `0` или `1`. Это тоже "сырой" физический сигнал. Он говорит нам о состоянии электрической цепи, но еще не говорит о состоянии окна в понятных для автоматизации терминах.

    > 💡 Подсказка: Для стабильного чтения дискретных сигналов всегда используйте внешнюю или внутреннюю "подтяжку" (pull-up/pull-down резисторы), чтобы избежать "плавающего" состояния входа, когда он не подключен ни к `GND`, ни к питанию. Подробнее об этом было рассмотрено в уроке 🔗 COURSE-03-M02-L01.

    ---

    Логическое событие: рождение смысла

    Логическое событие — это результат интеллектуальной обработки сырого физического сигнала. Это осмысленное, структурированное сообщение, которое говорит системе не о напряжении на клемме, а о том, что именно произошло в реальном мире. Процесс преобразования сигнала в событие называется нормализацией и является одной из ключевых задач инженера при настройке системы.

    Этот процесс происходит внутри Node-RED, как правило, в узле `function`.

    Техники нормализации и фильтрации

  • Приведение аналогового сигнала к физическим величинам. Сырое значение от АЦП (например, `1532`) бесполезно для логики. Его нужно преобразовать в градусы Цельсия, проценты влажности или паскали давления. Для этого используется формула или таблица преобразования из документации на датчик. Это и есть нормализация.
  • Фильтрация "дребезга контактов" (debounce). При замыкании механических контактов (кнопка, реле, геркон) возникает серия очень быстрых, хаотичных замыканий-размыканий, прежде чем контакт станет стабильным. Это называется "дребезг". Если не фильтровать его, одно нажатие кнопки может сгенерировать десятки сигналов `0` и `1`, что приведет к непредсказуемой работе логики. Для борьбы с этим используются специальные узлы (например, `delay` в режиме "rate limit" или `trigger`) или программные таймеры.
  • Использование пороговых значений (thresholds). Аналоговый сигнал может генерировать события. Например, мы можем решить, что событие `TEMPERATURE_HIGH` происходит, когда значение температуры превышает 25°C, а событие `TEMPERATURE_NORMAL` — когда опускается ниже 24.5°C (гистерезис для предотвращения частых переключений).
  • Формирование канонического `msg` объекта

    После нормализации и фильтрации результат должен быть упакован в стандартный, предсказуемый формат. Как мы знаем из паттернов Node-RED, это "контракт сообщения".

    Давайте посмотрим на примере преобразования сигнала с NTC-датчика в логическое событие.

    /*
    

    Узел Function: "Нормализация температуры в гостиной"

    Вход: msg.payload = 1532 (сырое значение от АЦП узла HI-AI)

    Выход: структурированное сообщение с температурой в °C

    */

    // --- 1. Нормализация ---

    // Предположим, мы экспериментально или по документации выяснили,

    // что для нашего датчика и делителя формула такова:

    // Temp_C = (3800 - raw_value) / 30.5

    let rawValue = msg.payload;

    let temperature = (3800 - rawValue) / 30.5;

    // Округляем до одного знака после запятой

    temperature = Math.round(temperature * 10) / 10;

    // --- 2. Валидация ---

    // Отсекаем нереалистичные значения, которые могут возникнуть при обрыве или КЗ датчика.

    if (temperature < -40 || temperature > 100) {

    // Если значение некорректно, логируем ошибку и останавливаем поток.

    // Узел Catch поймает эту ошибку.

    node.error(`Некорректное значение температуры после нормализации: ${temperature}°C, raw: ${rawValue}`, msg);

    return null; // Остановить обработку этого сообщения

    }

    // --- 3. Формирование каноничного сообщения (События) ---

    // Заполняем topic для маршрутизации

    msg.topic = "telemetry/living_room/temperature";

    // Заполняем payload согласно контракту

    msg.payload = {

    "value": temperature,

    "unit": "°C",

    "source": "ui-05-ntc-livingroom", // Уникальный ID источника

    "ts": Date.now(), // Временная метка события

    "raw": rawValue // Опционально сохраняем сырое значение для отладки

    };

    node.status({fill:"green", shape:"dot", text:`${temperature} °C`});

    return msg;

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

    ---

    Состояние системы: цифровая память объекта

    Если событие — это сообщение о том, что что-то изменилось, то состояние — это информация о том, как обстоят дела прямо сейчас. Состояние системы — это "снимок" всех её важных параметров в определенный момент времени, хранящийся в памяти контроллера.

    События порождают изменения состояния. Например, событие «Дверь открылась» изменяет состояние `system.doors.front_door` с `'closed'` на `'open'`.

    В Node-RED для хранения состояний используется механизм контекста. Контекст — это, по сути, область памяти, где можно хранить переменные. Существует три уровня контекста:

    > ⚠️ Внимание: Избегайте хранения слишком больших или сложных объектов в контексте. Это увеличивает использование оперативной памяти (ОЗУ) контроллера и может замедлить время развертывания потоков (deploy). Храните только необходимую информацию: `{'state': 'ON', 'brightness': 80}`, а не весь объект `msg`.

    Преимущества работы с состояниями

    Представьте, что вам нужно включить кондиционер, только если все окна в доме закрыты.

    Этот подход делает систему декомпозированной и масштабируемой. Логика управления кондиционером ничего не знает о герконах — она работает с абстрактными состояниями окон. А логика обработки герконов ничего не знает о кондиционере. Систему становится легко отлаживать и расширять.

    Пример чтения состояния из контекста в `function` узле:

    // Получаем текущий статус входной двери из глобального контекста
    

    const frontDoorStatus = global.get('security.doors.front_door');

    // frontDoorStatus может выглядеть так:

    // { "status": "closed", "last_change": 1678886400000 }

    if (frontDoorStatus && frontDoorStatus.status === 'open') {

    // Логика, если дверь открыта

    }

    Контроллер HI позволяет настроить персистентное хранение контекста. Это означает, что даже после перезагрузки или сбоя питания все сохраненные состояния будут восстановлены, и система вернется к работе в том же виде, в котором была до отключения. Это критически важно для надежности.

    ---

    Сквозной пример: от кнопки до управления светом

    Давайте объединим все три концепции на простом, но очень показательном примере: управление светом в комнате с помощью одной кнопки без фиксации. Каждое нажатие должно инвертировать состояние света (был включен — выключится, был выключен — включится).

    Наша задача:
  • Прочитать физический сигнал от кнопки, подключенной к универсальному входу HI-контроллера.
  • Отфильтровать дребезг и преобразовать сигнал в однократное логическое событие "Кнопка нажата".
  • На основе этого события изменить состояние света (`'ON'` или `'OFF'`), которое хранится в памяти.
  • Отправить команду на реле, управляющее светильником.
  • Схема потока в Node-RED:
               [HI-DI In]        [rbe]           [function]          [HI-Relay Out]
    

    (сигнал) -- (Кнопка) --.-- (Фильтр) -- (Событие) -- (Логика) -- (Изменение состояния) -- (Команда) --> (Реле света)

    | | | |

    0/1 1 "PRESSED" msg.payload: true/false

    Шаг 1: Чтение физического сигнала

    Используем узел `HI-DI In` (или его аналог для дискретных входов), настроенный на пин, к которому подключена кнопка. На выходе этого узла мы будем получать `msg.payload` со значением `1` при нажатии и `0` при отпускании.

    Шаг 2: Создание события "Кнопка нажата"

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

  • Подключаем выход узла `HI-DI In` к стандартному узлу `rbe` (report by exception). Этот узел будет пропускать сообщение дальше, только если его `payload` изменился. Он является простейшим фильтром.
  • После `rbe` ставим узел `switch`, который будет пропускать сообщение дальше, только если `msg.payload == 1`. Таким образом, мы отсекаем событие отпускания кнопки (`0`) и получаем только однократное событие "нажатие".
  • Теперь на выходе узла `switch` мы имеем чистое логическое событие, которое можно обрабатывать.

    Шаг 3: Обработка события и управление состоянием

    Это сердце нашей логики. Мы используем узел `function` для инвертирования состояния.

    /*
    

    Узел Function: "Логика переключения света"

    Вход: любое сообщение (событие нажатия кнопки)

    Выход: msg.payload = true (включить) или false (выключить)

    */

    // --- 1. Чтение текущего состояния ---

    // Сначала получаем текущее состояние света из контекста потока.

    // Если состояния нет (первый запуск), считаем, что свет выключен (false).

    let currentState = flow.get('light_state') || false;

    // --- 2. Инвертирование состояния ---

    // Меняем состояние на противоположное.

    let newState = !currentState;

    // --- 3. Сохранение нового состояния ---

    // Записываем новое состояние обратно в контекст потока для следующего нажатия.

    flow.set('light_state', newState);

    // --- 4. Формирование команды для реле ---

    // Помещаем новое состояние в msg.payload. Узел HI-Relay Out

    // ожидает `true` для включения или `false` для выключения.

    msg.payload = newState;

    // Обновляем визуальный статус узла для удобства отладки

    if (newState) {

    node.status({fill:"yellow", shape:"dot", text:"State: ON"});

    } else {

    node.status({fill:"grey", shape:"dot", text:"State: OFF"});

    }

    return msg;

    Шаг 4: Исполнение команды

    На выходе узла `function` мы имеем `msg.payload`, равный `true` или `false`. Это сообщение мы отправляем напрямую в узел `HI-Relay Out`, который настроен на управление нужным реле. Узел получит `true` и замкнет реле, или `false` и разомкнет его.

    Таким образом, мы прошли весь путь: от нестабильного сигнала `0/1/0/1/1...` на входе до чистого события "нажатие", которое изменило внутреннее состояние системы и привело к физическому действию.

    ---

    Резюме: Сигнал → Событие → Состояние

    В этом уроке мы рассмотрели три кита, на которых держится любая надежная система автоматизации. Четкое разделение этих понятий позволяет создавать логику, которая легко читается, отлаживается и масштабируется.

    Давайте закрепим основные определения:

    Освоив эту модель, вы перестаете мыслить в терминах "замкнуть реле, когда на входе X появится напряжение Y". Вместо этого вы начинаете проектировать на более высоком уровне абстракции: "Изменить состояние `climate.mode` на `heating`, когда произойдет событие `TEMPERATURE_TOO_LOW`". Это и есть профессиональный подход к автоматизации на платформе HI.

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

    >

    > - Физический сигнал (аналоговый/дискретный): Необработанная информация от датчика.

    > - Логическое событие: Осмысленное сообщение об изменении в системе.

    > - Состояние системы: Актуальный "снимок" параметров системы, хранящийся в памяти.

    > - Контекст Node-RED (global/flow): Механизм для хранения состояний.

    > - Нормализация сигнала: Преобразование сырых данных в реальные физические величины.

    > - Фильтрация дребезга (Debounce): Устранение ложных сигналов от механических контактов.

    > - АЦП (ADC): Аналого-цифровой преобразователь.

    > - Дискретный вход (DI): Вход для определения двух состояний (замкнуто/разомкнуто).

    Что дальше?

    В следующем уроке мы углубимся в практические аспекты работы с аналоговыми сигналами. Мы рассмотрим различные типы датчиков (NTC, Pt1000, 0-10В, 4-20мА), изучим типовые схемы их подключения к универсальным входам контроллера HI и разберем более сложные примеры нормализации и калибровки в Node-RED.