0
我想用簡單的SCADA/HMI編寫Java代碼,通過Modbus TCP將我的電腦連接到PLC。我編寫了代碼來開啓/關閉PLC上的5個線圈,但應用程序工作非常緩慢 - 當我按下按鈕兩次(這是開關線圈的條件)時,PLC需要4-6秒才能獲得命令。但我希望它能夠快速工作。java Modbus TCP SCADA/HMI工作速度非常慢
在代碼中,我編寫了建立連接的主類和線程類,其中爲每個線圈執行ModBusTCPTransaction。我把這個線程類稱爲»守護進程«,並在主類中啓動它。但是,也許這不是應該完成的方法 - 也許任何人都可以寫下這樣的SCADA/HMI系統通常是完成/工作,只需2/3個句子......我是否還需要一個deamon線程類......?
這裏是我的代碼
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的工作速度非常快。現在我正在無限循環中執行事務(daemon theread) - 事務每隔100毫秒發生一次,或者通常這些類型的SCADA只執行一次事務 - 當我更改事件(按下一個按鈕)時。 ?持有寄存器,它們的交易是否在無限循環中連續執行,或者只有在發生更改時才執行(SCADA上的十進制值被更改)。 – taDEUS 2015-02-09 16:21:47
您通常不會連續不斷地重複寫入相同的值。讀取值是另一回事......大多數工業協議沒有任何訂閱或未經請求的機制,因此使用輪詢。 – 2015-02-10 01:28:18
什麼是實際»輪詢«,我一直在網上搜索,但沒有找到任何明確的解釋 - 輪詢是否意味着執行modbus事務..?那麼讀取價值是什麼 - 也用它來輪詢..? – taDEUS 2015-02-16 15:28:20