使用Java实现上位机数据采集

基于Spring Boot开发上位机

背景

最近接到了自动化线的业务,客户方需要大屏展示各机台设备的数据,如温度、产量、速度、耗电量、开机时长、设备状态等情况,由于之前是使用**.NET+Winform** 实现的,上一任上位机开发工程师离职,所以之前的项目只做维护不做更改,本次属于使用Java对上位机进行重新开发。

了解常用的PLC与通讯协议

在进行上位机开发之前,我们需要先了解常见的PLC与相关的通讯协议

欧姆龙PLC: 欧姆龙PLC设备通过FINS协议进行通讯,由于FINS协议是欧姆龙PLC的内部协议,所以与其他PLC进行通信时还得给欧姆龙PLC安装相应的模块。
三菱PLC: 三菱PLC默认使用MELSEC协议,但在开发中常使用Modbus协议与三菱PLC通讯,需要对三菱PLC进行配置开通Modbus协议权限。
台达PLC: 台达PLC通常使用Modbus协议进行通讯,但是台达PLC内部的寄存器地址和Modbus寄存器地址并不相同,需要查看相应的操作手册进行操作。
汇川PLC: 汇川PLC通常使用串口进行通讯,在开发的过程中需要通过转换器把串口转网口,或者直接把串口转Modbus进行开发
西门子PLC: 西门子PLC通常使用S7协议进行通讯,S7协议又区分出了几种变体,主要为S7-1200/1500通讯协议S7-300/400通讯协议,最常见的一般是S7-1200/1500通讯协议

引入相关的依赖

本次上位机开发主要接触到前4种PLC,由于其中3种都可直接支持Modbus协议,所以主要引入的依赖为modbus协议相关的j2mod依赖与Fins协议相关的communication依赖,串口开发的相关依赖为jSerialComm,pom.xml加入以下内容。

		<dependency>
			<groupId>com.github.dathlin</groupId>
			<artifactId>communication</artifactId>
			<version>1.0.0</version>
		</dependency>
		<dependency>
			<groupId>com.ghgande</groupId>
			<artifactId>j2mod</artifactId>
			<version>3.1.1</version>
		</dependency>
		<dependency>
			<groupId>com.fazecast</groupId>
			<artifactId>jSerialComm</artifactId>
			<version>2.9.3</version>
		</dependency>

如果communication依赖下载不了可直接下载本文提供的jar包进行导入

使用ModbusTCP进行数据读写

j2mod中可直接使用ModbusTCPMaster进行创建连接,使用Register来对寄存器进行操作,读取的方法为readMultipleRegisters ,可读取多个连续的寄存器,写入的方法为writeMultipleRegisters 可写入多个连续的寄存器,代码示例如下:

		//创建ModbusTCP连接,PLC的IP地址为192.168.20.60,ModbusTCP默认端口号为502
        ModbusTCPMaster connection = new ModbusTCPMaster("192.168.20.60");
        connection.connect();
        if(connection.isConnected()) {
            log.info("Connection Success");
        }

        //向寄存器中写入数据,使用Register数组对数据进行封装,一个Register代表一个寄存器
        Register[] registers = new Register[4];
        for (int i = 0; i < 4; i++) {
            Register register = new ObservableRegister();
            register.setValue(i);
            registers[i] = register;
        }
        //从地址是5200的寄存器开始写入4个寄存器的数据
        connection.writeMultipleRegisters(5200,registers);

        //从寄存器读取数据,方法入参分别是开始的寄存器地址与读取的寄存器数量,从5200开始读取4个寄存器数据
        InputRegister[] inputRegister = connection.readMultipleRegisters(5200,4);
        for (InputRegister register : inputRegister) {
            log.info("读取到的寄存器数据为:{} ",register.getValue());
        }
        //关闭连接
        connection.disconnect();
使用串口转Modbus进行数据读写(由于连接问题未测试成功)

串口开发主要使用到的开发包为jSerialComm ,在j2mod中提供了ModbusSerialMaster来支持串口的连接,示例代码如下:

		// 串口设置
        SerialParameters serialParams = new SerialParameters();
        //根据串口的名字设置串口连接
        serialParams.setPortName("COM1");
        // 创建Modbus串口连接
        ModbusSerialMaster modbusSerialMaster = new ModbusSerialMaster(serialParams);
        modbusSerialMaster.connect();
        if (modbusSerialMaster.isConnected()) {
            log.info("Connection Success");
        }
        //读取寄存器地址
        InputRegister[] registers = modbusSerialMaster.readMultipleRegisters(5200, 2);
        for (InputRegister register : registers) {
            log.info("读取到的寄存器数据为{}", register.getValue());
        }
        //关闭连接
        modbusSerialMaster.disconnect();
使用Fins协议进行数据读写

对于Fins协议的操作与ModbusTCP类似,原理都是建立连接—>操作寄存器,在Fins协议中可使用OmronFinsNet 建立连接,使用ReadUInt16 方法读取寄存器数据,使用Write 对寄存器进行数据写入,相关的代码示例如下:

		//建立欧姆龙Fins连接,PLC的ip地址为192.168.20.90,欧姆龙PLC的默认端口为9600
        OmronFinsNet omronFinsNet = new OmronFinsNet("192.168.20.90", 9600);
        OperateResult result = omronFinsNet.ConnectServer();
        if (result.IsSuccess) {
            log.info("Connection Success");
        }
        //向D5200寄存器写入数据
        omronFinsNet.Write("D5200",1);
        //读取D5200寄存器的数据
        log.info("D5200寄存器的数据为:{}",omronFinsNet.ReadUInt16("D5200").Content);
        //关闭连接
        omronFinsNet.ConnectClose();
处理PLC连接数量限制与频繁创建销毁连接问题

通常PLC的连接数量收到限制,但是在数据采集的过程中我们不可能频繁的去建立和关闭连接,此时可以采用本地缓存对连接进行持久化,当缓存失效时释放连接

使用缓存过期策略释放连接

    /**
     * 缓存过期的同时自动断开连接
     */
    public static void setListener() {
        cache.setListener((key1, cachedObject) -> {
            if (cachedObject instanceof ModbusTCPMaster connection) {
                if (connection.isConnected()) {
                    connection.disconnect();
                }
            }
            if(cachedObject instanceof OmronFinsNet connection){
                connection.ConnectClose();
            }
        });
    }

建立连接的代码如下:

	/**
     * 获取modbus连接
     * @param ipAddr plc地址
     * @param port plc端口
     * @return modbus连接
     * @throws Exception 连接异常
     */
    public static Object getModbusConnection(String ipAddr,Integer port) throws Exception {
        if (LocalCacheUtil.containsKey(ipAddr)) {
            return LocalCacheUtil.get(ipAddr);
        } else {
            //创建连接
            ModbusTCPMaster connection = new ModbusTCPMaster(ipAddr,port);
            connection.connect();
            if(connection.isConnected()){
                //注册缓存监听
                LocalCacheUtil.setListener();
                //设置connection在缓存中的过期时间
                //由于使用lfu算法,缓存实际上并不会在到过期时间后立即进行释放,而是先淘汰最少使用的,然后每get一次都会进行续期
                LocalCacheUtil.put(ipAddr, connection, 5000L);
                return connection;
            }

        }
        String error = MessageFormat.format("plc连接异常,ip:{0},port:{1}",ipAddr,port);
        throw new RuntimeException(error);
    }
总结

使用Java写上位机和C#写上位机的区别主要是开发包的问题,实际操作上都是建立连接—>操作寄存器

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值