Что такое сигнал: аналоговый vs дискретный
id: COURSE-01-M02-L01
title: "Что такое сигнал: аналоговый vs дискретный"
level: foundation
tags: [сигнал, аналоговый, дискретный, Node-RED, MQTT, датчик, сенсор, гистерезис, foundation]
prerequisites: [COURSE-01-M01]
version: 1.0.0
status: published
learning_outcomes:
- "Различать аналоговые и дискретные сигналы на примерах оборудования для умного дома."
- "Интерпретировать `msg.payload` из MQTT для обоих типов сигналов."
- "Создавать в Node-RED простейший сценарий преобразования аналогового сигнала в дискретное событие."
- "Объяснять необходимость использования гистерезиса при работе с аналоговыми пороговыми значениями."
key_concepts:
- "Сигнал"
- "Аналоговый сигнал"
- "Дискретный сигнал"
- "Порог (Threshold)"
- "Гистерезис"
- "Датчик (сенсор)"
- "Node-RED"
- "MQTT"
- "msg.payload"
## COURSE-01-M02-L01: Введение: Что такое сигнал в системах автоматизации?
В основе любой системы автоматизации лежит обмен информацией между её компонентами. Контроллер должен "понимать", что происходит в окружающем мире, и на основе этого отдавать команды исполнительным устройствам. Этот обмен информацией происходит посредством сигналов.
> 💡 Подсказка: Мысленно представляйте сигналы как нервную систему здания. Датчики — это рецепторы (глаза, кожа), которые воспринимают внешние воздействия. Провода и радиоэфир — нервные волокна, передающие импульсы. Контроллер — мозг, который анализирует эти импульсы и принимает решения. Исполнительные устройства (реле, приводы) — мышцы, выполняющие команды. Понимание природы этих "импульсов" — ключ к созданию стабильных и предсказуемых сценариев автоматизации.
📋 Ключевые понятия:
- Сигнал — это физическая величина (температура, влажность, освещенность, состояние контакта), преобразованная в электрическую форму (напряжение, ток, последовательность импульсов), пригодную для передачи, обработки и хранения контроллером.
- Датчик (сенсор) — устройство, которое измеряет физическую величину и преобразует ее в сигнал.
- Исполнительное устройство (актуатор) — устройство, которое получает сигнал от контроллера и производит физическое действие (включает свет, открывает клапан, изменяет скорость двигателя).
Для инженера по автоматизации критически важно понимать, что все сигналы делятся на два фундаментальных типа: аналоговые и дискретные. Это различие определяет, как мы подключаем датчики к универсальным входам контроллера, как мы интерпретируем данные, поступающие по MQTT, и, самое главное, какую логику мы выстраиваем в Node-RED для обработки этих данных. Неправильная интерпретация типа сигнала — одна из самых частых причин ошибок в сценариях автоматизации, приводящая к некорректной работе системы.
В этом уроке мы подробно разберем оба типа сигналов, научимся их идентифицировать в потоке данных контроллера и создадим практический сценарий, демонстрирующий работу с ними.
---
Аналоговые сигналы: непрерывный диапазон
Аналоговый сигнал — это сигнал, который может принимать любое значение в пределах заданного непрерывного диапазона. Подобно плавной регулировке громкости на аналоговом усилителе, такой сигнал не имеет резких скачков между фиксированными состояниями.
Представьте термометр. Температура может быть 23°C, 23.1°C, 23.11°C и так далее. Между любыми двумя значениями всегда можно найти бесконечное множество других. Это и есть суть аналоговой величины.
Примеры аналоговых сигналов в автоматизации зданий:
- Температура воздуха: Датчик 1-Wire, подключенный к универсальному входу контроллера, измеряет температуру в диапазоне, например, от -40 до +85 °C.
- Освещенность: Датчик освещенности выдает значение в люксах (лк), например, от 0 лк (полная темнота) до 2000 лк (яркий дневной свет). Это позволяет плавно регулировать искусственное освещение (диммировать).
- Уровень CO₂: Датчик качества воздуха, подключенный по шине Modbus RS-485, передает концентрацию углекислого газа в ppm (parts per million), например, в диапазоне 400–5000 ppm.
- Влажность: Гигрометр измеряет относительную влажность в процентах (%), например, от 0 до 100%.
- Положение диммера или сервопривода: Управляющий сигнал 0-10В для драйвера светильника или привода заслонки, где 0В — выключено, 10В — 100% мощности/открытия, а 5В — 50%.
В нашей платформе аналоговые сигналы от датчиков, подключенных к универсальным входам (например, 1-Wire) или по шинам данных (Modbus, CAN), преобразуются в цифровой вид с помощью АЦП (Аналого-цифрового преобразователя) и далее передаются по MQTT.
Контракт сообщения для аналогового сигнала (пример):
Когда датчик температуры 1-Wire, подключенный к контроллеру, измеряет температуру 24.5 °C, драйвер `wb-w1` публикует сообщение в MQTT. В Node-RED вы получите сообщение (`msg`), которое выглядит следующим образом:
json
{
"topic": "/devices/wb-w1/controls/28-00000578a1b2",
"payload": "24.5",
"qos": 0,
"retain": false,
"_msgid": "a1b2c3d4.e5f6g7"
}
Ключевые моменты для инженера:
`topic`: Указывает на источник данных. В нем содержится идентификатор устройства (в данном случае, уникальный адрес датчика 1-Wire `28-00000578a1b2`).
`payload`: Содержит само значение. Обратите внимание, что оно часто приходит в виде строки (`"24.5"`), а не числа (`24.5`). При обработке в Node-RED узел `switch` или `function` обычно автоматически преобразуют его в число, но для надежности иногда требуется явное преобразование.
---
Дискретные сигналы: конечный набор состояний
Дискретный (или цифровой) сигнал — это сигнал, который может принимать только одно из нескольких предопределенных, конечных значений. В подавляющем большинстве случаев в автоматизации зданий мы имеем дело с бинарными сигналами, у которых всего два состояния.
> 💡 Подсказка: В контексте Node-RED и многих языков программирования, дискретные сигналы часто представляются булевыми типами `true`/`false` или числами `1`/`0`, что значительно упрощает написание логических условий в узлах `switch` и `function`.
Представьте обычный выключатель света. У него есть только два положения: "Включено" и "Выключено". Третьего не дано. Это классический пример дискретного устройства.
Примеры дискретных сигналов в автоматизации зданий:
- Датчик движения: Сработал (есть движение) / Не сработал (нет движения).
- Датчик протечки воды: Сухо / Вода обнаружена.
- Кнопка выключателя: Нажата / Отпущена.
- Геркон (магнитоконтактный датчик): Дверь/окно закрыто (контакт замкнут) / Дверь/окно открыто (контакт разомкнут).
- Состояние реле контроллера: Включено (замкнуто) / Выключено (разомкнуто).
В нашей платформе такие датчики, как правило, подключаются к универсальным входам, настроенным в режим «сухой контакт». Контроллер отслеживает замыкание или размыкание внешней цепи и генерирует соответствующее MQTT-сообщение.
Контракт сообщения для дискретного сигнала (пример):
Когда на универсальный вход `A1_IN`, настроенный как «сухой контакт», подается сигнал (например, замыкается датчик протечки), драйвер `wb-gpio` публикует сообщение в MQTT. В Node-RED оно будет выглядеть так:
json
{
"topic": "/devices/wb-gpio/controls/A1_IN",
"payload": "1",
"qos": 0,
"retain": false,
"_msgid": "h8g7f6e5.d4c3b2"
}
Когда контакт размыкается, приходит сообщение с `payload: "0"`.
Ключевые моменты для инженера:
`topic`: Указывает на конкретный вход контроллера, например, `A1_IN`.
`payload`: Содержит `1` (событие произошло, контакт замкнут) или `0` (состояние покоя, контакт разомкнут). Эти значения легко проверяются в узле `switch`.
Понимание этого бинарного принципа позволяет строить простую и надежную логику: `ЕСЛИ msg.payload == 1 ТОГДА отправить команду на реле`.
---
Практика в Node-RED: Преобразование аналогового сигнала в дискретный
Одна из самых частых задач инженера — заставить систему реагировать на достижение аналоговым сигналом определенного порога (threshold). Например, включить вентиляцию, когда температура в помещении превысила 25 °C. В этот момент мы фактически преобразуем непрерывный аналоговый сигнал в дискретное событие: "температура выше нормы".
Задача: Создать flow в Node-RED, который включает реле вентиляции (выход `K5`), когда температура с датчика `28-00000578a1b2` становится выше 25 °C, и выключает, когда она опускается ниже этого порога.
Простое решение (неправильное):
Логика, казалось бы, проста. Мы можем использовать узел `switch` для проверки условия.
- Flow Diagram (ASCII):
[MQTT In: Температура] --> [Switch: t > 25?] --(1)--> [Function: ON] --> [MQTT Out: Реле K5]
|
+--(2)--> [Function: OFF]--> [MQTT Out: Реле K5]
Узел `switch` настраивается на `msg.payload > 25`. Если условие истинно, сообщение идет на первый выход; иначе — на второй.
Проблема «дребезга» (Flapping):
> ⚠️ Внимание: Игнорирование гистерезиса в реальных системах приводит к преждевременному износу исполнительных устройств (реле, контакторов), созданию паразитного сетевого трафика и снижению комфорта для пользователей. Всегда закладывайте гистерезис при работе с аналоговыми пороговыми значениями.
Представьте, что температура колеблется точно около нашего порога: 24.9 °C, 25.1 °C, 24.9 °C, 25.1 °C... Это приведет к тому, что реле вентиляции будет постоянно включаться и выключаться, создавая шум и быстро изнашиваясь. Такое поведение недопустимо.
Решение: Введение гистерезиса
Гистерезис — это создание "зоны нечувствительности" для предотвращения дребезга. Логика меняется:
- Включить вентиляцию, когда температура поднялась выше 25 °C.
- Выключить вентиляцию, когда температура опустилась ниже 24 °C.
Таким образом, между 24 °C и 25 °C система не меняет своего состояния. Этот диапазон в 1 градус и есть петля гистерезиса.
Реализация гистерезиса в Node-RED через узел `function`:
Это наиболее гибкий и надежный способ. Мы будем хранить текущее состояние вентилятора в контексте потока (`flow context`).
Flow Diagram (ASCII):
[MQTT In: Температура] --> [Function: Логика с гистерезисом] --(ВКЛ)--> [MQTT Out: Реле K5]
|
+-(ВЫКЛ)--> [MQTT Out: Реле K5]
Код для узла `function`:
javascript
// === НАСТРОЙКИ ===
const TEMP_HIGH = 25.0; // Порог включения
const TEMP_LOW = 24.0; // Порог выключения
// Получаем текущее значение температуры из payload
// Преобразуем в число (float) для корректного сравнения
let currentTemp = parseFloat(msg.payload);
// Проверка, что данные корректны
if (isNaN(currentTemp)) {
node.warn("Некорректное значение температуры: " + msg.payload);
return null; // Прекращаем обработку, если пришли не-числовые данные
}
// Получаем текущее состояние вентилятора из контекста потока.
// Если его нет, считаем, что он выключен (false).
let fanState = flow.get("fanState") || false;
// === ЛОГИКА ГИСТЕРЕЗИСА ===
let newState = fanState;
if (fanState === false && currentTemp >= TEMP_HIGH) {
// Вентилятор был выключен, и температура превысила верхний порог
newState = true; // Принимаем решение включить
} else if (fanState === true && currentTemp <= TEMP_LOW) {
// Вентилятор был включен, и температура упала ниже нижнего порога
newState = false; // Принимаем решение выключить
}
// Если состояние не изменилось, ничего не делаем
if (newState === fanState) {
return null; // Нет изменений, нет команд, нет лишнего трафика
}
// Состояние изменилось. Сохраняем новое состояние в контекст.
flow.set("fanState", newState);
// Формируем сообщение для реле
if (newState === true) {
msg.payload = "1"; // Команда на включение
} else {
msg.payload = "0"; // Команда на выключение
}
// Отправляем сообщение дальше в поток
return msg;
JSON для импорта Flow (скелет):
json
[
{
"id": "1",
"type": "mqtt in",
"name": "Температура в комнате",
"topic": "/devices/wb-w1/controls/28-00000578a1b2",
"broker": "YOUR_MQTT_BROKER_ID"
},
{
"id": "2",
"type": "function",
"name": "Логика с гистерезисом",
"func": "/ Вставьте код JS отсюда /",
"outputs": 1
},
{
"id": "3",
"type": "mqtt out",
"name": "Управление реле K5",
"topic": "/devices/wb-gpio/controls/K5/on",
"broker": "YOUR_MQTT_BROKER_ID"
},
{
"id": "4",
"type": "debug",
"name": "Статус команды"
}
]
Этот пример демонстрирует профессиональный подход: не простое сравнение, а надежная логика с обработкой состояний, валидацией данных и минимизацией лишних команд.
---
Итоги: Сводная таблица и выводы
Для закрепления материала сведем ключевые различия между аналоговыми и дискретными сигналами в одну таблицу.
| Параметр | Аналоговый сигнал | Дискретный сигнал |
| :--- | :--- | :--- |
| Природа | Непрерывный, плавно изменяющийся | Прерывистый, имеет конечный набор состояний |
| Кол-во состояний | Бесконечное множество в заданном диапазоне | Два (чаще всего) или несколько |
| Примеры датчиков | Датчик температуры, влажности, освещенности, CO₂ | Датчик движения, протечки, геркон, кнопка |
| Примеры `payload` | `"23.5"`, `"850.2"`, `"45"` | `"1"`, `"0"`, `"true"`, `"false"`, `"on"`, `"off"` |
| Основная задача в логике | Сравнение с порогом, анализ тренда, вычисление среднего | Проверка на равенство, логические операции (И/ИЛИ/НЕ) |
| Типичные узлы Node-RED | `switch` (сравнение >, <), `function`, `smooth`, `rbe` | `switch` (сравнение ==, !=), `trigger`, `function` |
Выводы:
Разделяй и властвуй: Четкое понимание, с каким типом сигнала вы работаете на каждом этапе сценария — аналоговым или дискретным — является основой для построения корректной и стабильной логики автоматизации.
Преобразование — ключевая операция: Многие сценарии строятся на преобразовании аналогового сигнала (например, температуры) в дискретное событие ("пора включать охлаждение").
Гистерезис — обязателен: При работе с аналоговыми порогами всегда используйте гистерезис для защиты оборудования и обеспечения комфорта.
> 🔗 Связанный материал: На аппаратном уровне преобразование сигналов выполняют АЦП (Аналого-цифровой преобразователь) и ЦАП (Цифро-аналоговый преобразователь). АЦП стоит на входе контроллера и "оцифровывает" непрерывный сигнал от датчика. ЦАП, наоборот, преобразует цифровую команду контроллера (например, 'установить яркость 50%') в аналоговый управляющий сигнал (например, 5 Вольт для драйвера 0-10В). Подробно аппаратную часть, включая АЦП и работу с raw-данными сенсоров, мы разбираем в продвинутом курсе: COURSE-04-M01-L02 'Работа с периферией микроконтроллеров'.
Что дальше?
Теперь, когда мы разобрались с фундаментальными типами сигналов, в следующем уроке мы рассмотрим, как эти сигналы превращаются в события и как контроллер управляет состояниями устройств.
➡️ Следующий урок: COURSE-01-M02-L02: События и состояния: как контроллер принимает решения