2015-02-07 2 views
0

Modbus TCP를 통해 내 컴퓨터를 PLC에 연결하는 간단한 SCADA/HMI 용 Java 코드를 작성하려고합니다. PLC에 5 개의 코일을 켜거나 끄는 코드를 작성했지만 애플리케이션이 매우 느리게 작동합니다. 버튼을 두 번 누르면 (코일을 켜고 끄는 조건) PLC는 4-6 초가 걸립니다 명령. 그러나 나는 그것이 빨리 일하기를 원한다.자바 Modbus TCP SCADA/HMI가 매우 느리게 작동합니다.

코드에서 필자는 연결을 설정하는 메인 클래스와 각 코일에 대해 ModBusTCPTransaction을 실행하는 스레드 클래스를 작성했습니다. 쓰레드 클래스를»Daemon«이라고 부르며 메인 클래스에서 시작합니다. 하지만 어쩌면 이것은 일을해야한다는 접근 방식이 아닙니다. 어쩌면 누구나 2/3 문장으로 SCADA/HMI 시스템이 얼마나 잘 수행되는지/작업 할 수 있는지 기록 할 수 있습니다 ... 심지어 데몬 스레드 클래스가 필요합니까? 여기

내 코드

import java.net.*; 
import java.io.*; 
import net.wimpi.modbus.*; 
import net.wimpi.modbus.msg.*; 
import net.wimpi.modbus.io.*; 
import net.wimpi.modbus.net.*; 
import net.wimpi.modbus.util.*; 
import java.awt.Color; 
import java.awt.FlowLayout; 
import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.awt.Graphics; 

// 1. daemon class 
class NitCoil extends Thread { 

    private WriteCoilRequest coil_req = null; 
    private ModbusTCPTransaction trans = null; 
    private int i; 

    NitCoil(String s , int i) { 
     super(s); 
     this.i = i; 
    } 

    public void run(){ 
     try { 
     while(true) { 
      coil_req = new WriteCoilRequest(i, ModbusTest.coil_con[i]); 
      trans = new ModbusTCPTransaction(ModbusTest.con); 
      trans.setRequest(coil_req); 
      trans.execute(); 
      this.sleep((int)(Math.random()*100)); 
     } 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
    } 
    } 

} 
//2. main class 
public class ModbusTest { 

    public static TCPMasterConnection con = null; 
    public static boolean[] coil_con = {false,false,false,false,false}; 
    public static void main(String[] args) { 

     try { 

      /* Variables for storing the parameters */ 
      InetAddress addr = null; //the slave's address 
      int port = Modbus.DEFAULT_PORT; 
      int repeat = 1; //a loop for repeating the transaction 

      //3. Setup the parameters 
      if (args.length < 1) { 
       System.exit(1); 
      } else { 
       try { 
        String astr = "192.168.0.25:502"; 
        int idx = astr.indexOf(':'); 
        { 
         port = Integer.parseInt(astr.substring(idx+1)); 
         astr = astr.substring(0,idx); 
        } 
        addr = InetAddress.getByName(astr); 
        if (args.length == 1) { 
         repeat = Integer.parseInt(args[0]); 
        } 
       } catch (Exception ex) { 
        ex.printStackTrace(); 
        System.exit(1); 
       } 
      } 

      //4. Open the connection 
      con = new TCPMasterConnection(addr); 
      con.setPort(port); 
      con.connect(); 

      //5. defining frame, panel, button 
      JFrame frame = new JFrame("JFrame Example"); 
      JPanel panel = new JPanel(); 
      panel.setLayout(new FlowLayout()); 
      JLabel label = new JLabel("This is a label!"); 

      //6. creating 5 buttons    
      JButton[] button = new JButton[5]; 

      for (int j = 0; j < 5; j++){ 
       final int temp = j; 
       button[j] = new JButton(String.valueOf(j)); 

      //7. button 
      button[j].setText("Switch ON light "+j); 

      button[j].addActionListener(new ActionListener() { 

      public void actionPerformed(ActionEvent e) { 
       if (coil_con[temp] == true) 
        coil_con[temp] = false; 
        else 
        coil_con[temp] = true; 
      } 
      }); 
      }; 
      panel.add(label); 
      panel.add(button[0]); 
      panel.add(button[1]); 
      panel.add(button[2]); 
      panel.add(button[3]); 
      panel.add(button[4]); 

      //8. call of demon 
      NitCoil n1 = new NitCoil("daemon1", 0); 
      n1.setDaemon(true); 
      n1.start(); 
      NitCoil n2 = new NitCoil("daemon2", 1); 
      n2.setDaemon(true); 
      n2.start(); 
      NitCoil n3 = new NitCoil("daemon3", 2); 
      n3.setDaemon(true); 
      n3.start(); 
      NitCoil n4 = new NitCoil("daemon4", 3); 
      n4.setDaemon(true); 
      n4.start(); 
      NitCoil n5 = new NitCoil("daemon5", 4); 
      n5.setDaemon(true); 
      n5.start(); 


      //9. Close the connection 
      JButton buttonClose = new JButton(); 
      buttonClose.setText("disconnect"); 

      buttonClose.addActionListener(new ActionListener() { 

      public void actionPerformed(ActionEvent e) { 
       ModbusTest.con.close(); 
      } 
      }); 
      panel.add(buttonClose); 
      panel.setBackground(Color.green); 

      frame.add(panel); 
      frame.setSize(300, 300); 
      frame.setLocationRelativeTo(null); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.setVisible(true); 

     } catch (Exception ex) { 
     ex.printStackTrace(); 
     } 

    } 

} 

답변

0

당신이 응답 시간처럼 무엇인지 볼 수 Wireshark를 봤어입니까? 장치가 느리게 응답하는 것일 수 있습니다.

또한 현재 설정 한 방법대로 항상 5 개의 코일을 계속 작성하므로 이상적이지는 않습니다.

코일 주소가 연속되어 있기 때문에 WriteMultipleCoils 함수 (0x0F)를 사용하여 하나의 요청으로 다섯 개의 코일 모두에 쓸 수 있습니다.

+0

지금은 WriteMultipleCoilsRequest 함수를 사용했으며 이제는 SCADA가 매우 빠르게 작동합니다. 이제 트랜잭션을 무한 루프 (데몬)로 실행하고 있습니다. 트랜잭션이 100ms마다 발생합니다. 괜찮습니다. 일반적으로 이러한 종류의 SCADA는 트랜잭션을 한 번만 실행합니다. 버튼을 누르면 변경됩니다. ? 레지스터를 유지하는 것은 트랜잭션이 무한 루프에서 연속적으로 실행되는지 아니면 변경이 발생했을 때만 실행되는지 (SCADA에서 10 진수 값이 변경됨)? – taDEUS

+0

일반적으로 동일한 값을 계속해서 반복해서 쓰지는 않습니다. 가치를 읽는 것은 또 다른 이야기입니다. 대부분의 산업 프로토콜에는 구독이나 원치 않는 메커니즘이 없으므로 대신 폴링이 사용됩니다. –

+0

실제로 폴링 무엇입니까«, 나는 웹 검색하고 있지만 명확한 설명을 찾지 못했습니다 - 폴링 의미 modbus 트랜잭션을 실행하는 ..? 그리고 가치를 읽는 것은 그것을 위해 사용 된 폴링입니까? – taDEUS

관련 문제