กลับหน้าหลัก
views
How to Use Arduino with Modbus RTU Relay RS485/TTL 12V
Last updated on

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.

Full circuit diagram showing Arduino + MAX485 + Modbus Relay 1 channel + 12V power supply + load

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

Detailed wiring between Arduino and MAX485 module showing RO, DI, DE, RE pin assignments

Connect Arduino to MAX485 Module

ArduinoMAX485
5VVCC
GNDGND
2 (RX)RO
3 (TX)DI
4DE / 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

MAX485Relay Module
AA+
BB-

Connect Power and Load

  1. Supply 12V DC to the Relay Module (positive-negative terminals)
  2. AC Live (L) from the load power source connects directly to the load L terminal
  3. AC Neutral (N) from the load power source connects to NO on the Relay Module
  4. Load Neutral connects to COM on the Relay Module
Power wiring for 12V supply to relay and load connection showing NO COM NC terminals

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

CommandFunction CodeDescription
ON05hClose the relay
OFF05hOpen the relay
Read Status01hGet current relay state
Read ID03hRead 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 sendModbusCommand function 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

จ้างทำโปรเจคเลย

ความคิดเห็น