来自ioLogik R1210的Modbus读取计数器通过Java ModbusClient-Library

时间:2018-04-24 08:59:51

标签: java serial-port modbus rs485

我正在努力阅读正确的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重置计数器。很高兴能够设置频道的偏好。

我希望你能帮助我。

1 个答案:

答案 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]);