使用Jamod编写Modbus通信协议

4

我在使用jamod写入modbus时遇到了一个奇怪的情况。以下读取代码完美地运行:

public static void main(String[] args) throws Exception {
   InetAddress address = InetAddress.getByName("host.somewhere");
   TCPMasterConnection connection = new TCPMasterConnection(address);
   connection.setPort(502);
   connection.connect();
   ReadMultipleRegistersRequest request = new ReadMultipleRegistersRequest(0, 1);
   ReadMultipleRegistersResponse response = (ReadMultipleRegistersResponse)
       executeTransaction(connection, request);
}

private static ModbusResponse executeTransaction(TCPMasterConnection connection,
         ModbusRequest request) 
         throws ModbusIOException, ModbusSlaveException, ModbusException {
   ModbusTCPTransaction transaction = new ModbusTCPTransaction(connection);
   transaction.setRequest(request);
   transaction.execute();
   return transaction.getResponse();
}

然而,试图以类似的方式编写却失败了(Jamod尝试了3次,每次遇到SocketTimeoutException,最终抛出了ModbusException)。

public static void main(String[] args) throws Exception {
    final InetAddress address = InetAddress.getByName("host.somewhere");
    final TCPMasterConnection connection = new TCPMasterConnection(address);
    connection.setPort(502);
    connection.connect();
    Register reg = new SimpleRegister(0);
    WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(0,
        new Register[]{reg});
    executeTransaction(connection, request);
}

是的,我知道我正在使用多寄存器版本的请求对象,但我正在使用的设备仅支持功能码3和16。

我还编写了原始套接字测试程序来写入寄存器,就我所见,它运行正常。但在这两种情况下使用jamod会更好。

有没有人有使用jamod的经验,并且能否告诉我我做错了什么?这在jamod的1.1和1.2rc1版本中都发生了。或者这可能是某个特定供应商的情况吗?


1
我首先会弄清楚这是一个jamod还是设备问题。你能否尝试用其他方式向设备写入数据? - kgiannakakis
是的,我能够做到。我编写了一个测试程序,使用tcp-socket向设备进行写入操作。在我的测试中,至少从套接字中读取到的已写入寄存器的值为最近写入的值。(而且我使用的是随机值,而不仅仅是零 :))。 - Ahe
5个回答

2

默认情况下,Modbus请求的单元ID为0。因此,必须设置任何其他ID以进行请求,例如:

WriteCoilRequest writeCoilRequest = new WriteCoilRequest(ref, bool);
writeCoilRequest.setUnitID(unitid);

我浪费了几个小时尝试解决你在问题中描述的同样的问题。


听起来很合理。但是我无法测试,希望这能帮到某些人。 - Ahe

1

最后我自己编写了一个modbus实现。我只需要支持两种不同的功能码,所以实现很简单。

虽然后来我发现了另一个开源的java modbus库。如果其他人遇到相同的问题,使用modbus4j可能会有所帮助。


我不得不在较旧的jamod版本上进行大量工作,以使其正常工作(现在是2012年...)。有一个更新的版本(所以如果你最近没有看过,请再去看看),可能更好地支持Modbus/TCP。 - Julie in Austin
3
最终,我感到非常沮丧,不得已在SourceForge上创建了“j2mod”来代替原先的“jamod”。这是一个大幅修订的版本,现在已经被我们公司用于设备出货。另外一个问题是,“jamod”并不支持大量的Modbus消息,因此我实现了能够找到的所有消息。如果你搜索“j2mod”,就可以在SourceForge上找到我的修改版。 - Julie in Austin

0

我曾经遇到过类似的问题,我试图在一个被定义为线圈寄存器的“设备作业”中写入一个值。所以我使用了:

WriteCoilRequest coil_req = new WriteCoilRequest(registerReference,value2write)

然后问题就解决了。也许这可以帮到你。

再见!


哇,对一个五年前的问题的回答。不过很抱歉,我无法测试您的解决方案,因为多年来我一直没有接触到相关设备。 - Ahe
2
我知道回答有点晚了,但我认为这对于我们处于同样位置的其他人可能会有用 ;) - jomazz

0

我基于你的问题编写的方法可行!

try {
            ModbusTCPTransaction trans = null; // the transaction

            String refe = "0";// HEX Address
            int ref = Integer.parseInt(refe, 16);// Hex to int
            // int count = 1; // the number Address to read

            ReadMultipleRegistersRequest ainReq = new ReadMultipleRegistersRequest(
                    ref, count);
            ReadMultipleRegistersResponse ainRes = new ReadMultipleRegistersResponse();

            // 3. Start Transaction
            trans = new ModbusTCPTransaction(con);
            trans.setRetries(5);
            trans.setReconnecting(true);
            trans.setRequest(ainReq);

            int k = 0;
            do {
                trans.execute();
                ainRes = (ReadMultipleRegistersResponse) trans.getResponse();
                Register reg = new SimpleRegister(ertekInt);
                WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(0,
                        new Register[]{reg});
                System.out.println("Állított AOUT:  " + request.getRegisterValue(k));
                lista.add(createPlanet("AOUT",
                        "" + k + "    " + request.getRegisterValue(k)));
                k++;
            } while (k < count);
} catch (ModbusIOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ModbusSlaveException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ModbusException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

0

我在Android上遇到了这个问题。

由于这个任务需要等待外部设备的响应,可能需要一些时间,所以我找到的解决方案是在另一个线程中执行写入和读取操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接