Introduction to SimpleModbus
SimpleModbus is a Modbus RTU protocol library developed for the Arduino platform, hosted onGoogle Code Archive(The project has been archived). It was developed by Juan Bester and includes two independent Arduino libraries, SimpleModbusMaster and SimpleModbusSlave. Although the project name includes "Simple", its features cover the most commonly used function codes in Modbus RTU communication, making it very suitable for Arduino beginners and rapid prototyping development.
⚠️Note: The SimpleModbus project is no longer active for updates. For new projects, it is recommended to use the more modernModbus RTU for Arduinolibrary (named "Modbus") oresp-modbus(ESP32 platform). But the code of SimpleModbus is concise and easy to understand, making it still valuable as an introductory material for learning Modbus protocol implementation.
Functions supported by SimpleModbus
- SimpleModbusMaster: Supports FC01 (read coil), FC02 (read discrete input), FC03 (read hold register), FC04 (read input register), FC15 (write multi coil), FC16 (write multi register)
- SimpleModbusSlave: Supports FC03 (read hold register) and FC16 (write multi register)
- Hardware Requirements: Arduino+RS-485 Conversion Module (such as MAX485)
Hardware Connections
Arduino is connected to the RS-485 bus through the MAX485 module. Typical wiring method:
| MAX485 pin | Arduino Uno | Description |
|---|---|---|
| VCC | 5V | Power |
| GND | GND | 地 |
| RO | RX (D0) | Receive data → Arduino serial port RX |
| DI | TX (D1) | Send data ← Arduino serial port TX |
| RE | D2 | Enable reception (low effectiveness) |
| DE | D2 | Enable sending (high efficiency), parallel with RE to the same IO |
| A | A (bus+) | RS-485 A line (differential+) |
| B | B (Bus -) | RS-485 B-line (differential -) |
⚠️ A 120 Ω terminal resistor (between A-B) must be added at both ends of the RS-485 bus, otherwise signal reflection may occur during long-distance communication, leading to data errors.
SimpleModbus Slave Example: Arduino as Modbus RTU Slave
#include <SimpleModbusSlave.h>
// 定义保持寄存器数组(10个寄存器)
enum {
TEMP_REG = 0, // 温度(x10)
HUMIDITY_REG, // 湿度(x10)
COIL_STATUS, // 线圈状态
SETPOINT, // 设定值
// ... 更多寄存器
TOTAL_REGS = 10
};
unsigned int holdingRegs[TOTAL_REGS];
void setup() {
// 设置 RS-485 方向控制引脚
pinMode(2, OUTPUT);
// SimpleModbusSlave 参数:
// 1. 寄存器数组地址
// 2. 寄存器数量
// 3. 发送使能引脚
// 4. 发送使能有效电平
// 5. 从站地址
// 6. 波特率
// 7. 校验(0=无校验)
modbus_configure(holdingRegs, TOTAL_REGS,
2, // TXEN 引脚
HIGH, // TXEN 高电平时发送
1, // 从站地址
9600, // 波特率
0); // 校验
}
void loop() {
// 更新传感器数据(模拟)
holdingRegs[TEMP_REG] = analogRead(A0) / 2; // 温度(模拟)
holdingRegs[HUMIDITY_REG] = analogRead(A1) / 3;
holdingRegs[COIL_STATUS] = digitalRead(3);
// 处理 Modbus 请求
modbus_update();
}SimpleModbusMaster Example: Reading Slave Data
#include <SimpleModbusMaster.h>
#define TOTAL_NO_OF_REGISTERS 2
unsigned int holdingRegs[TOTAL_NO_OF_REGISTERS];
void setup() {
Serial.begin(9600);
// SimpleModbusMaster 参数:
// 1. 本地寄存器数组
// 2. 读取/写入的寄存器数量
// 3. 发送使能引脚
// 4. 发送使能有效电平
modbus_configure(holdingRegs, TOTAL_NO_OF_REGISTERS,
2, // TXEN 引脚
HIGH); // TXEN 高电平时发送
}
void loop() {
// 从站地址 1,起始地址 0,读取 2 个保持寄存器
unsigned char result = modbus_read_holding_registers(1, 0, 2);
if (result == 0) {
Serial.print("温度: ");
Serial.print(holdingRegs[0] / 10.0);
Serial.print("°C, 湿度: ");
Serial.print(holdingRegs[1] / 10.0);
Serial.println("%");
} else {
Serial.print("Modbus 读取失败,错误码: ");
Serial.println(result);
}
delay(1000);
}SimpleModbus vs Modern Alternative Solutions
The SimpleModbus project stopped updating several years ago, and modern Arduino projects recommend the following alternative solutions:
| Library Name | Platform | characteristics |
|---|---|---|
| ArduinoModbus | Arduino (official) | Arduino official maintenance, supports RTU and TCP, one click installation of Arduino IDE library manager |
| Modbus-Master-Slave-for-Arduino | Arduino | Supports both master and slave stations, with full coverage of feature codes and active updates on GitHub |
| esp-modbus | ESP32 / ESP8266 | Espressif official library, supports Modbus RTU/TCP/ASCII, with excellent performance |
| SimpleModbus | Arduino | is simple and easy to understand, suitable for learning, but has stopped updating |
Implementing Modbus RTU Communication on ESP32 (Modern Solution)
If you are using the ESP32 platform, we recommend the official ESP modbus library from Espressif. Here is a minimal example:
// ESP32 使用 HardwareSerial + MAX485
#include <Arduino.h>
// 定义 RS-485 控制引脚
#define RXD2 16 // ESP32 RX2
#define TXD2 17 // ESP32 TX2
#define DE_RE 4 // RS-485 方向控制
HardwareSerial modbusSerial(2);
void setup() {
Serial.begin(115200);
modbusSerial.begin(9600, SERIAL_8N1, RXD2, TXD2);
pinMode(DE_RE, OUTPUT);
digitalWrite(DE_RE, LOW); // 默认接收模式
}
void loop() {
// 发送 Modbus RTU 请求(手动构造帧)
uint8_t request[] = {
0x01, // 从站地址
0x03, // 功能码(读保持寄存器)
0x00, 0x00, // 起始地址
0x00, 0x02 // 读取 2 个寄存器
};
uint16_t crc = calculateCRC(request, 6);
request[6] = crc & 0xFF;
request[7] = crc >> 8;
// 切换到发送模式
digitalWrite(DE_RE, HIGH);
delayMicroseconds(100);
modbusSerial.write(request, 8);
modbusSerial.flush();
// 切换回接收模式
digitalWrite(DE_RE, LOW);
// 等待响应
delay(500);
while (modbusSerial.available()) {
Serial.printf("%02X ", modbusSerial.read());
}
Serial.println();
delay(2000);
}Arduino Official Arduino Modbus Library
Open the Library Manager (Sketch → Include Library → Manage Libraries) in the Arduino IDE, search for"Arduino Modbus", and install it. Arduino Modbus supports Modbus RTU (RS-485) and Modbus TCP (WiFi/Ethernet), both in master and slave modes.
#include <ArduinoRS485.h>
#include <ArduinoModbus.h>
void setup() {
Serial.begin(9600);
// 初始化 RS-485
RS485.begin(9600);
// 启动 Modbus RTU 从站(地址 1)
ModbusRTUServer.begin(1, 9600);
// 配置保持寄存器
ModbusRTUServer.configureHoldingRegisters(0, 10);
}
void loop() {
// 轮询 Modbus 请求
ModbusRTUServer.poll();
// 更新寄存器值
int sensorValue = analogRead(A0);
ModbusRTUServer.holdingRegisterWrite(0, sensorValue);
}Common problem troubleshooting
Communication completely unresponsive
- Check if the direction switching logic of the MAX485 DE/RE pin is correct (HIGH when sending, LOW when receiving)
- Confirm that the baud rate and slave address are consistent with the master configuration
- Use USB to RS-485 module+serial port to manually monitor bus data and confirm if the signal exists
- Check if the A/B lines are reversed (use a multimeter to measure differential voltage: when A is positive for B, the bus is idle)
Occasionally losing data or CRC errors
- Check if a 120 Ω terminal resistor is added to both ends of the RS-485 bus
- Try to reduce the baud rate (4800 or 2400), eliminate signal integrity factors
- Shorten the bus length or add a repeater
- Confirm that there is sufficient delay (at least 1 character time) between sending and receiving switching
Summary
SimpleModbus, as an early Arduino Modbus RTU library, has simple code and clear functions, suitable for beginners to understand the implementation principle of the Modbus protocol. But in actual projects, it is recommended to use alternative solutions with more active maintenance and more complete functions: Arduino official library Arduino Modbus (universal Arduino platform) or ESP modbus (ESP32/ESP8266 platform). No matter which library is chosen, the core Modbus RTU communication principle - slave address, function code, register mapping, CRC check - is consistent.
Leave a Reply