1

背景:

一段时间以来,我们一直在使用带有 TM3AI8、TM3DQ8R 和 TM3DI8 模块的 Schneider M251 PLC,我注意到我们收到了通过 Modbus tcp 发送的意外值。

大多数时候,我们通过 Modbus 协议接收的信号在 4mA 范围内,处于我们预期信号的较低部分。但是,我们看到一个间歇性的 0 很少通过 modbus tcp 使用 easy modbus tcp 库发送到我们的 java 软件

图书馆:http ://easymodbustcp.net/en/

具体来说,当我们调用:

val = modbusClient.ReadHoldingRegisters(3005, 1)[0];

我们看到一个间歇性的不频繁 val = 0 出现,但只是偶尔出现。当我检查名为 soMachine 的 PLC 软件时,它似乎从未显示过零值。有没有人遇到过这种问题?我使用结构文本设置了一个 POU 来计算 IO 读数为 0 的次数,显然它从来都不是。所以我认为它与modbus库有关。

我在下面提供了一个 system.out.println(val) 来显示问题:

VAL IS THIS NOW: 3995
VAL IS THIS NOW: 3989
VAL IS THIS NOW: 3995
VAL IS THIS NOW: 3995
VAL IS THIS NOW: 3986
VAL IS THIS NOW: 3998
VAL IS THIS NOW: 3992
VAL IS THIS NOW: 3989
VAL IS THIS NOW: 3998
VAL IS THIS NOW: 3995
VAL IS THIS NOW: 0        <- Random intermittent 0
VAL IS THIS NOW: 3986
VAL IS THIS NOW: 3998
VAL IS THIS NOW: 3992
VAL IS THIS NOW: 3989
VAL IS THIS NOW: 3995
VAL IS THIS NOW: 3989
VAL IS THIS NOW: 3989 

plc 上的 I/O 配置为 0-20mA 扩展,传感器为 4-20mA 传感器。我们的单位刻度上的零读数代表 -2500 个单位,这对我们的系统造成了问题,因为它代表了我们测量中的巨大差异。我们正在使用 Schneider 卡上提供的诊断位以及检测传感器故障。但是,传感器似乎没有故障并且工作正常。

如您所见,来自 IO 卡的信号也有点嘈杂。读取此传感器的电压时,万用表不会波动,并且在我们的万用表上非常稳定,在 3.989mV 范围内。

当我们看到间歇性的 0 打印到控制台时,我们在 soMachine 中看不到 0。此外,每 250 毫秒调用一次轮询值的方法。

我们采用了以下“过滤器”,但这并不是解决问题的理想方法。

static int pt05ErrorCount = 0, pt05lastVal;
private static double readRegister3005() throws IOException{
    try {
    int val;
    if(PLC.isConnected()) {
        val = modbusClient.ReadHoldingRegisters(3005, 1)[0];

        if(val > 0) {
            pt05ErrorCount = 0;
            pt05lastVal = val;
        }
    }else {
        val = -1000;
    }
    System.out.println("VAL IS THIS NOW: "+val);
    if(val > 0) {
        return (double) (10000-0)/(20-4)*((double) val/1000-4)+0; //convert mA to psig
    }else {
        if(pt05ErrorCount > maxErrorCount) {
        pt05ErrorCount++;
        return (double) (10000-0)/(20-4)*((double) val/1000-4)+0;
    }else {
        return (double) (10000-0)/(20-4)*((double) pt05lastVal/1000-4)+0;
    }
    }
    } catch(Exception e) {
        System.out.println(e);
        throw new IOException(Globals.getSystemCalendarDateandTime() + " PLC.java > readRegister3005(): ERROR reading PLC address 3005.");
    }
}

如果您需要有关此问题的更多信息,请告诉我。

ReadHoldingRegisters 方法如下:

 /**
        * Read Holding Registers from Server
        * @param        startingAddress      Fist Address to read; Shifted by -1    
        * @param        quantity            Number of Inputs to read
        * @return       Holding Registers from Server
        * @throws de.re.easymodbus.exceptions.ModbusException
        * @throws UnknownHostException
        * @throws SocketException
        * @throws SerialPortTimeoutException 
        * @throws SerialPortException 
        */
    public int[] ReadHoldingRegisters(int startingAddress, int quantity) throws de.re.easymodbus.exceptions.ModbusException,
                UnknownHostException, SocketException, IOException, SerialPortException, SerialPortTimeoutException
    {
        if (tcpClientSocket == null)
            throw new de.re.easymodbus.exceptions.ConnectionException("connection Error");
        if (startingAddress > 65535 | quantity > 125)
            throw new IllegalArgumentException("Starting adress must be 0 - 65535; quantity must be 0 - 125");
        int[] response = new int[quantity];
        this.transactionIdentifier = toByteArray(0x0001);
        this.protocolIdentifier = toByteArray(0x0000);
        this.length = toByteArray(0x0006);
        //serialdata = this.unitIdentifier;
        this.functionCode = 0x03;
        this.startingAddress = toByteArray(startingAddress);
        this.quantity = toByteArray(quantity);

        byte[] data = new byte[]
                {
                    this.transactionIdentifier[1],
                    this.transactionIdentifier[0],
                    this.protocolIdentifier[1],
                    this.protocolIdentifier[0],
                    this.length[1],
                    this.length[0],
                    this.unitIdentifier,
                    this.functionCode,
                    this.startingAddress[1],
                    this.startingAddress[0],
                    this.quantity[1],
                    this.quantity[0],
                    this.crc[0],
                    this.crc[1]     
                };
            
            if (this.serialflag)
            {
                crc = calculateCRC(data, 6, 6);
                data[data.length -2] = crc[0];
                data[data.length -1] = crc[1];
            }
            byte[] serialdata = null;   
            if (serialflag)
            {          
                serialdata = new byte[8];
                java.lang.System.arraycopy(data, 6,serialdata,0,8);
                serialPort.purgePort(SerialPort.PURGE_RXCLEAR);
                serialPort.writeBytes(serialdata);
                if (debug) StoreLogData.getInstance().Store("Send Serial-Data: "+ Arrays.toString(serialdata));
               long dateTimeSend = DateTime.getDateTimeTicks();
               byte receivedUnitIdentifier = (byte)0xFF;
               serialdata = new byte[256];
               int expectedlength = 5+2*quantity;
               while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.getDateTimeTicks() - dateTimeSend) > 10000 * this.connectTimeout))
               {
                   serialdata = serialPort.readBytes(expectedlength, this.connectTimeout); 
               
                   receivedUnitIdentifier = serialdata[0];
               }
               if (receivedUnitIdentifier != this.unitIdentifier)
               {
                    data = new byte[256];                       
               }
               if (serialdata != null)
               {
                   data = new byte[262]; 
                   System.arraycopy(serialdata, 0, data, 6, serialdata.length);
                   if (debug) StoreLogData.getInstance().Store("Receive ModbusRTU-Data: " + Arrays.toString(data));
               }
                for (int i = 0; i < quantity; i++)
                {
                    byte[] bytes = new byte[2];
                    bytes[0] = data[3+i*2];
                    bytes[1] = data[3+i*2+1];
                    ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);                     
                    response[i] = byteBuffer.getShort();
        }   
            }

                
        if (tcpClientSocket.isConnected() | udpFlag)
        {
            if (udpFlag)
            {
                InetAddress ipAddress = InetAddress.getByName(this.ipAddress);
                DatagramPacket sendPacket = new DatagramPacket(data, data.length, ipAddress, this.port);
                DatagramSocket clientSocket = new DatagramSocket();
                clientSocket.setSoTimeout(500);
                clientSocket.send(sendPacket);
                data = new byte[2100];
                DatagramPacket receivePacket = new DatagramPacket(data, data.length);
                clientSocket.receive(receivePacket);
                clientSocket.close();
                data = receivePacket.getData();
            }
            else
            {
                outStream.write(data, 0, data.length-2);
                if (debug) StoreLogData.getInstance().Store("Send ModbusTCP-Data: "+Arrays.toString(data));   
                if (sendDataChangedListener.size() > 0)
                {
                    sendData = new byte[data.length-2];
                    System.arraycopy(data, 0, sendData, 0, data.length-2);
                    for (SendDataChangedListener hl : sendDataChangedListener)
                        hl.SendDataChanged();
                }
                data = new byte[2100];
                int numberOfBytes = inStream.read(data, 0, data.length);
                if (receiveDataChangedListener.size() > 0)
                {
                    receiveData = new byte[numberOfBytes];
                    System.arraycopy(data, 0, receiveData, 0, numberOfBytes);
                    for (ReceiveDataChangedListener hl : receiveDataChangedListener)
                        hl.ReceiveDataChanged();
                    if (debug) StoreLogData.getInstance().Store("Receive ModbusTCP-Data: " + Arrays.toString(data));
                }
                        }
            }
            if (((int) data[7]) == 0x83 & ((int) data[8]) == 0x01)
            {
                if (debug) StoreLogData.getInstance().Store("FunctionCodeNotSupportedException Throwed");
                throw new de.re.easymodbus.exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
            }
            if (((int) data[7]) == 0x83 & ((int) data[8]) == 0x02)
            {
                if (debug) StoreLogData.getInstance().Store("Starting adress invalid or starting adress + quantity invalid");
                throw new de.re.easymodbus.exceptions.StartingAddressInvalidException("Starting adress invalid or starting adress + quantity invalid");
            }           
            if (((int) data[7]) == 0x83 & ((int) data[8]) == 0x03)
            {
                if (debug) StoreLogData.getInstance().Store("Quantity invalid");
                throw new de.re.easymodbus.exceptions.QuantityInvalidException("Quantity invalid");
            }
            if (((int) data[7]) == 0x83 & ((int) data[8]) == 0x04)
            {
                if (debug) StoreLogData.getInstance().Store("Error reading");
                throw new de.re.easymodbus.exceptions.ModbusException("Error reading");
            }
            for (int i = 0; i < quantity; i++)
            {
                byte[] bytes = new byte[2];
                bytes[0] = data[9+i*2];
                bytes[1] = data[9+i*2+1];
                ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
                        
                response[i] = byteBuffer.getShort();
            }
            
        
        return (response);
    }

问候,

4

0 回答 0