使用modbus-serial库向Radioshuttle写寄存器无响应,求排查
Modbus TCP写入Radioshuttle设备无响应问题分析
问题代码
const ModbusRTU = require("modbus-serial"); const gatewayIpAddress = "XXX.XXX.XXX.XXX"; const tcpPort = 502; const unitId = 1; const storePallet = async (shuttle) => { console.log("Storepallet function"); console.log("ShuttleNumber: " + shuttle); const client = new ModbusRTU(); try { await client.connectTCP(gatewayIpAddress, { port: tcpPort }); console.log("Connected to Radioshuttle device over Modbus TCP"); // Write store request await client.setID(unitId); await client.writeRegister(0, 1); // Address 0 represents tag #4 BIT 02.0.1 console.log("Pallet stored successfully"); client.close(); } catch (error) { console.error("Error storing pallet:", error); client.close(); throw error; } }; storePallet(1).catch((error) => { // Handle the error here console.error("Unhandled error:", error); });
设备文档关键信息
连接的Modbus TCP客户端(主站)设置
常规设置
RS网关IP地址:XXX.XXX.XXX.XXX
TCP端口:502
单元ID/从站地址:1
写入Radioshuttle输入数据
功能码:16 – 写入多个寄存器
写入数据起始地址:1
写入数据长度:5寄存器 - RS输入标签对应Register 1和2,存储请求相关信息如下:
Tag # Format Address Name 4 BIT 002.0.1 Store request 描述:由MCS设为1以启动将托盘存入货架的命令;当RS回复RS输出标签#5设为1时,由MCS设为0。
错误点分析
- 功能码不匹配:设备要求写入使用功能码16(写入多个寄存器),但代码中使用
writeRegister方法,对应Modbus功能码06(写入单个寄存器),不符合设备通信规范。 - 寄存器地址错误:文档中Store request的地址是
002.0.1,其中002是1-based的寄存器地址,对应modbus-serial库中0-based的地址为1(库的寄存器地址从0开始计数);而代码中写的地址0对应的是文档里的Register 1,完全不对。 - 位操作逻辑错误:Store request是寄存器中的单个BIT(第1位,文档中位编号从1开始),不能直接将整个寄存器值设为1,这样会覆盖该寄存器的其他位数据,导致设备无法正确识别命令。正确做法是先读取寄存器当前值,仅将目标位设为1,再写回寄存器。
- 未遵循写入长度要求:设备要求写入起始地址1、长度5的寄存器组,即使只需要修改其中一个位,也需要按照设备要求的长度构造写入数据(保持其他寄存器原有值不变)。
修正后的代码
const ModbusRTU = require("modbus-serial"); const gatewayIpAddress = "XXX.XXX.XXX.XXX"; const tcpPort = 502; const unitId = 1; const WRITE_START_ADDR = 0; // 对应文档中1-based起始地址1,转换为0-based const WRITE_LENGTH = 5; // 文档要求的写入长度 const STORE_REQUEST_REG_INDEX = 1; // 对应文档中002寄存器(1-based),0-based索引为1 const STORE_REQUEST_BIT = 1; // 文档中BIT 02.0.1,位编号从1开始 const storePallet = async (shuttle) => { console.log("Storepallet function"); console.log("ShuttleNumber: " + shuttle); const client = new ModbusRTU(); try { await client.connectTCP(gatewayIpAddress, { port: tcpPort }); console.log("Connected to Radioshuttle device over Modbus TCP"); await client.setID(unitId); // 1. 读取当前的输入寄存器组(5个寄存器) const response = await client.readInputRegisters(WRITE_START_ADDR, WRITE_LENGTH); const currentRegisters = response.data; // 2. 修改目标寄存器的对应位:将Store request位设为1 const bitMask = 1 << (STORE_REQUEST_BIT - 1); // 转换为0-based位的掩码 currentRegisters[STORE_REQUEST_REG_INDEX] |= bitMask; // 仅将目标位设为1,其他位保留 // 3. 使用功能码16写入多个寄存器(对应writeRegisters方法) await client.writeRegisters(WRITE_START_ADDR, currentRegisters); console.log("Store request sent successfully"); // 可选:轮询设备响应,确认完成后将Store request位设为0 // let isCompleted = false; // while (!isCompleted) { // const outputResponse = await client.readInputRegisters(0, 10); // 文档中读取起始地址1(0-based为0),长度10 // // 根据文档找到输出标签#5对应的寄存器位,判断是否完成 // // isCompleted = /* 检查对应位是否为1 */; // await new Promise(resolve => setTimeout(resolve, 1000)); // } // // 将Store request位重置为0 // currentRegisters[STORE_REQUEST_REG_INDEX] &= ~bitMask; // await client.writeRegisters(WRITE_START_ADDR, currentRegisters); // console.log("Store request reset to 0"); client.close(); } catch (error) { console.error("Error storing pallet:", error); if (client.isOpen) { client.close(); } throw error; } }; storePallet(1).catch((error) => { console.error("Unhandled error:", error); });
修正说明
- 功能码修正:使用
writeRegisters方法对应Modbus功能码16,完全符合设备要求。 - 地址修正:将文档中的1-based地址转换为库的0-based地址,确保操作到正确的寄存器。
- 位操作修正:通过读取原有寄存器值,仅修改目标位,避免覆盖其他关键配置数据。
- 遵循写入长度:按照设备要求写入5个寄存器,保持其他寄存器值不变,确保通信格式与设备预期一致。
内容的提问来源于stack exchange,提问作者Deesak
相关产品推荐
相关产品推荐

