Arduino开发板作为Modbus主设备,可以读取或改写其他Modbus从设备的数据
Arduino开发板作为Modbus主设备,可以读取或改写其他Modbus从设备的数据,可作为釆集数据的中转站或显示设备用,仅提供软件代码和
用Arduino当Modbus主站,说白了就是让这块小开发板当数据指挥官——把温湿度传感器、智能电表、PLC这些从站设备的数据捞过来,要么自己接个LCD显示,要么转发给上位机当中转站,甚至还能反过来给从站发指令改参数,玩法直接拉满。
Arduino开发板作为Modbus主设备,可以读取或改写其他Modbus从设备的数据,可作为釆集数据的中转站或显示设备用,仅提供软件代码和
先上核心代码,后面碎碎念关键细节:
#include <ModbusRTU.h> // 定义Modbus主站用的串口(这里用Serial2避免占用调试用的Serial0) ModbusRTU modbusClient; // 从站配置:根据你的实际设备改! #define SLAVE_ADDR 1 // 从站地址,别和其他设备撞了 #define TEMP_REG 0 // 温度值存在从站的0号保持寄存器 #define HUMI_REG 1 // 湿度值存在1号保持寄存器 #define CONTROL_REG 10 // 用来控制从站继电器的寄存器 void setup() { // 调试串口打开,方便看数据 Serial.begin(115200); // Modbus主站串口初始化:波特率9600,8N1标准格式(必须和从站一致!) modbusClient.begin(9600, SERIAL_8N1, Serial2); delay(100); Serial.println("Arduino Modbus 主站已上线!"); } void loop() { // 第一步:读取从站的温湿度寄存器(2个寄存器:0和1) uint8_t readStatus = modbusClient.readHoldingRegisters(SLAVE_ADDR, TEMP_REG, 2); if (readStatus == modbusClient.ku8MBSuccess) { // 从返回的数据包里抠出寄存器值 float temperature = modbusClient.getResponseBuffer(0) / 10.0; // 假设从站存的是放大10倍的整数 float humidity = modbusClient.getResponseBuffer(1) / 10.0; Serial.print("读取成功 | 温度: "); Serial.print(temperature); Serial.print("℃ | 湿度: "); Serial.print(humidity); Serial.println("%"); } else { Serial.print("读取失败,错误码: "); Serial.println(readStatus); } // 第二步:每隔5秒给从站写一次控制指令(比如切换继电器状态) static unsigned long lastWriteTime = 0; if (millis() - lastWriteTime > 5000) { lastWriteTime = millis(); // 生成一个0/1的切换值,模拟开关控制 static uint16_t ctrlValue = 0; ctrlValue = !ctrlValue; uint8_t writeStatus = modbusClient.writeSingleRegister(SLAVE_ADDR, CONTROL_REG, ctrlValue); if (writeStatus == modbusClient.ku8MBSuccess) { Serial.print("写入成功!控制寄存器设为: "); Serial.println(ctrlValue); } else { Serial.print("写入失败,错误码: "); Serial.println(writeStatus); } } delay(1000); // 每秒读一次数据,别太急 }碎碎念时间:
- 串口选择:为什么用Serial2而不是默认的Serial?因为Serial0要留给电脑调试打印用啊!不然你一边发Modbus指令一边打调试信息,串口数据就乱成粥了。要是你用的是Nano这种只有一组硬件串口的板子,那只能把调试信息关了,或者用软件串口库模拟一个。
- 指令踩坑点:
- 从站地址必须和设备一致!比如你买的温湿度模块地址设的是2,这里SLAVE_ADDR就得改成2,不然主站喊破喉咙也没人理。
- 波特率、数据位、停止位必须和从站严丝合缝!Modbus RTU默认8N1(8数据位、无校验、1停止位),波特率常用9600/19200,瞎改的话就是鸡同鸭讲。
- 数据解析:
modbusClient.getResponseBuffer(0)这句话就是从返回的数据包里把第一个寄存器的值抠出来。为啥要除以10?因为很多传感器会把小数放大10倍存成整数(比如25.3℃存成253),防止浮点传输出问题,读回来再缩回去就行,灵活调整。
- 写入逻辑:这里写的是单个保持寄存器,要是想写多个,用
writeMultipleRegisters就行。比如给PLC批量写参数,一次传好几个值,效率更高。
实际玩法拓展:
- 数据中转站:把读取到的温湿度值通过WiFi模块(比如ESP8266)上传到阿里云/腾讯云,Arduino就成了现场设备和云端的桥梁。
- 本地显示:接个I2C OLED屏,把
temperature和humidity丢到屏幕上,不用连电脑也能看数据。 - 联动控制:比如读到温度超过30℃,就给控制寄存器写1,触发从站的继电器开风扇,完美实现闭环控制。
最后提一嘴:要是调试的时候一直读不到数据,先把主站和从站用USB转TTL接电脑,用串口助手发指令试试,排除是硬件还是代码的问题——毕竟有时候不是代码错了,是杜邦线插反了啊喂!
