How to Use Arduino with Modbus RTU Relay RS485/TTL 12V
How to Use Arduino with Modbus RTU Relay RS485/TTL 12V
This guide explains how to control a 1-channel Modbus RTU relay module using Arduino. The module supports both RS485 and TTL (Direct UART) interfaces, runs on 12V, and is suitable for Home Automation, Smart Farm, or small industrial control systems.
Why Use Modbus RTU Relay
Standard relay modules require multiple signal wires connected to each Arduino I/O pin. Using several relays becomes messy and uses up many pins quickly.
Modbus RTU works differently — only two wires (A+ and B-) connect to all relays on the same bus. Each relay has its own unique Address, so you can control dozens of them using just one serial port on your Arduino.
Required Components
- Arduino UNO R3
- MAX485 Module (RS485 to TTL converter)
- Modbus-RTU 1 Way Relay Module RS485/TTL 12V
- 12V 5A Power Adapter (for the relay module)
- 9V 2A Power Adapter (for Arduino)
- Breadboard MB-102 (830 points)
- Jumper wires: Male-Male, Male-Female, Female-Female (at least 20cm, 40 pieces)
- DC Jack female adapter 2.1 x 5.5mm
Wiring Diagram
Connect Arduino to MAX485 Module
| Arduino | MAX485 |
|---|---|
| 5V | VCC |
| GND | GND |
| 2 (RX) | RO |
| 3 (TX) | DI |
| 4 | DE / RE (tie both together) |
DE and RE must be tied together and connected to Arduino pin 4. This single digital pin controls both send and receive modes.
Connect MAX485 to Relay Module
| MAX485 | Relay Module |
|---|---|
| A | A+ |
| B | B- |
Connect Power and Load
- Supply 12V DC to the Relay Module (positive-negative terminals)
- AC Live (L) from the load power source connects directly to the load L terminal
- AC Neutral (N) from the load power source connects to NO on the Relay Module
- Load Neutral connects to COM on the Relay Module
Modbus RTU Command Basics
The Modbus relay communicates using hexadecimal values. Every command includes a 2-byte CRC checksum at the end for data integrity verification.
Common Commands
| Command | Function Code | Description |
|---|---|---|
| ON | 05h | Close the relay |
| OFF | 05h | Open the relay |
| Read Status | 01h | Get current relay state |
| Read ID | 03h | Read module’s Address |
The command frame format is [ID] [Function Code] [Address] [Data] [CRC High] [CRC Low]
Arduino Code for Modbus RTU Relay Control
#include <SoftwareSerial.h>
// Pin definitions
#define RO_PIN 2 // MAX485 RO (receive output)
#define DI_PIN 3 // MAX485 DI (drive input)
#define DE_RE_PIN 4 // MAX485 DE/RE control
SoftwareSerial modbusSerial(RO_PIN, DI_PIN);
// Default settings (adjust per your module)
byte relayID = 0x01; // Relay Address
unsigned long baudRate = 9600; // Module Baud Rate
void setup() {
Serial.begin(9600);
modbusSerial.begin(baudRate);
pinMode(DE_RE_PIN, OUTPUT);
// Start in receive mode
digitalWrite(DE_RE_PIN, LOW);
Serial.println("Modbus RTU Relay Ready");
}
// Send Modbus RTU command
void sendModbusCommand(byte id, byte functionCode, byte highAddr, byte lowAddr, byte highData, byte lowData) {
byte frame[8];
frame[0] = id;
frame[1] = functionCode;
frame[2] = highAddr;
frame[3] = lowAddr;
frame[4] = highData;
frame[5] = lowData;
// Calculate CRC16
unsigned int crc = calculateCRC(frame, 6);
frame[6] = highByte(crc);
frame[7] = lowByte(crc);
// Transmit (set DE/RE HIGH before sending)
digitalWrite(DE_RE_PIN, HIGH); // Enable transmitter
delay(1);
modbusSerial.write(frame, 8);
modbusSerial.flush();
digitalWrite(DE_RE_PIN, LOW); // Back to receive mode
}
// Turn relay ON
void relayOn(byte id) {
sendModbusCommand(id, 0x05, 0x00, 0x00, 0xFF, 0x00);
Serial.print("Relay ");
Serial.print(id, HEX);
Serial.println(" -> ON");
}
// Turn relay OFF
void relayOff(byte id) {
sendModbusCommand(id, 0x05, 0x00, 0x00, 0x00, 0x00);
Serial.print("Relay ");
Serial.print(id, HEX);
Serial.println(" -> OFF");
}
// Read relay status
bool readRelayStatus(byte id) {
sendModbusCommand(id, 0x01, 0x00, 0x00, 0x00, 0x01);
// Wait for response
delay(50);
if (modbusSerial.available() >= 5) {
byte response[5];
for (int i = 0; i < 5; i++) {
response[i] = modbusSerial.read();
}
// Verify CRC before using
if (verifyCRC(response, 5)) {
return response[3] == 0x01; // 0x01 = ON, 0x00 = OFF
}
}
return false;
}
// CRC16 calculation (Modbus variant)
unsigned int calculateCRC(byte *data, int length) {
unsigned int crc = 0xFFFF;
for (int i = 0; i < length; i++) {
crc ^= data[i];
for (int j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
// CRC verification
bool verifyCRC(byte *data, int length) {
unsigned int crc = calculateCRC(data, length - 2);
return (data[length - 2] == lowByte(crc) && data[length - 1] == highByte(crc));
}
void loop() {
// Relay ON for 2 seconds
relayOn(relayID);
delay(2000);
// Relay OFF for 2 seconds
relayOff(relayID);
delay(2000);
// Manual status check (type 'r' or 'R' in Serial Monitor)
if (Serial.available()) {
char cmd = Serial.read();
if (cmd == 'r' || cmd == 'R') {
bool status = readRelayStatus(relayID);
Serial.print("Relay Status: ");
Serial.println(status ? "ON" : "OFF");
}
}
}
Points to adjust for your actual module:
relayID— change to match your module’s Address (default is often 0x01)baudRate— must match the value set on the module (9600 is common)- If your module uses Function Code 0x06 for Write Single Register instead of 0x05, update the
sendModbusCommandfunction accordingly
Setting Address and Baud Rate
When using multiple relays on the same bus, each must have a unique Address (range 0x01 to 0xFF), and all must share the same Baud Rate. Common Baud Rates are 2400, 4800, 9600, and 19200 bps.
To change Address or Baud Rate, send a Write Register command via Modbus RTU to the module’s configuration registers. Refer to your specific module’s documentation for register addresses.
Using with ESP32 / ESP8266
For ESP32 or ESP8266 instead of Arduino UNO, you can use Hardware Serial instead of SoftwareSerial, which is faster and more reliable. Adjust pin connections to match your board’s hardware UART pins and replace the SoftwareSerial usage with Serial2 or Serial1.
Reference Video
https://www.youtube.com/embed/Ljv46KAmBA8
Summary
Using Arduino to control a Modbus RTU relay over RS485 is a reliable way to switch high-voltage devices from a distance. The key hardware requirement is the MAX485 module as a signal converter. On the software side, correct CRC calculation is essential for the module to respond.
อยากทำโปรเจคแบบนี้?
รับทำโปรเจค Arduino / IoT จบงานไว ส่งงานครบ พร้อมสอน
If you need Arduino project service or urgent IoT development, see full service details on the home page
จ้างทำโปรเจคเลย