Introduction
Hello everyone, today I’m excited to share the process of setting up RS-485 communication using ESP32-S3. This is a key part of my project to create a wireless node sensor for measuring tunnel structure displacements. However, in this article, I’ll guide you through the process of establishing RS-485 communication between two ESP32-S3 devices: one as the master and the other as the slave. This configuration enables seamless data exchange between the devices, making it valuable for various applications.
The Hardware
The hardware for this project comprises two ESP32-S3 devices (Get them here), with both equipped with RS-485 communication capabilities using a straightforward TTL-RS485 module (Available here). One of these devices serves as the master, while the other assumes the role of the slave. In this setup, the master initiates requests to the slave, and the slave promptly responds with the requested data.
Wiring
Below is a simple schematic for the wiring:

Codes
The testing codes are available on my Github here
Code for the Slave:
#include <ModbusRTU.h>
#define RXD1 17
#define TXD1 18
#define SLAVE_ID 1 // Modbus Slave ID
#define REGN 1
const int analogPin = A0;
ModbusRTU mb;
void setup() {
Serial.begin(9600, SERIAL_8N1);
Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1); // Start the Serial1 communication
mb.begin(&Serial1);
mb.slave(SLAVE_ID); // Initialize the modbus slave device with ID 1
mb.addHreg(REGN); // Add a register with address 1
mb.Hreg(REGN, 100); // Assign a value of 100 to the local Holding Register #REGN (for testing)
}
void loop() {
mb.task(); // Process incoming Modbus requests
// Read the analog value from the analog pin
uint16_t sensorValue = analogRead(analogPin);
// Update the holding register with the sensor value
mb.Hreg(REGN, sensorValue); // Store the value in holding register 0
delay(100); // Add a small delay for stability
yield();
}
Code for the Master:
#include <ModbusRTU.h>
#define SLAVE_ID 1
#define RXD1 17
#define TXD1 18
#define REGN 1
#define REG_COUNT 1
ModbusRTU mb;
bool cb(Modbus::ResultCode event, uint16_t transactionId, void* data) { // Callback to monitor errors
Serial.printf_P("Request result: 0x%02X, Mem: %d\n", event, ESP.getFreeHeap());
return true;
}
void setup() {
Serial.begin(9600);
Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1);
mb.begin(&Serial1);
mb.master();
}
void loop() {
uint16_t res[REG_COUNT];
if (!mb.slave()) { // Check if no transaction is in progress
mb.readHreg(SLAVE_ID, REGN, res, REG_COUNT, cb); // Send Read Hreg to the Modbus Server
while (mb.slave()) { // Check if a transaction is active
mb.task();
delay(10);
}
Serial.println(res[0]);
}
delay(1000);
}
Serial Monitor Output
Upon successful setup and execution of your RS-485 communication, you can monitor the communication through the serial monitor. Here’s a sample output to expect:

Conclusion
This project demonstrates how to establish RS-485 communication between ESP32-S3 devices. The master can initiate requests to the slave, and the slave responds with the requested data. This setup provides a foundation for various applications, from data logging to remote control. As with any embedded system, thorough testing and, if necessary, calibration are essential for precise measurements and reliable data exchange