`
sunxboy
  • 浏览: 2828373 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Java应用程序的MODBUS通讯

 
阅读更多

实验目的

JAVA应用程序通过MODBUS协议RTU模式读写设备

 

实验器材

西门子 s7-200 226cn PLC 的CPU一台;s7-200 编程电缆一条,这条电缆亦充当MODBUS的串行口上的连接线。编程电缆是USB接口的,由于此编程电缆的驱动程序安装后即模拟了一个虚拟的串行口COM3,因此可以借助此电缆充当实际的物理连接线路

 

开发环境

Jdk1.6 update 25; STEP 7-MicroWIN 4.0;西门子S7-200的MODBUS库

 

实验目标

读PLC的输入过程映像寄存器;写PLC的V存储区

 

JAVA应用程序第三方开发包下载页面 http://sourceforge.net/projects/modbus4j/files/modbus4j/

 

Java串行口编程开发包 RXTXcomm.jar

 

环境搭建

PLC充当从站,占用通讯口port0;JAVA应用程序充当主站,发起读写的请求并等待PLC的响应。示例程序里写十六进制数值31(即二进制 00110001)到保持寄存器上,

PLC的Q1显示的结果是:

Q1.0 亮

Q1.1 灭

Q1.2 灭

Q1.3 灭

Q1.4 亮

Q1.5 亮

Q1.6 灭

Q1.7 灭

 

PLC从站的编程目标:MODBUS协议上的保持寄存器里的一个字节输出到Q,以便通过PLC上的指示灯观察。

 

PLC上的梯形图



 

说明:

IB0上的值决定是否启用MODBUS

通讯波特率9600

从站地址是5

I和Q的最大访问个数是128

模拟量输入最大访问个数是32

保持寄存器可访问1000个字

VB1上的字节输出到Q1.0 ... Q1.7

 

 

 

JAVA应用程序

import com.serotonin.io.serial.*;

import com.serotonin.modbus4j.*;

import com.serotonin.modbus4j.exception.*;

import com.serotonin.modbus4j.msg.*;

import java.util.*;

final class HardneedlTest {

    //MODBUS网络上从站地址

    private final static int SLAVE_ADDRESS=5;

 

    //串行口波特率

    private final static int BAUD_RATE = 9600;

    

    public static void main(String[] args) throws Exception {

        SerialParameters serialParameters = new SerialParameters();

 

        //设定MODBUS通讯的串行口

        serialParameters.setCommPortId("COM3");

 

        //设定成无奇偶校验

        serialParameters.setParity(0);

 

        //设定成数据位是8位

        serialParameters.setDataBits(8);

 

        //设定为1个停止位

        serialParameters.setStopBits(1);

 

        serialParameters.setPortOwnerName("Numb nuts");

 

        //串行口上的波特率

        serialParameters.setBaudRate(BAUD_RATE);

 

        ModbusFactory modbusFactory = new ModbusFactory();

        ModbusMaster master = modbusFactory.createRtuMaster(serialParameters);

        try {

            master.init();

            readDiscreteInputTest(master,SLAVE_ADDRESS,0,8);

            writeRegistersTest(master,SLAVE_ADDRESS, 0, new short[]{0x31,0xb,0xc,0xd,0xe,0x9, 0x8, 0x7, 0x6} );

            readHoldingRegistersTest(master,SLAVE_ADDRESS,0,8);

        }

        finally {

            master.destroy();

        }

    }

 

    /**

     * 读开关量型的输入信号

     * @param master 主站

     * @param slaveId 从站地址

     * @param start 起始偏移量

     * @param len 待读的开关量的个数

     */

    private static void readDiscreteInputTest(ModbusMaster master, int slaveId, int start, int len) {

        try {

            ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, start, len);

            ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);

 

            if (response.isException())

                System.out.println("Exception response: message=" + response.getExceptionMessage());

            else

                System.out.println(Arrays.toString(response.getBooleanData()));

        }

        catch (ModbusTransportException e) {

            e.printStackTrace();

        }

    }

 

    /**

     * 读保持寄存器上的内容

     * @param master 主站

     * @param slaveId 从站地址

     * @param start 起始地址的偏移量

     * @param len 待读寄存器的个数

     */

    private static void readHoldingRegistersTest(ModbusMaster master, int slaveId, int start, int len) {

        try {

            ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len);

            ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);

 

            if (response.isException())

                System.out.println("Exception response: message=" + response.getExceptionMessage());

            else

                System.out.println(Arrays.toString(response.getShortData()));

        }

        catch (ModbusTransportException e) {

            e.printStackTrace();

        }

    }

 

    /**

     * 批量写数据到保持寄存器

     * @param master 主站

     * @param slaveId 从站地址

     * @param start 起始地址的偏移量

     * @param values 待写数据

     */

    public static void writeRegistersTest(ModbusMaster master, int slaveId, int start, short[] values) {

        try {

            WriteRegistersRequest request = new WriteRegistersRequest(slaveId, start, values);

            WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);

 

            if (response.isException())

                System.out.println("Exception response: message=" + response.getExceptionMessage());

            else

                System.out.println("Success");

        }

        catch (ModbusTransportException e) {

            e.printStackTrace();

        }

    }

}

分享到:
评论
5 楼 abababudei 2016-05-06  
请教一下,这个您是怎么解决的:
/dev/ttyS2
entering RXTXPort:testRead
RXTX Warning:  Removing stale lock file. /data/local/tmp/LCK..ttyS2
Unable to remove stale lock file: /data/local/tmp/LCK..ttyS2
leaving RXTXPort:testRead no lock
...
com.serotonin.io.serial.SerialPortException: gnu.io.NoSuchPortException
com.serotonin.modbus4j.exception.ModbusInitException: com.serotonin.io.serial.SerialPortException: gnu.io.NoSuchPortException
com.serotonin.modbus4j.serial.SerialMaster.init(SerialMaster.java:31)
at com.serotonin.modbus4j.serial.rtu.RtuMaster.init(RtuMaster.java:23)
at com.example.modbus.SerialUtils.init(SerialUtils.java:44)
...
当android板块插上USB调试线就重启APK就可以正常读取这个串口
总共出现了这三种情况:
RXTX Error:  Unable to remove stale lock file: /data/local/tmp/LCK..ttyS2
RXTX fhs_lock() Error: creating lock file: /data/local/tmp/LCK..ttyS2: File exists
RXTX Warning:  Removing stale lock file. /data/local/tmp/LCK..ttyS2
4 楼 sunxboy 2014-11-15  
u011033959 写道
我想请教一下,我打算用该代码实现与ModbusSlave模拟器之间的通信,运行出现下面错误:
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version   = RXTX-2.1-7
Exception in thread "main" java.lang.NullPointerException
at modbus1.HardneedlTest.readDiscreteInputTest(HardneedlTest.java:50)
at modbus1.HardneedlTest.main(HardneedlTest.java:31)
我该如何解决?


你这是modbus serial 通讯。
首先,你的rxtx 包正确的放到 jdk 路径去了么 ?
其次,能不能将通讯部分的代码贴上来,这样方便找问题,你这空指针异常很常见,看不出什么问题
3 楼 u011033959 2014-11-01  
我想请教一下,我打算用该代码实现与ModbusSlave模拟器之间的通信,运行出现下面错误:
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version   = RXTX-2.1-7
Exception in thread "main" java.lang.NullPointerException
at modbus1.HardneedlTest.readDiscreteInputTest(HardneedlTest.java:50)
at modbus1.HardneedlTest.main(HardneedlTest.java:31)
我该如何解决?
2 楼 sunxboy 2013-10-24  
类似的错误我遇到时,你可以尝试从以下几个方面着手:
1.设备的死机导致的通信故障
使用Modbus仿真工具可以无视这个问题

2.构造request时,设置的count大小不合理。具体大小根据实际情况调整。
值过小时也会报类似问题。

3.多线程环境下,多个线程同时通讯时,同步没有处理好,也会报类似问题。
1 楼 chenqiang_99 2013-10-21  
我想请教一下 你有没遇见这个问题
com.serotonin.modbus4j.exception.ModbusTransportException: com.serotonin.messaging.TimeoutException: request=com.serotonin.modbus4j.serial.rtu.RtuMessageRequest@6abf2d5e
at com.serotonin.modbus4j.serial.rtu.RtuMaster.send(RtuMaster.java:57)
at com.serotonin.modbus.readHoldingRegistersTest(modbus.java:64)
at com.serotonin.modbus.main(modbus.java:38)

相关推荐

Global site tag (gtag.js) - Google Analytics