공부/자바(JAVA)

RX,TX - 시리얼(Serial)

도도-도윤 2017. 10. 21. 22:56

RX,TX - 시리얼(Serial)


자바 프로그램 작성을 통해서, 시리얼 통신을 다뤄보고자 합니다.


1. 개발 언어


개발언어

 자바(JAVA)


* 라이브러리(RXTX 프로젝트)



 http://rxtx.qbang.org/wiki/index.php/Main_Page


RXTXcomm.jar




2. 시리얼 프로그램 - 자바로 작성하기(입문)




 1. Eclipse에서 프로젝트 속성 설정하기




 2. RXTXcomm.jar을 "Add Jars"를 클릭하여 추가합니다.


 package Program;

 import Libraries.Serial;


 public class Init {

        public static void main(String[] args) {
  
        try {
                (new Serial()).connect("COM6");
        }
        catch (Exception e) {
                e.printStackTrace();
        }
  
     }
 }

 Init.java


package Libraries;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class Serial
{
    public Serial()
    {
        super();
    }
   
    public void connect ( String portName ) throws Exception
    {
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier( portName );
        if ( portIdentifier.isCurrentlyOwned() )
        {
            System.out.println("Error: Port is currently in use");
        }
        else
        {
            //클래스 이름을 식별자로 사용하여 포트 오픈
            CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
           
            if ( commPort instanceof SerialPort )
            {
                //포트 설정(통신속도 설정. 기본 9600으로 사용)
                SerialPort serialPort = (SerialPort) commPort;
                serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
               
                //Input,OutputStream 버퍼 생성 후 오픈
                InputStream in = serialPort.getInputStream();
                OutputStream out = serialPort.getOutputStream();
               
                 //읽기, 쓰기 쓰레드 작동
                (new Thread(new SerialReader(in))).start();
                (new Thread(new SerialWriter(out))).start();

            }
            else
            {
                System.out.println("Error: only serial ports are handled by this example.");
            }
        }    
    }
   
    /** */
    //데이터 수신
    public static class SerialReader implements Runnable
    {
        InputStream in;
       
        public SerialReader ( InputStream in )
        {
            this.in = in;
        }
       
        public void run ()
        {
            byte[] buffer = new byte[1024];
            int len = -1;
            try
            {
                while ( ( len = this.in.read(buffer)) > -1 )
                {
                    System.out.print(new String(buffer,0,len));
                }
            }
            catch ( IOException e )
            {
                e.printStackTrace();
            }           
        }
    }

    /** */
    //데이터 송신
    public static class SerialWriter implements Runnable
    {
        OutputStream out;
       
        public SerialWriter ( OutputStream out )
        {
            this.out = out;
        }
       
        public void run ()
        {
            try
            {
                int c = 0;
                while ( ( c = System.in.read()) > -1 )
                {
                    this.out.write(c);
                }
               
            }
            catch ( IOException e )
            {
                e.printStackTrace();
            }           
        }
       
    }
   
}

 Serial.java



 동작 - 영상

 



SerialProgram.zip




(고급) 3. RX-TX GUI 프로그램 작성하기



 




/*
 *  2017. 10. 21
 *  GUI.java
 *  Created By D.Y. Jung
 */

package Main;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import Libraries.CommBaudRate;
import Libraries.Communicator;
import Libraries.KeybindingController;

import javax.swing.JLabel;
import java.awt.Window.Type;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.JMenuBar;
import javax.swing.JList;
import javax.swing.JComboBox;
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JMenu;


public class GUI extends JFrame implements ChangeListener, ActionListener {

         //Communicator object
         public Communicator communicator = null;
         //KeybindingController object
         public KeybindingController keybindingController = null;
 
         private JPanel contentPane;
         public JComboBox cmbPort;
         public JComboBox cmbBaudRate;
         public JTextArea txtLog;
         public JButton btnConnect;
         public JButton btnDisconnect;
         public JButton btnSend;
 
         private JMenuBar menuBar;

          //Variables
         public int nrOfLeds;
         public byte rValue;
         public byte gValue;
         public byte bValue;
         public byte intensityValue;
         public byte[] rgbMap = new byte[10];
         private JLabel lblTitle;
         private JLabel lblLog;
         private JTextField txtCmd;
         private JMenu mnNewMenu;

 
 /**
  * Create the frame.
  */
 public GUI() {
         initComponents(); 
         createObjects(); 
         communicator.searchForPorts();
         keybindingController.toggleControls();

 }
 
 private void createObjects() {
  
         communicator = new Communicator(this);
         keybindingController = new KeybindingController(this);
  
 }

 private void initComponents() {


       setTitle("RX-TX");
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       setBounds(100, 100, 800, 384);
  
       menuBar = new JMenuBar();
       setJMenuBar(menuBar);
  
       mnNewMenu = new JMenu("파일(&F)");
       mnNewMenu.setMnemonic(KeyEvent.VK_F); // Alt + F 키
       menuBar.add(mnNewMenu);
  
       contentPane = new JPanel();
       contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
       setContentPane(contentPane);
       contentPane.setLayout(null);
  
       JPanel panel = new JPanel();
       panel.setBounds(0, 47, 772, 231);
       contentPane.add(panel);
       panel.setLayout(null);
  
       cmbPort = new JComboBox();
       cmbPort.setBounds(12, 33, 102, 21);
       panel.add(cmbPort);
 
       cmbBaudRate = new JComboBox();
       CommBaudRate baudRate = new CommBaudRate();
       baudRate.initComponent(cmbBaudRate);
       cmbBaudRate.setBounds(12, 62, 102, 21);
       panel.add(cmbBaudRate);
  
       lblTitle = new JLabel("Select the 시리얼 COM Port");
       lblTitle.setBounds(12, 8, 391, 15);
       panel.add(lblTitle);
  
       lblLog = new JLabel("로그(Log)");
       lblLog.setBounds(411, 7, 223, 15);
       panel.add(lblLog);
  
       btnConnect = new JButton("Connect(연결)");
       btnConnect.setBounds(123, 32, 140, 23);
       panel.add(btnConnect);
  
       btnDisconnect = new JButton("Disconnect(끊기)");
       btnDisconnect.setBounds(263, 32, 140, 23);
       panel.add(btnDisconnect);
  
       btnConnect.setActionCommand("connect");
       btnDisconnect.setActionCommand("disconnect");
  
       btnConnect.addActionListener(this);
       btnDisconnect.addActionListener(this);
  
       btnSend = new JButton("전송(Send)");
       btnSend.setActionCommand("sendCmd");
       btnSend.addActionListener(this);
       btnSend.setBounds(263, 92, 140, 23);
       panel.add(btnSend);
  
       txtLog = new JTextArea();
       txtLog.setBounds(411, 32, 349, 189);
  

       JScrollPane scrollPane = new JScrollPane(txtLog);
       scrollPane.setBounds(411, 31, 349, 179);
       panel.add(scrollPane);
  
       txtCmd = new JTextField();
       txtCmd.setBounds(12, 93, 251, 21);
       panel.add(txtCmd);
       txtCmd.setColumns(10);
  
 
 }
 
 @Override
 public void actionPerformed(ActionEvent e) {
  
      if("connect".equals(e.getActionCommand())){
            communicator.connect();
            if (communicator.getConnected() == true) {
                  if (communicator.initIOStream() == true) {
                            communicator.initListener();
                  }
            }
        }
        else if ("disconnect".equals(e.getActionCommand())) {
            communicator.disconnect();
        }
        else if ("led1".equals(e.getActionCommand())) {
            rgbMap[1] = rValue;
            rgbMap[2] = gValue;
            rgbMap[3] = bValue;
            communicator.updateFrame(rgbMap);

        }
        else if ("led2".equals(e.getActionCommand())) {
            rgbMap[4] = rValue;
            rgbMap[5] = gValue;
            rgbMap[6] = bValue;
            communicator.updateFrame(rgbMap);

        }
        else if ("led3".equals(e.getActionCommand())) {
            rgbMap[7] = rValue;
            rgbMap[8] = gValue;
            rgbMap[9] = bValue;
            communicator.updateFrame(rgbMap);

        }
        else if ("toggleMusic".equals(e.getActionCommand())) {
             if (rgbMap[1] == 0) {
                    rgbMap[1] = 1;
             }
             else {
                    rgbMap[1] = 0;
             }
             communicator.updateFrame(rgbMap);
        }
        else if ("sendCmd".equals(e.getActionCommand()) ) {
             byte[] array = txtCmd.getText().getBytes();
   
             for ( byte data :  array ) {
                    communicator.writeData(data);
             }
       }

 }
 
 public static void main(String[] args) {
  
         EventQueue.invokeLater(new Runnable() {
                 public void run() {
                      try {
                                new GUI().setVisible(true);
                      } catch (Exception e) {
                                e.printStackTrace();
                      }
                }
        });
  
     }


 @Override
 public void stateChanged(ChangeEvent arg0) {
  
  /*
            JSlider source = (JSlider)e.getSource();
            if (!source.getValueIsAdjusting()) {
                  if (source.equals(RSlider)){
                          rValue = (byte)source.getValue();
                          System.out.println("R:" + rValue);
                          //communicator.updateRGB(rValue, gValue, bValue);
                  }
                  else if (source.equals(GSlider)) {
                          gValue = (byte)source.getValue();
                          System.out.println("G:" + gValue);
                         //communicator.updateRGB(rValue, gValue, bValue);
                  }
                 else if (source.equals(BSlider)) {
                          bValue = (byte)source.getValue();
                          System.out.println("B:" + bValue);
                          //communicator.updateRGB(rValue, gValue, bValue);
                   }
                  else {
                          intensityValue = (byte)source.getValue();
                          System.out.println("I:" + intensityValue);
                          rgbMap[0] = intensityValue;
                          communicator.updateFrame(rgbMap);
                 }
        }
         */
  
    }


}

 GUI.java

 package Libraries;

import javax.swing.JComboBox;


public class CommBaudRate{
 
         public JComboBox initComponent( JComboBox cmbBaudRate ) {
  
                   int i = 0;
                   int n = 14;
                   int rate = 0;
  
                   while ( i <= n )
                   {
                        switch(i)
                        {
                                case 0:
                                       rate = 300;
                                       break;
     
                                case 1:
                                       rate = 1200;
                                       break;
     
                                case 2:
                                       rate = 2400;
                                       break;
     
                                case 3:
                                       rate = 4800;
                                       break;
    
                                case 4:
                                       rate = 9600;
                                       break;
     
                                case 5:
                                       rate = 19200;
                                       break;
     
                                case 6:
                                       rate = 38400;
                                       break;
     
                                case 7:
                                       rate = 57600;
                                       break;
     
                                case 8:
                                       rate = 74880;
                                       break;
    
                                case 9:
                                       rate = 115200;
                                       break;
     
                                case 10:
                                       rate = 230400;
                                       break;
     
                                case 11:
                                       rate = 250000;
                                       break;
     
                                case 12:
                                       rate = 500000;
                                       break;
     
                                case 13:
                                       rate = 1000000;
                                       break;
    
                                case 14:
                                       rate = 2000000;
                                       break;
    
                                default:
                                       rate = 0;
                                       break;
                }
   
                cmbBaudRate.addItem(rate);
                i++;
          }


           return cmbBaudRate;
      }

}

 CommBaudRate.java

 /*
 *  2017. 10. 21
 *  Communicator.java
 *  Created By D.Y. Jung
 */


package Libraries;

import gnu.io.*;

import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.TooManyListenersException;

import Main.GUI;


public class Communicator implements SerialPortEventListener
{
          //passed from main GUI
          GUI window = null;


          //for containing the ports that will be found
           private Enumeration ports = null;


           //map the port names to CommPortIdentifiers
           private HashMap portMap = new HashMap();


           //this is the object that contains the opened port
           private CommPortIdentifier selectedPortIdentifier = null;
           private SerialPort serialPort = null;
           private int baudRate;


           //input and output streams for sending and receiving data
           private InputStream input = null;
           private OutputStream output = null;


           //just a boolean flag that i use for enabling
           //and disabling buttons depending on whether the program
           //is connected to a serial port or not

           //private int sensCounter = 0;

          private boolean bConnected = false;


           //the timeout value for connecting with the port
          final static int TIMEOUT = 2000;

           //some ascii values for for certain things
          final static int SPACE_ASCII = 32;
          final static int DASH_ASCII = 45;
          final static int NEW_LINE_ASCII = 10;


          //a string for recording what goes on in the program
          //this string is written to the GUI
          String logText = "";


          public Communicator(GUI window)
          {
                 this.window = window;
          }


          //search for all the serial ports
          //pre: none
          //post: adds all the found ports to a combo box on the GUI
          public void searchForPorts()
          {
                 ports = CommPortIdentifier.getPortIdentifiers();


                 while (ports.hasMoreElements())
                 {
                         CommPortIdentifier curPort = (CommPortIdentifier)ports.nextElement();

                         //get only serial ports
                         if (curPort.getPortType() == CommPortIdentifier.PORT_SERIAL)
                         {
                               window.cmbPort.addItem(curPort.getName());
                               portMap.put(curPort.getName(), curPort);
                         }
                 }
          }


          //connect to the selected port in the combo box
          //pre: ports are already found by using the searchForPorts method
          //post: the connected COM port is stored in commPort, otherwise,
          //an exception is generated
          public void connect()
          {
                   String selectedPort = (String)window.cmbPort.getSelectedItem();
                   selectedPortIdentifier = (CommPortIdentifier)portMap.get(selectedPort);

                   CommPort commPort = null;

                   try
                   {
                              //the method below returns an object of type CommPort
                              commPort = selectedPortIdentifier.open("RoboLink Master Control Panel", TIMEOUT);
                             //the CommPort object can be casted to a SerialPort object
                              serialPort = (SerialPort)commPort;

                             //for controlling GUI elements
                              setConnected(true);

                             //logging
                             logText = selectedPort + " opened successfully.";
   
                             baudRate = (int) window.cmbBaudRate.getSelectedItem();
   
                             window.txtLog.setForeground(Color.black);
                             window.txtLog.append(logText + "\n");

                             window.txtLog.append( baudRate + "Rate" + "\n" );
   
               serialPort.setSerialPortParams( baudRate , SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
                           //CODE on SETTING BAUD RATE ETC OMITTED
                           //XBEE PAIR ASSUMED TO HAVE SAME SETTINGS ALREADY

                           //enables the controls on the GUI if a successful connection is made
           

                            window.keybindingController.toggleControls();
                   }
                   catch (PortInUseException e)
                   {
                            logText = selectedPort + " is in use. (" + e.toString() + ")";

                            window.txtLog.setForeground(Color.RED);
                            window.txtLog.append(logText + "\n");
                    }
                    catch (Exception e)
                    {
                            logText = "Failed to open " + selectedPort + "(" + e.toString() + ")";
                            window.txtLog.append(logText + "\n");
                            window.txtLog.setForeground(Color.RED);
                    }
             }


            //open the input and output streams
            //pre: an open port
            //post: initialized input and output streams for use to communicate data
            public boolean initIOStream()
           {
                     //return value for whether opening the streams is successful or not
                     boolean successful = false;

                     try {

                             input = serialPort.getInputStream();
                             output = serialPort.getOutputStream();

                             successful = true;
                             return successful;
                    }
                    catch (IOException e) {
                            logText = "I/O Streams failed to open. (" + e.toString() + ")";
                            window.txtLog.setForeground(Color.red);
                            window.txtLog.append(logText + "\n");
                            return successful;
                    }
           }


           //starts the event listener that knows whenever data is available to be read
           //pre: an open serial port
           //post: an event listener for the serial port that knows when data is received
           public void initListener()
           {
                    try
                    {
                           serialPort.addEventListener(this);
                           serialPort.notifyOnDataAvailable(true);
                     }
                    catch (TooManyListenersException e)
                    {
                           logText = "Too many listeners. (" + e.toString() + ")";
                           window.txtLog.setForeground(Color.red);
                           window.txtLog.append(logText + "\n");
                    }
          }


          //disconnect the serial port
          //pre: an open serial port
          //post: closed serial port
         public void disconnect()
         {
                    //close the serial port
                   try
                   {
                          //byte temp = 0;
                          //writeData(temp);

                          serialPort.removeEventListener();
                          serialPort.close();
                          input.close();
                          output.close();
   
                          setConnected(false);
                          window.keybindingController.toggleControls();

                          logText = "Disconnected.";
                          window.txtLog.setForeground(Color.red);
                          window.txtLog.append(logText + "\n");
                   }
                   catch (Exception e)
                   {
                          logText = "Failed to close " + serialPort.getName() + "(" + e.toString() + ")";
                          window.txtLog.setForeground(Color.red);
                          window.txtLog.append(logText + "\n");
                   }
         }


         final public boolean getConnected()
         {
                return bConnected;
         }


         public void setConnected(boolean bConnected)
         {
                 this.bConnected = bConnected;
         }

        //what happens when data is received
        //pre: serial event is triggered
        //post: processing on the data it reads
        public void serialEvent(SerialPortEvent evt) {
  
          if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE)
          {
               try
              {
                     //byte singleData = (byte)input.read();
                     //String Data = new String(singleData);
    
                     // 문자열 출력
                     byte[] buffer = new byte[1024];
    
                     int len = -1;

                      try
                      {
                           while ( ( len = input.read(buffer)) > -1 )
                           {
                                  System.out.print(new String(buffer, 0, len));
                                  window.txtLog.append(new String(buffer,0,len));
                           }
                
                                 window.txtLog.append("\n");
                                 System.out.print("\n");
                
                             }             
                             catch ( IOException e )
                             {
                                  e.printStackTrace();
                             }
            
                        }
                        catch (Exception e)
                        {
                               logText = "Failed to read data. (" + e.toString() + ")";
                               window.txtLog.setForeground(Color.red);
                               window.txtLog.append(logText + "\n");
                         }
   
                }
  
        }


        //method that can be called to send data
        //pre: open serial port
        //post: data sent to the other device
        public void writeData(byte Data)
        {
               try
               {
                      output.write(Data);
                      output.flush();
   
                      System.out.println("Send Byte " + Data);
                      window.txtLog.append("Send Byte " + Data + "\n");
                }
                catch (Exception e)
                {
                     //logText = "Failed to write data. (" + e.toString() + ")";
                      window.txtLog.setForeground(Color.red);
                      window.txtLog.append(logText + "\n");
                }
        }

        public void updateRGB(byte rValue, byte gValue, byte bValue) {
                writeData(rValue);
                writeData(gValue);
                writeData(bValue);
  
        }

        public void updateFrame(byte[] rgbMap) {
                for (int i = 0; i < rgbMap.length; i++) {
                      writeData(rgbMap[i]);
                }
  
         }

}

 Communicator.java

 /*
 *  2017. 10. 21
 *  KeybindingController.java
 *  Created By D.Y. Jung
 */

 package Libraries;

 import Main.GUI;

 

 public class KeybindingController {
             GUI window = null;


             public KeybindingController(GUI window) {
                       this.window = window;
             }


             public void toggleControls() {
  
                      if (window.communicator.getConnected() == true) {
    
                             window.btnDisconnect.setEnabled(true);
                             window.btnConnect.setEnabled(false);
                             window.cmbPort.setEnabled(false);
   
                            /*
                             window.RSlider.setEnabled(true);
                             window.GSlider.setEnabled(true);
                             window.BSlider.setEnabled(true);
                             window.IntensitySlider.setEnabled(true);
                            */
                      }
  
                      else {
                              window.btnDisconnect.setEnabled(false);
                              window.btnConnect.setEnabled(true);
                              window.cmbPort.setEnabled(true);

                           /*
                              window.RSlider.setEnabled(false);
                              window.GSlider.setEnabled(false);
                              window.BSlider.setEnabled(false);
                              window.IntensitySlider.setEnabled(false);
                           */
                     }
          }

}

 KeybindingController.java


소스 파일

171021 - Java-RXTX.zip



4. 참고 자료

1. Serial Communication in Java with Example Program,
https://blog.henrypoon.com/blog/2011/01/01/serial-communication-in-java-with-example-program/


2. TIAL/GUI.java at master · nilsberglund/TIAL,

https://github.com/nilsberglund/TIAL/tree/master/Java-App/src/tialControlPanel


3. Serial port - Wikipedia

https://en.wikipedia.org/wiki/Serial_port


시리얼 포트에 대한 소개 및 Baud Rate(보오 레이트) 값 등을 자세히 소개하고 있습니다.

RXTXcomm.jar
0.06MB
171021 - Java-RXTX.zip
0.06MB
SerialProgram.zip
0.0MB