Датчики температуры в теплице на Modbus RTU
Беспроводные датчики соблазнительны, пока не выясняется, что в теплице из стекла и мокрого металла они теряют связь, а батарейки садятся в мороз. Проводная шина RS-485 с протоколом Modbus RTU скучнее, зато работает годами. Рассказываем, как мы её строим.
Почему RS-485 и Modbus
- Расстояние. На скорости 9600 бит/с шина надёжно работает на длине до 1200 м — хватает на ряд теплиц.
- Помехоустойчивость. Дифференциальная пара «A/B» мало чувствительна к наводкам от насосов и вентиляторов.
- Простота. Одна витая пара плюс общий провод, до 32 стандартных устройств на сегмент (до 256 с приёмопередатчиками на 1/8 нагрузки).
- Выбор датчиков. Датчики температуры и влажности воздуха, почвы, CO₂, освещённости с Modbus RTU выпускают десятки производителей, они взаимозаменяемы.
Modbus RTU — протокол «вопрос — ответ»: ведущее устройство (у нас это маленький Linux-сервер или контроллер) по очереди спрашивает каждый датчик по адресу, датчик отвечает значениями регистров. Сами датчики никогда не говорят первыми, поэтому коллизий на шине нет.
Топология: линия, а не звезда
Главное правило, которое нарушают чаще всего: RS-485 — это линия. Кабель идёт от ведущего устройства к первому датчику, от него ко второму и так далее. Отводы от магистрали к датчику — как можно короче, в пределах полуметра. «Звезда» из щита, где к каждому датчику идёт свой кабель, на 9600 бит/с иногда работает, но начинает сбоить при добавлении устройств и в сырую погоду.
- Терминаторы — резисторы 120 Ом между A и B, ровно два: на самом первом и самом последнем устройстве линии. У многих датчиков и адаптеров они включаются перемычкой; на промежуточных устройствах перемычки должны быть сняты.
- Подтяжка (bias) — резисторы, которые держат линию в определённом состоянии, когда никто не передаёт. Обычно они уже есть в адаптере ведущего устройства; если нет, без них шина «ловит» мусор между запросами.
- Общий провод. «RS-485 — это два провода» — миф. Без общего провода разница потенциалов между землёй щита и землёй дальнего датчика легко выходит за допустимый диапазон, особенно рядом с насосами.
- Кабель — экранированная витая пара для интерфейсов (например, 2×2×0,5: одна пара на A/B, вторая на питание и общий). Экран заземляется в одной точке, у щита.
Монтаж в теплице
Теплица — агрессивная среда: влажность под 100 %, конденсат, удобрения, перепады от −25 °C зимней ночью до +45 °C летним днём. Что мы делаем всегда:
- Датчик воздуха — в радиационном экране (жалюзийный колпак), иначе солнце покажет вам +38 °C при реальных +27.
- Высота — на уровне растений, а не у конька крыши; не ближе метра от труб отопления и форсунок туманообразования.
- Соединения — только в распаечных коробках IP65 с кабельными вводами; кабель заводится снизу с петлёй, чтобы вода стекала мимо ввода.
- Каждая теплица — отдельный сегмент шины через изолированный повторитель. Наводка или короткое замыкание в одной теплице не кладёт остальные.
- На кабелях между зданиями — защита от импульсных перенапряжений с обеих сторон.
- Раз в сезон — сверка с поверенным эталонным термометром. Ёмкостные датчики влажности в теплицах «плывут» на 2–5 % в год.
Адреса и регистры
У каждого устройства на шине — уникальный адрес от 1 до 247. Новые датчики почти всегда приходят с адресом 1, поэтому адреса назначаем на столе, подключая датчики по одному. Как именно меняется адрес, описано в документации датчика: обычно это запись в специальный регистр. Наклейку с адресом — на корпус и в схему.
Данные датчика лежат в регистрах — 16-битных ячейках. Типичная карта регистров недорогого датчика температуры и влажности выглядит так:
| Регистр | Функция | Значение | Пример |
|---|---|---|---|
0x0000 | 03, чтение | Влажность × 10, % | 712 → 71,2 % |
0x0001 | 03, чтение | Температура × 10, °C, со знаком | 65 486 → −5,0 °C |
0x07D0 | 06, запись | Адрес устройства | 1…247 |
0x07D1 | 06, запись | Скорость: 0 — 2400, 1 — 4800, 2 — 9600 | 2 |
Обратите внимание на температуру: отрицательные значения передаются в дополнительном коде, и «сырое» 65 486 означает 65 486 − 65 536 = −50, то есть −5,0 °C. Если опрашивающая программа читает регистр как беззнаковый, первым морозом вы получите +6548,6 °C и ложную тревогу о пожаре.
Адреса регистров и коды функций у разных производителей разные; одни используют функцию 03 (holding registers), другие — 04 (input registers). Таблица выше — пример, а не стандарт. Всегда сверяйтесь с паспортом датчика.
Опрос с Linux
Для проверки на месте удобна консольная утилита mbpoll. Прочитать два регистра начиная с первого у датчика с адресом 3:
mbpoll -m rtu -b 9600 -P none -d 8 -s 1 \
-a 3 -t 4 -r 1 -c 2 -1 /dev/ttyUSB0
# -t 4 — holding registers (функция 03), -r 1 — нумерация с единицы,
# -c 2 — два регистра, -1 — один опрос и выход
-- Polling slave 3...
[1]: 712
[2]: 246
Для постоянного опроса мы пишем небольшую службу на Python с библиотекой minimalmodbus. Она опрашивает все датчики раз в 15 секунд и складывает результат в файл для textfile-коллектора node_exporter — дальше значения попадают в Prometheus, графики и тревоги.
#!/usr/bin/env python3
# /opt/greenhouse/poll.py
import os, time, minimalmodbus
PORT = "/dev/ttyUSB0"
OUT = "/var/lib/node_exporter/textfile/greenhouse.prom"
SENSORS = {1: "t1_west", 2: "t1_center", 3: "t1_east", 4: "t2_west"}
def make(addr):
s = minimalmodbus.Instrument(PORT, addr)
s.serial.baudrate = 9600
s.serial.timeout = 0.3
s.clear_buffers_before_each_transaction = True
return s
devices = {addr: make(addr) for addr in SENSORS}
while True:
lines = []
for addr, name in SENSORS.items():
dev = devices[addr]
for attempt in range(3):
try:
hum = dev.read_register(0, 1, functioncode=3)
temp = dev.read_register(1, 1, functioncode=3, signed=True)
lines.append(f'greenhouse_temp_c{{sensor="{name}"}} {temp}')
lines.append(f'greenhouse_humidity{{sensor="{name}"}} {hum}')
lines.append(f'greenhouse_up{{sensor="{name}"}} 1')
break
except (IOError, ValueError):
time.sleep(0.1)
else:
lines.append(f'greenhouse_up{{sensor="{name}"}} 0')
tmp = OUT + ".tmp"
with open(tmp, "w") as f:
f.write("\n".join(lines) + "\n")
os.replace(tmp, OUT) # атомарная замена: коллектор не прочитает половину файла
time.sleep(15)
Обратите внимание на метрику greenhouse_up. Самая опасная ситуация — не «температура упала», а «датчик молчит, а на графике застыло последнее нормальное значение». Тревога на отсутствие данных так же важна, как тревога на мороз.
Сколько датчиков успеет опросить одна шина? На 9600 бит/с один байт передаётся около 1,15 мс. Запрос двух регистров — 8 байт, ответ — 9, плюс паузы и время реакции датчика: на практике 40–60 мс на устройство. Значит, 40 датчиков опрашиваются за 2–3 секунды — с огромным запасом для теплицы, где температура меняется за минуты.
Типичные неисправности
| Симптом | Частая причина | Что проверить |
|---|---|---|
| Датчик не отвечает совсем | Не тот адрес или скорость; перепутаны A и B | Подключить один датчик коротким кабелем; поменять A/B местами — обозначения у производителей не совпадают |
| Часть ответов с ошибкой CRC | Нет терминаторов или их больше двух; нет общего провода | Сопротивление между A и B на обесточенной шине: должно быть около 60 Ом |
| Сбои ночью или в дождь | Конденсат в распаечной коробке; кабель идёт рядом с силовым | Вскрыть коробки на линии, проверить вводы; развести кабели минимум на 20 см |
| Сбои при включении насосов | Наводки от частотного преобразователя | Заземление экрана в одной точке; изолированный повторитель на сегмент |
| Скачущие, «чужие» значения | Два устройства с одним адресом | Отключать датчики по одному и смотреть, какой пропадает |
Если хочется посмотреть, как это работает в реальном хозяйстве, — в кейсе про тепличное хозяйство в Зеленодольском районе описано, как такая шина трижды за зиму предупредила об остановке котла.