Integrating an RS485 Sensor with ESP32

Udara Kumarasena
4 min readMay 3, 2024

In this guide, we will explore how to connect an RS485 sensor, the XY-MD02, to an ESP32 microcontroller using an MAX485 module. We’ll go through the necessary components, wiring setup, and the code required to get temperature readings from the sensor.

What You Need

Wiring

Please follow the following wiring diagram,

Code

Here is the complete code I used.


#include <ModbusMaster.h>

#define MAX485_DE 32
#define MAX485_RE_NEG 33

#define RXD2 16
#define TXD2 17

ModbusMaster node;

void preTransmission()
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}

void setup() {
Serial.begin(9600);
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);

Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
node.begin(3, Serial2); // Modbus slave ID 3 for XY-MD02
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}

void loop() {
uint8_t result = node.readInputRegisters(0x0001, 1); // Read one register
if (result == node.ku8MBSuccess) {
int temperature = node.getResponseBuffer(0); // First buffer index holds the temperature
Serial.print("Temp: ");
Serial.print(temperature);
Serial.println(" C");
}
delay(2000); // Delay between readings
}

Detailed Code Explanation

#include <ModbusMaster.h>

This line includes the ModbusMaster library, which facilitates the communication between the ESP32 and Modbus devices using the RS485 standard. This library provides methods for sending and receiving data over the Modbus protocol. You can download the library through the Google Drive link.

#define MAX485_DE      32
#define MAX485_RE_NEG 33
#define RXD2 16
#define TXD2 17

The above definitions assign names to the GPIO numbers. ‘MAX485_DE’ and ‘MAX485_RE_NEG’ control the transmission and reception modes of the MAX485 chip, while ‘RXD2’ and ‘TXD2’ are used for UART communication on ESP32’s second serial port.

void preTransmission()
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
  • preTransmission: Activates the MAX485 module to transmit mode by setting the DE and RE pins high. This function is called automatically by the Modbus master library before sending any data.
  • postTransmission: Deactivates the transmit mode by setting the DE and RE pins low, switching the MAX485 to receive mode. This function is called right after data transmission is complete.
void setup() {
Serial.begin(9600);
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);

Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
node.begin(1, Serial2);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
  • Serial Communication: Initializes the default serial port for debugging and messages at 9600 bps.
  • Pin Modes: Sets the pins connected to the MAX485 module as outputs and initializes them to a low state, ensuring the module starts in receive mode.
  • Serial2 Communication: Configures the second serial port for Modbus communication with the sensor, using the pins defined for RXD2 and TXD2.
  • Modbus Initialization: Initializes the Modbus communication on ‘Serial2’, setting the sensor’s slave ID(Device Address) to 1. It is in the datasheet of the sensor.
void loop() {
uint8_t result = node.readInputRegisters(0x0001, 1);
if (result == node.ku8MBSuccess) {
int temperature = node.getResponseBuffer(0);
Serial.print("Temp: ");
Serial.print(temperature);
Serial.println(" C");
}

uint8_t result = node.readInputRegisters(0x0002, 1);
if (result == node.ku8MBSuccess) {
int temperature = node.getResponseBuffer(0);
Serial.print("Humidity: ");
Serial.print(temperature);
Serial.println(" %");
}
delay(2000);
}
  • The above piece of code deals with getting temperature and humidity readings.
  • Use “readInputRegisters” to function code 0x04 and “readHoldingRegisters” to function code 0x03.
  • For reading the temperature the register address is 0x0001 and for reading the humidity the register address address 0x0002.
  • In “node.readInputRegisters(0x0002, 1);”, “1” refers to the no of bytes we request for that particular address. It is given in the datasheet as “Quantity Hi” and “Quantity Li”.
  • In the line “int temperature = node.getResponseBuffer(0);” it reads the 1st byte by refering to “0”. If you requested 2 bytes earlier, you can use “1” to read the 2nd byte.

Contact us for any consultations or projects related to any RS485 sensor.

Protonest for more details.

Protonest specializes in transforming IoT ideas into reality. We offer prototyping services from concept to completion. Our commitment ensures that your visionary IoT concepts become tangible, innovative, and advanced prototypes.

Our Website: https://www.protonest.co/

Email: udara@protonest.co

If you enjoyed this article and would like to show some support, consider buying me a coffee on Ko-Fi.

Your support not only helps me keep creating content like this but also fuels me! ☕️📚

Thank you for being an amazing reader!

Here’s my Ko-Fi link: https://ko-fi.com/udarakumarasena

Cheers!

--

--

Udara Kumarasena

I am a Sri Lankan who is passionate about using technology for a sustainable future.