我正在努力阅读正确的modbus值。
这里有一些背景信息 我们建立了一个虚拟comport,它连接到现有的Commport-Server和ioLogik R1210 Model(https://www.moxa.com/support/sarch_result.aspx?prod_id=922&type_id=7&type=doc)。最后一个组件附加了一个自己的按钮,增加了ioLogik R1210模块的de DI /通道“0”中的计数器。我可以通过MOXA公司提供的ioSearch-Software看到这一点,它也生产ioLogik R1210模块。如果按下按钮,计数器也会增加。因此,硬件很好,从我的客户端到ioLogikModul通过已结算的虚拟comport连接 - 否则ioSearch将无法显示正确的计数器。
现在我正在尝试通过Java在Channel“0”中读取和写入计数器。我尝试了几个Modbus-Libraries,但总是遇到同样的问题,我不知道如何读取正确的寄存器/线圈/输入。
在以下用户手册和章节“ioLogik R1210 Modbus地址和寄存器映射”(页45或附录A-3)中给出了寄存器: https://www.moxa.com/doc/man/ioLogik_R1200_Series_UM_e3.3.pdf
虽然这条线听起来像是我需要阅读的一个寄存器: 0×0020; 30033; R等字; DI-00_counterValueHigh; 04:输入;注册;高位字
但是如果我尝试使用具有预期寄存器的ModbusClient-Library(https://sourceforge.net/projects/easymodbustcp-udp-java/),我得到一个奇怪的输出。
以下是我的一些代码:
package com.mg.moxa.modbus;
import java.io.IOException;
import de.re.easymodbus.exceptions.ModbusException;
import de.re.easymodbus.modbusclient.ModbusClient;
public class ModbusClientTest {
public static void main(final String[] args) {
modbusLibrary();
}
private static void modbusLibrary() {
final ModbusClient modbusClient = new ModbusClient();
try {
// modbusClient.Connect();
modbusClient.Connect("COM5");
// final int[] readHolding = modbusClient.ReadHoldingRegisters(0, 32);
// System.out.print("readHolding [");
// for (int i = 0; i < readHolding.length; i++) {
// System.out.print(readHolding[i] + ", ");
// }
// System.out.println("]");
final boolean[] readCoils = modbusClient.ReadCoils(32, 1);
System.out.print("readCoils [");
for (int i = 0; i < readCoils.length; i++) {
System.out.print(readCoils[i] + ", ");
}
System.out.println("]");
final int[] readInputRegisters = modbusClient.ReadInputRegisters(30033, 16); // high value
System.out.print("readInputRegisters [");
for (int i = 0; i < readInputRegisters.length; i++) {
System.out.print(readInputRegisters[i] + ", ");
}
System.out.println("]");
final int[] readInputRegistersLow = modbusClient.ReadInputRegisters(30033, 8); // low Value
System.out.print("readInputRegisters [");
for (int i = 0; i < readInputRegistersLow.length; i++) {
System.out.print(readInputRegistersLow[i] + ", ");
}
System.out.println("]");
//modbusClient.WriteSingleCoil(0, true);
// final boolean[] readDiscreteInputs = modbusClient.ReadDiscreteInputs(0, 32);
// System.out.print("readDiscreteInputs [");
// for (int i = 0; i < readDiscreteInputs.length; i++) {
// System.out.print(readDiscreteInputs[i] + ", ");
// }
// System.out.println("]");
modbusClient.Disconnect();
} catch (final ModbusException e) {
// TODO Auto-generated catch block
System.err.println("Fehler beim lesen des Modbus: " + e.toString());
e.printStackTrace();
} catch (final IOException e) {
// TODO Auto-generated catch block
System.err.println("Fehler beim lesen des Modbus: " + e.toString());
e.printStackTrace();
} catch (final Exception e) {
// TODO Auto-generated catch block
System.err.println("Fehler beim lesen des Modbus: " + e.toString());
e.printStackTrace();
}
}
}
此代码段的输出如下:
readCoils [false, ]
readInputRegisters [12031, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
readInputRegisters [12031, 0, 0, 0, 0, 0, 0, 0, ]
位置0处的输入寄存器值始终不同(如果有助于分析,则大多为-18180或12031)
我在这里做错了什么?我想我很想念正确阅读寄存器的方法。
是否有更好/更简单的方法来获取特定频道的反值。
我还需要用java重置计数器。很高兴能够设置频道的偏好。
我希望你能帮助我。
答案 0 :(得分:0)
尝试从“地址”列中的值而不是“注册”列中读取值。令人困惑,但在Modbus协议寄存器(输入,保持等)实际上是基于0(0 - 65535)。 0xxxx(线圈),1xxxx(离散输入),3xxxx(输入寄存器),4xxxx(保持寄存器)“寄存器”来自Modicon Modbus协议。 Modicon“寄存器”地址通常仍然在文档中使用,因为一些BMS系统期望这些值,但根据我的经验,它们通常需要更改为Modbus地址:
00001-09999 -> read coils 0-9998
10001-19999 -> read discrete inputs 0-9998
30001-39999 -> read input registers 0-9998
40001-49999 -> read holding registers 0-9998
如果您需要“DI-00_counterValueHigh”值,请尝试:
final int[] readInputRegisters = modbusClient.ReadInputRegisters(0x20, 1);
注意,这只给出了该计数器的高16位,以读取整个值,尝试:
final int[] readInputRegisters = modbusClient.ReadInputRegisters(0x20, 2);
这应该为您提供2个16位值,您需要通过执行以下操作将其组合成32位值(注意:我很长时间没有使用Java,因此语法可能不完全在C / C ++中,我会使用无符号值来防止符号扩展等。)
int counter = (readInputRegisters[0] << 16) | (readInputRegisters[1]);