The following example SerSimple.java shows how to configure a serial Modbus protocol and read values:
// Import the FieldTalk protocol library import com.focus_sw.fieldtalk.*; public class SerSimple { public static void main(String[] args) { try { new SerSimple().poll(); } catch (NoClassDefFoundError e) { System.out.println("The Java Communication API is not installed!"); System.out.println("COMM API packages can be found in the lib subdirectory."); System.out.println("On Windows please copy the files 'comm.jar' into 'lib/ext', 'win32com.dll' into 'bin' and 'javax.comm.properties' into 'lib' sub-directory of your Java runtime."); } catch (Exception e) { e.printStackTrace(); } } public void poll() throws Exception { // Declare as MbusAsciiMasterProtocol if Modbus ASCII should be used //MbusAsciiMasterProtocol mbus = new MbusAsciiMasterProtocol(); MbusRtuMasterProtocol mbus = new MbusRtuMasterProtocol(); // Declare as int[] or float[] array to read 32-bit values instead short[] dataSet1 = new short[1 /*Number of values to be read*/]; // Configure and open port mbus.setRetryCnt(0); // Increase to 2 for poor links mbus.setPollDelay(0); // Increase if slave needs time between polls mbus.openProtocol("COM1", 19200, mbus.DATABITS_8, mbus.STOPBITS_1, mbus.PARITY_EVEN); try { while (true) { try { // Read data from slave mbus.readMultipleRegisters(1 /*Slave address*/, 100 /*Start reference*/, dataSet1); // Simply print the first value read System.out.println("Data = " + dataSet1[0]); } catch (BusProtocolException e) { System.out.println(e.toString()); } } } finally { // Clean-up mbus.closeProtocol(); } } }
The following example SerCommunicator.java shows how to use multi-threading for concurrent polling of multiple slave devices of the same type:
// Import the FieldTalk protocol library import com.focus_sw.fieldtalk.*; public class SerCommunicator implements Runnable { // Declare as MbusAsciiMasterProtocol if Modbus ASCII should be used MbusRtuMasterProtocol mbus = new MbusRtuMasterProtocol (); // Data to be exchanged DeviceDataProfile device1 = new DeviceDataProfile(); DeviceDataProfile device2 = new DeviceDataProfile(); public static void main(String[] args) { try { new SerCommunicator("COM1"); } catch (NoClassDefFoundError e) { System.out.println("The Java Communication API is not installed!"); System.out.println("COMM API packages can be found in the lib subdirectory."); System.out.println("On Windows please copy the files 'comm.jar' into 'lib/ext', 'win32com.dll' into 'bin' and 'javax.comm.properties' into 'lib' sub-directory of your Java runtime."); } catch (Exception e) { e.printStackTrace(); } } public SerCommunicator(String portName) throws Exception { // Configure and open port mbus.setRetryCnt(0); // Increase to 2 for poor links mbus.setPollDelay(0); // Increase if slaves need quiet period on bus mbus.openProtocol(portName, 19200, MbusRtuMasterProtocol.DATABITS_8, MbusRtuMasterProtocol.STOPBITS_1, MbusRtuMasterProtocol.PARITY_EVEN); // Start communication threads to two similar devices new PollThread(mbus, 1 /*Slave address*/, device1).start(); new PollThread(mbus, 2 /*Slave address*/, device2).start(); // Start data processing thread new Thread (this).start(); } public void run() { while(true) { processData(device1); processData(device2); // Sleep for 1000 ms try { Thread.currentThread().sleep(1000); } catch (java.lang.InterruptedException e) { /* ignore */ } } } public void processData(DeviceDataProfile data) { synchronized(data.deviceDataSet1) { // Do something here with data ... } synchronized(data.deviceDataSet2) { // Do something here with data ... } synchronized(data.deviceDataSet3) { // Update data to be written here ... } } }
class DeviceDataProfile { // Declare as int[] or float[] array to read 32-bit values instead public short[] deviceDataSet1 = new short[10 /*No of values to be read*/]; public short[] deviceDataSet2 = new short[10 /*No of values to be read*/]; public short[] deviceDataSet3 = new short[10 /*No of values to be sent*/]; }
import java.io.*; // Import the FieldTalk protocol library import com.focus_sw.fieldtalk.*; public class PollThread extends Thread { MbusMasterFunctions mbus; int slaveAddr; DeviceDataProfile deviceDataProfile; public PollThread(MbusMasterFunctions mbus, int slaveAddr, DeviceDataProfile deviceDataProfile) { this.mbus = mbus; this.slaveAddr = slaveAddr; this.deviceDataProfile = deviceDataProfile; } public void run() { while (true) { try { // Read data set 1 from slave mbus.readMultipleRegisters(slaveAddr, 100 /*Start reference*/, deviceDataProfile.deviceDataSet1); // Read data set 2 from slave mbus.readMultipleRegisters(slaveAddr, 140 /*Start reference*/, deviceDataProfile.deviceDataSet2); // Write data set 3 to slave mbus.writeMultipleRegisters(slaveAddr, 160 /*Start reference*/, deviceDataProfile.deviceDataSet3); System.out.println("Polling slave " + slaveAddr); } catch (BusProtocolException e) { System.out.println("Slave " + slaveAddr + ": " + e.toString()); } catch (IOException e) { System.out.println("Slave " + slaveAddr + ": " + e.toString()); } } } }
The following example TcpSimple.java shows how to configure a MODBUS/TCP protocol and read values:
// Import the FieldTalk protocol library import com.focus_sw.fieldtalk.*; public class TcpSimple { public static void main(String[] args) { try { new TcpSimple().poll(); } catch (Exception e) { e.printStackTrace(); } } public void poll() throws Exception { MbusTcpMasterProtocol mbus = new MbusTcpMasterProtocol (); // Declare as int[] or float[] array to read 32-bit values instead short[] dataSet1 = new short[10 /*Number of values to be read*/]; // Configure and open connection mbus.setPollDelay(1000); // Poll only every 1 s mbus.openProtocol("127.0.0.1"); // Pass IP address or host name here try { while (true) { try { // Read data from slave mbus.readMultipleRegisters(1 /*Slave address*/, 100 /*Start reference*/, dataSet1); // Simply print the first value read System.out.println("Data = " + dataSet1[0]); } catch (BusProtocolException e) { System.out.println(e.toString()); } } } finally { // Clean-up mbus.closeProtocol(); } } }
The following example CyclicPollApplet.java shows how to use the protocol package in conjunction with an applet to present process information dynamically on a web page.
The Applet shows a dynamic tank level display within a web page. The tank level data is retrieved from a MODBUS/TCP based measurement system at IP address 10.0.0.11, Modbus unit 1. Two tank levels are displayed. In addition a pump can be started and stopped. The Modbus register table is as follows:
import java.applet.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; // Import the Java I/O package for the I/O Exceptions import java.io.*; // Import the FieldTalk protocol library import com.focus_sw.fieldtalk.*; public class CyclicPollApplet extends Applet implements Runnable { /************************************************************************** * Modbus communication related data **************************************************************************/ Thread pollThread; // The cyclic poll thread volatile boolean pollThreadExit; // Flag to safely terminate the thread MbusTcpMasterProtocol mbus = new MbusTcpMasterProtocol(); // The protocol short readDataTable[] = new short[2]; // The data table to be read /************************************************************************** * User interface data **************************************************************************/ GridBagLayout gridBagLayout = new GridBagLayout(); JLabel StatusLabel = new JLabel(); JLabel titleLabel = new JLabel(); JLabel tank1Label = new JLabel(); JLabel tank2Label = new JLabel(); JLabel tankLevel1Label = new JLabel(); JLabel tankLevel2Label = new JLabel(); JProgressBar tankLevel1Bar = new JProgressBar(); JProgressBar tankLevel2Bar = new JProgressBar(); JButton startPumpButton = new JButton(); JButton pumpStopButton = new JButton(); /************************************************************************** * Standard applet methods **************************************************************************/ public CyclicPollApplet() { } public void init() { try { jbInit(); invalidateUiData(); } catch (NoClassDefFoundError e) { System.out.println("The Java Communication API is not installed!"); System.out.println("COMM API packages can be found in the lib subdirectory."); System.out.println("On Windows please copy the files 'comm.jar' into 'lib/ext', 'win32com.dll' into 'bin' and 'javax.comm.properties' into 'lib' sub-directory of your Java runtime."); } catch(Exception e) { e.printStackTrace(); } } public void start() { try { StatusLabel.setText("Connecting..."); mbus.openProtocol("127.0.0.1"); StatusLabel.setText("Connected to MODBUS/TCP slave device"); pollThreadExit = false; pollThread = new Thread(this); pollThread.start(); } catch (Exception e) { StatusLabel.setText(e.toString()); } } public void stop() { try { pollThreadExit = true; // Stop thread safely try { pollThread.join(); } catch (java.lang.InterruptedException e) { /* ignore */ } mbus.closeProtocol(); StatusLabel.setText("Connection closed"); invalidateUiData(); } catch (Exception e) { StatusLabel.setText(e.toString()); invalidateUiData(); } } /************************************************************************** * User interface management **************************************************************************/ private void jbInit() throws Exception { StatusLabel.setBorder(BorderFactory.createLoweredBevelBorder()); StatusLabel.setText("Status"); titleLabel.setFont(new java.awt.Font("Dialog", 1, 14)); titleLabel.setBorder(BorderFactory.createRaisedBevelBorder()); titleLabel.setText("FieldTalk(tm) Modbus Master Protocol Sample"); startPumpButton.setBackground(Color.green); startPumpButton.setText("Start Pump"); startPumpButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { startPumpButton_actionPerformed(e); } }); pumpStopButton.setBackground(Color.red); pumpStopButton.setText("Stop Pump"); pumpStopButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { pumpStopButton_actionPerformed(e); } }); tankLevel1Label.setBackground(Color.white); tankLevel1Label.setFont(new java.awt.Font("Dialog", 1, 12)); tankLevel1Label.setForeground(Color.blue); tankLevel1Label.setBorder(BorderFactory.createLoweredBevelBorder()); tankLevel1Label.setHorizontalAlignment(SwingConstants.RIGHT); tankLevel1Label.setHorizontalTextPosition(SwingConstants.RIGHT); tankLevel2Label.setBackground(Color.white); tankLevel2Label.setFont(new java.awt.Font("Dialog", 1, 12)); tankLevel2Label.setForeground(Color.magenta); tankLevel2Label.setBorder(BorderFactory.createLoweredBevelBorder()); tankLevel2Label.setHorizontalAlignment(SwingConstants.RIGHT); tankLevel2Label.setHorizontalTextPosition(SwingConstants.RIGHT); tankLevel2Bar.setOrientation(JProgressBar.VERTICAL); tankLevel2Bar.setForeground(Color.magenta); tankLevel2Bar.setPreferredSize(new Dimension(50, 200)); tankLevel2Bar.setMaximum(1000); tankLevel1Bar.setOrientation(JProgressBar.VERTICAL); tankLevel1Bar.setForeground(Color.blue); tankLevel1Bar.setPreferredSize(new Dimension(50, 200)); tankLevel1Bar.setMaximum(1000); this.setLayout(gridBagLayout); tank1Label.setText("Tank 1"); tank2Label.setText("Tank 2"); this.add(tankLevel1Bar, new GridBagConstraints(0, 2, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0)); this.add(startPumpButton, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0 ,GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); this.add(tank1Label, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 0, 10), 0, 0)); this.add(tank2Label, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 0, 10), 0, 0)); this.add(StatusLabel, new GridBagConstraints(0, 5, 3, 1, 0.0, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); this.add(titleLabel, new GridBagConstraints(0, 0, 3, 1, 0.0, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); this.add(tankLevel2Bar, new GridBagConstraints(1, 2, 1, 2, 0.0, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0)); this.add(tankLevel1Label, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0 ,GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 10, 10), 0, 0)); this.add(tankLevel2Label, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0 ,GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 10, 10), 0, 0)); this.add(pumpStopButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0 ,GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); } void invalidateUiData() { // Invalidate user interface data tankLevel1Label.setText("???"); tankLevel2Label.setText("???"); tankLevel1Bar.setValue(0); tankLevel2Bar.setValue(0); } /************************************************************************** * Data transfer methods **************************************************************************/ public void run() { while (!pollThreadExit) { // // Sleep for 1000 ms // try { Thread.currentThread().sleep(1000); } catch (java.lang.InterruptedException e) { /* ignore */ } // // Data transmission // try { // Read data from slave into the readDataTable mbus.readMultipleRegisters(1, 100, readDataTable); StatusLabel.setText("Updating live data ..."); // Update user interface with values tankLevel1Label.setText(Integer.toString(readDataTable[0])); tankLevel2Label.setText(Integer.toString(readDataTable[1])); tankLevel1Bar.setValue((int) readDataTable[0]); tankLevel2Bar.setValue((int) readDataTable[1]); } catch (Exception e) { // I/O exception or bus protocol exception occured StatusLabel.setText(e.toString()); invalidateUiData(); } } } void startPumpButton_actionPerformed(ActionEvent a) { try { // Write command bit 0 to command register at 110 mbus.writeSingleRegister(1, 110, (short) 0x0001); } catch (IOException e) { // I/O exception or bus protocol exception occured StatusLabel.setText(e.toString()); } } void pumpStopButton_actionPerformed(ActionEvent a) { try { // Write command bit 1 to command register at 110 mbus.writeSingleRegister(1, 110, (short) 0x0002); } catch (Exception e) { // I/O exception or bus protocol exception occured StatusLabel.setText(e.toString()); } } }