В предыдущей статье рассмотрел подключение бюджетного модуля RS485 к ESP8266. Фактически это чип MAX485 без защиты от напастей ну и стоит около 0,3 $ Лучше закупать оптом по 5 шт, так выгоднее, да и небольшая подстраховка на случай выгорания, поскольку защиты линии RS485 нет.

В промышленной эксплуатации лучше использовать ранее рассмотренные XY-485 или XY-017. Они более защищены от различных проблем, вроде удара молнии.
Плата ESP32 DevKit V1 широко распространена на Aliexpress по цене около 6 USD.
Схема соединения платы RS485 с ESP32 DevKit V1
На плате ESP32 DevKit V1 имеется три аппаратных UART порта
именуемые как U0UXD, U1UXD и U2UXD:
- U0UXD используется чипом преобразователя USB интерфейса платы ESP32 DevKit V1.
- U1UXD можно использовать для своих проектов. Некоторые платы используют этот порт на пине используемом под SPI Flash. Если не перенести на другой GPIO, то при обращении к этому пину программа выпадет в ошибку.
- U2UXD можно использовать для своих проектов.
На большинстве плат с ESP32 U0UXD занят для работы с конвертером USB интерфейса. Остается два свободных UART порта. Схема подключения ESP32 LuaNode32 к бюджетному модулю RS485 следующая:

В моем примере модуль RS485 интерфейса запитывается непосредственно от пина 3,3 В платы LuaNode32. Этот вариант рабочий. Если будете использовать отдельный блок питания для RS485 платы, то основная рекомендация:
Блок питания для модулей RS485 ДОЛЖЕН БЫТЬ на 3,3V,
иначе можно сжечь GPIO ESP32!!!
Либо используйте конвертер TTL уровней.
| ESP32 LuaNode32 | RS485 (MAX485 chipset) |
| Rx (PIN RX2, GPIO16) | RO (receiver output) |
| Tx (PIN TX2, GPIO17) | DI (driver input) |
| DE_RE (GPIO4, D4) | DE (driver enable) RE (receiver enable) |
| 3,3V | VCC (Блок питания +3,3V) |
| GND | GND |
DI (driver input) — цифровой вход передатчика;
RO (receiver output) — цифровой выход приемника;
DE (driver enable) — разрешение работы передатчика;
RE (receiver enable) — разрешение работы приемника;
Пины DE И RE закорачиваем.
| Термодатчик | RS485 (MAX485 chipset) |
| A+ | A+ |
| B- | B- |
| GND | GND |
| GND (Блок питания -) | |
| VCC (Блок питания +5V) |
ESP32 программа для работы с RS485 c DE/RE
#include "ModbusMaster.h" //https://github.com/4-20ma/ModbusMaster
/*!
We're using a MAX485-compatible RS485 Transceiver.
Rx/Tx is hooked up to the hardware serial port at 'Serial'.
The Data Enable (DE) and Receiver Enable (RE) pins are hooked up as follows:
*/
#define MAX485_RE_NEG 4 //D4 RS485 has a enable/disable pin to transmit or receive data. Arduino Digital Pin 2 = Rx/Tx 'Enable'; High to Transmit, Low to Receive
#define Slave_ID 1
#define RX_PIN 16 //RX2
#define TX_PIN 17 //TX2
// instantiate ModbusMaster object
ModbusMaster modbus;
void preTransmission()
{
digitalWrite(MAX485_RE_NEG, HIGH); //Switch to transmit data
}
void postTransmission()
{
digitalWrite(MAX485_RE_NEG, LOW); //Switch to receive data
}
void setup()
{
pinMode(MAX485_RE_NEG, OUTPUT);
// Init in receive mode
digitalWrite(MAX485_RE_NEG, LOW);
// Modbus communication runs at 9600 baud
Serial.begin(9600, SERIAL_8N1);
Serial2.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN);
modbus.begin(Slave_ID, Serial2);
// Callbacks allow us to configure the RS485 transceiver correctly
modbus.preTransmission(preTransmission);
modbus.postTransmission(postTransmission);
}
long lastMillis = 0;
void loop()
{
long currentMillis = millis();
if (currentMillis - lastMillis > 1000)
{
uint8_t result = modbus.readInputRegisters(0x01, 2);
if (getResultMsg(&modbus, result))
{
Serial.println();
double res_dbl = modbus.getResponseBuffer(0) / 10;
String res = "Temperature: " + String(res_dbl) + " C\r\n";
res_dbl = modbus.getResponseBuffer(1) / 10;
res += "Humidity: " + String(res_dbl) + " %";
Serial.println(res);
}
lastMillis = currentMillis;
}
}
bool getResultMsg(ModbusMaster *node, uint8_t result)
{
String tmpstr2 = "\r\n";
switch (result)
{
case node->ku8MBSuccess:
return true;
break;
case node->ku8MBIllegalFunction:
tmpstr2 += "Illegal Function";
break;
case node->ku8MBIllegalDataAddress:
tmpstr2 += "Illegal Data Address";
break;
case node->ku8MBIllegalDataValue:
tmpstr2 += "Illegal Data Value";
break;
case node->ku8MBSlaveDeviceFailure:
tmpstr2 += "Slave Device Failure";
break;
case node->ku8MBInvalidSlaveID:
tmpstr2 += "Invalid Slave ID";
break;
case node->ku8MBInvalidFunction:
tmpstr2 += "Invalid Function";
break;
case node->ku8MBResponseTimedOut:
tmpstr2 += "Response Timed Out";
break;
case node->ku8MBInvalidCRC:
tmpstr2 += "Invalid CRC";
break;
default:
tmpstr2 += "Unknown error: " + String(result);
break;
}
Serial.println(tmpstr2);
return false;
}