SimpleModbus 简介
SimpleModbus 是一套为 Arduino 平台개발的 Modbus RTU 프로토콜库,托管在 Google Code Archive(项目已被归档)。它由 Juan Bester 개발,包含 SimpleModbusMaster(마스터库)和 SimpleModbusSlave(슬레이브库)两个独立的 Arduino 库。虽然项目名称里有"Simple",但它提供的功能覆盖了 Modbus RTU 통신中最常用的기능 코드,非常适合 Arduino 初学者和快速原型개발。
⚠️ 注意:SimpleModbus 项目已不再活跃更新。对于新项目,推荐使用更现代化的 Modbus RTU for Arduino 库(库名为 "Modbus")或 esp-modbus(ESP32 平台)。但 SimpleModbus 的代码简洁易懂,作为학습 Modbus 프로토콜实现的入门자료仍然很有价值。
SimpleModbus 支持的功能
- SimpleModbusMaster:支持 FC01(读코일)、FC02(读이산 입력)、FC03(读유지 레지스터)、FC04(读입력 레지스터)、FC15(写多코일)、FC16(写多레지스터)
- SimpleModbusSlave:支持 FC03(读유지 레지스터)和 FC16(写多레지스터)
- 硬件要求:Arduino + RS-485 转换模块(如 MAX485)
硬件연결
Arduino 通过 MAX485 模块연결 RS-485 总线。典型배선방식:
| MAX485 引脚 | Arduino Uno | 설명 |
|---|---|---|
| VCC | 5V | 电源 |
| GND | GND | 地 |
| RO | RX (D0) | 수신데이터 → Arduino 시리얼 포트 RX |
| DI | TX (D1) | 보내기데이터 ← Arduino 시리얼 포트 TX |
| RE | D2 | 수신使能(低有效) |
| DE | D2 | 보내기使能(高有效),与 RE 并联到同一 IO |
| A | A (总线+) | RS-485 A 线(差分+) |
| B | B (总线-) | RS-485 B 线(差分-) |
⚠️ 在 RS-485 总线的两端必须加 120Ω 终端电阻(A-B 之间),否则长距离통신会出现信号反射导致데이터错误。
SimpleModbusSlave 예제:Arduino 作为 Modbus RTU 슬레이브
#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 예제:읽기슬레이브데이터
#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 现代替代方案
SimpleModbus 项目已经在数年前정지更新,现代 Arduino 项目推荐以下替代方案:
| 库名 | 平台 | 特点 |
|---|---|---|
| ArduinoModbus | Arduino(官方) | Arduino 官方维护,支持 RTU 和 TCP,Arduino IDE 库管理器一键安装 |
| Modbus-Master-Slave-for-Arduino | Arduino | 同时支持마스터和슬레이브,기능 코드覆盖全,GitHub 活跃更新 |
| esp-modbus | ESP32 / ESP8266 | Espressif 官方库,支持 Modbus RTU/TCP/ASCII,性能优异 |
| SimpleModbus | Arduino | 简单易懂,适合학습,但已停更 |
ESP32 上实现 Modbus RTU 통신(现代方案)
如果你使用 ESP32 平台,推荐 Espressif 官方的 esp-modbus 库。以下是一个最小예제:
// 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 官方 ArduinoModbus 库
在 Arduino IDE 中열기库管理器(Sketch → Include Library → Manage Libraries),검색 "ArduinoModbus",安装即可。ArduinoModbus 支持 Modbus RTU(RS-485)和 Modbus TCP(WiFi/以太网),마스터和슬레이브모드均可。
#include <ArduinoRS485.h>
#include <ArduinoModbus.h>
void setup() {
Serial.begin(9600);
// 初始化 RS-485
RS485.begin(9600);
// 启动 Modbus RTU 슬레이브(주소 1)
ModbusRTUServer.begin(1, 9600);
// 설정유지 레지스터
ModbusRTUServer.configureHolding회원가입s(0, 10);
}
void loop() {
// 轮询 Modbus 请求
ModbusRTUServer.poll();
// 更新레지스터 값
int sensorValue = analogRead(A0);
ModbusRTUServer.holding회원가입Write(0, sensorValue);
}
常见문제排查
통신完全没有响应
- 检查 MAX485 DE/RE 引脚的方向전환逻辑是否正确(보내기时 HIGH、수신时 LOW)
- 确认통신 속도和슬레이브 주소与마스터설정一致
- 用 USB 转 RS-485 模块 + 시리얼 포트助手监控总线데이터,确认信号是否存在
- 检查 A/B 线是否接反(用万用表测差分电压:A 对 B 应为正电压时总线空闲)
偶尔丢데이터或 CRC 错误
- 检查 RS-485 总线两端是否加了 120Ω 终端电阻
- 降低통신 속도尝试(4800 或 2400),排除信号完整性因素
- 缩短总线길이或加中继器
- 确认보내기完成到수신전환之间留有足够的延时(至少 1 个문자时间)
总结
SimpleModbus 作为早期 Arduino Modbus RTU 库,其代码简洁、功能明确,适合初学者理解 Modbus 프로토콜的实现원리。但在实际项目中,推荐使用维护更活跃、功能更完善的替代方案:Arduino 官方库 ArduinoModbus(通用 Arduino 平台)或 esp-modbus(ESP32/ESP8266 平台)。无论选择哪个库,核心的 Modbus RTU 통신원리——슬레이브 주소、기능 코드、레지스터 매핑、CRC 검증——都是一致的。
답글 작성