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();
}
}
}
지금은 WriteMultipleCoilsRequest 함수를 사용했으며 이제는 SCADA가 매우 빠르게 작동합니다. 이제 트랜잭션을 무한 루프 (데몬)로 실행하고 있습니다. 트랜잭션이 100ms마다 발생합니다. 괜찮습니다. 일반적으로 이러한 종류의 SCADA는 트랜잭션을 한 번만 실행합니다. 버튼을 누르면 변경됩니다. ? 레지스터를 유지하는 것은 트랜잭션이 무한 루프에서 연속적으로 실행되는지 아니면 변경이 발생했을 때만 실행되는지 (SCADA에서 10 진수 값이 변경됨)? – taDEUS
일반적으로 동일한 값을 계속해서 반복해서 쓰지는 않습니다. 가치를 읽는 것은 또 다른 이야기입니다. 대부분의 산업 프로토콜에는 구독이나 원치 않는 메커니즘이 없으므로 대신 폴링이 사용됩니다. –
실제로 폴링 무엇입니까«, 나는 웹 검색하고 있지만 명확한 설명을 찾지 못했습니다 - 폴링 의미 modbus 트랜잭션을 실행하는 ..? 그리고 가치를 읽는 것은 그것을 위해 사용 된 폴링입니까? – taDEUS