Гайд · RS-485 · Modbus
Читаем промышленные датчики за 1200 м по RS-485 и Modbus RTU
I²C и обычный UART сдаются после метра-двух. Когда нужно дотянуться до датчика через сарай, котельную или цех — десятки узлов, сотни метров, электрические помехи — ответ это RS-485, а язык поверх него обычно Modbus RTU. Модуль MAX485 за доллар и ESP32 доведут тебя до цели.
RS-485 — не новый протокол, это тот же UART-кадр, просто пущенный по витой паре дифференциальными уровнями, как в CAN. Отсюда и дальнобойность, и стойкость к помехам. Если идея в новинку — сначала загляни в раздел RS-232 / RS-485 интерактивного разбора шин: там на осциллограмме видно, почему дифференциал бьёт однопроводный сигнал.
Почему RS-485, а не UART
- Дифференциальная пара (A/B) — помеха приходит в оба провода одинаково и вычитается. Десятки-сотни метров вместо сантиметров.
- Многоточечность — до 32 узлов (до 128 на современных трансиверах) на одной паре.
- Полудуплекс — все делят одну пару и говорят по очереди, поэтому трансиверу нужно явно сообщать, когда передавать, а когда слушать.
Подключение MAX485
MAX485 — это трансивер: с одной стороны UART, с другой — пара A/B шины RS-485. Единственный неочевидный вывод — направление: DE (driver enable) и RE (receiver enable) соединяют вместе и управляют одним GPIO — HIGH на передачу, LOW на приём.
Модуль MAX485 ESP32
----------- -----
RO (выход приёмника) --> RX (напр. GPIO16)
DI (вход передатчика) <- TX (напр. GPIO17)
DE + RE (соединены) <-- DIR (напр. GPIO4) // HIGH = передача, LOW = приём
VCC --> 5V (модуль) / есть варианты под 3V3-логику
GND --> GND
A / B --> витая пара на шину (120 Ом на двух дальних концах)
Два аппаратных правила, на которых спотыкаются все: поставь терминатор 120 Ом на двух дальних концах шины (не на каждом узле) и веди A→A, B→B по всей линии. На длинных или «тихих» шинах добавь резисторы смещения, чтобы в покое линия сидела на определённом уровне.
Modbus RTU на один экран
Modbus — простейший протокол «ведущий-ведомый»: ведущий спрашивает, один ведомый отвечает, каждый
кадр заканчивается CRC. В основном нужны две функции — 0x03 (чтение holding-регистров) и
0x04 (чтение input-регистров). Вот ESP32 читает два регистра у ведомого №1 библиотекой
ModbusMaster, автоматически дёргая пин направления:
#include <ModbusMaster.h>
#define DIR 4 // пин направления DE+RE
ModbusMaster node;
void preTx() { digitalWrite(DIR, HIGH); } // включить передатчик перед отправкой
void postTx() { digitalWrite(DIR, LOW); } // вернуться на приём после
void setup() {
pinMode(DIR, OUTPUT); digitalWrite(DIR, LOW);
Serial2.begin(9600, SERIAL_8N1, 16, 17); // UART для RS-485
node.begin(1, Serial2); // адрес ведомого 1
node.preTransmission(preTx);
node.postTransmission(postTx);
}
void loop() {
// Читаем 2 holding-регистра с адреса 0x0000 (функция 0x03)
if (node.readHoldingRegisters(0x0000, 2) == node.ku8MBSuccess) {
uint16_t temp = node.getResponseBuffer(0);
uint16_t hum = node.getResponseBuffer(1);
Serial.printf("temp=%u hum=%u\n", temp, hum);
}
delay(1000);
} Это весь паттерн: указал библиотеке свой UART, дал колбэки на пин направления и вызывай
readHoldingRegisters(). Карту регистров своего датчика подставь из его даташита.
Когда не работает — типовые подозреваемые
- Перепутаны A/B — баг RS-485 №1. Перевёрнутая пара даёт тишину или мусор; просто поменяй два провода местами.
- Нет терминаторов — 120 Ом ставятся на двух физических концах магистрали, не на каждом узле. Без них отражения ломают кадры на длинных линиях.
- Тайминг пина направления — отпустишь DE слишком рано и обрежешь собственный последний байт. Доверь это библиотеке или добавь крошечную задержку после последнего байта.
- Несовпадение скорости / чётности — все узлы должны согласиться:
9600 8N1против8E1— частый тихий сбой. - Нет общей земли / опоры — длинным изолированным линиям всё равно нужна опора по земле между трансиверами.
Сделай правильно пару, терминаторы и пин направления — и один ESP32 опросит целое здание Modbus-датчиков: счётчики энергии, температурные зонды, ПЛК — по одной витой паре.
Посмотри, как дифференциальная пара несёт байт там, где обычный UART не может.