Internet Connection  인터넷 연결

 . Super PLC와 인터넷 통신
 .
PC와 Super PLC의 모뎀 통신
 .
Super PLC의 파일 및 이메일 서비스
  .
나 자신만의 GUI 애플릭 (Applet) 만들기 

 
든 Super PLC에는 인터넷 통신 기능이 기본으로 내장되어 있습니다

사용자는 언제 어디서나 터넷을 경유하여 원격으로 Super PLC의 프로그램밍하고 모니터하고 그리고 장비를 제어하는 Super PLC를 제어할 수 있습니다.

사용자의 Super PLC 또한 모뎀을 경유하여 인터넷에 연결하기위하여 다이얼 업 기능을 가지고 있으며 원격지로 데이터를 보내기 위하여 저장할 수 있으며 또한 이메일을 보내는 기능을 가지고 있습니다.

이러한 모든 기능들은 미래에 제공되는 것이 아니라
Super PLC에서는 그 기능을 초저가의 PLC임에도 불구하고 제공하고 있는 것입니다.

 Super PLC와 인터넷 통신                                                                       

인터넷 TRiLOGI 버전 5 는 일반적으로 어떠한 윈도우 기반의 프로그램과도 잘 호환이 된다. 그리고 이것은 사용자에게 RS232 포트를 경유하여 PLC에 연결된 PC(TLServer)를 통해 PLC를 프로그램할 수 있도록 하여준다. 클라이언트/서버 기반의 구조로서 자바 (Java) 웹 브라우저를 사용하여 인터넷 네트워크 또는 회사 랜 상의 어떠한 컴퓨터에서도 PLC 프로그램을 할 수 있다. PLC의 로칼 모드 프로그램밍을 통해 이미 프로그램밍하는 방법을 익혔다면 이와같은 원격 프로그램밍은 똑 같은 윈도우 기반의 소프트웨어를 사용하기 때문에 인터넷을 경유하여 PLC를 프로그램밍하는 것에대해서는 별도의 추가적인 교육이 필요없다.

원격 프로그램밍 및 모니터링 기능을 위해 PLC가 시리얼 포트를 통해 네트워크에 연결된 PC와 연결하는 것이 필요한다. 이때 아래 그림과 같이 이 PC에서 인터넷 버전의 TRiLOGI 소프트웨어에서 함께 제공된 "TLServer" 소프트웨어(기본으로 제공)를 실행시켜야만 한다.

 internetwork.jpg (29823 bytes)

TLServer PC 회사의 랜(LAN) 또는 인터넷에 M-시리즈 PLC를 연결하기 위한 게이트웨이 역할을 하게 된다. 인터넷으로의 실제 연결은 이 PC에 의하여 제공되는 것이다.  이 PC를 인터넷에 연결하기 위하여 Ethernet, T-1, DSL, 케이블 모뎀, 또는 전화 모뎀 등등을 이용할 수 있다.

TRiLOGI와 같은 클라이언트 프로그램이 PLC로부터 프로그램 또는 데이터를 읽거나 PLC에 쓰기를 원한다면 인트라넷, 인터넷 또는 로칼 호스트 연결을 통해 TCP/IP 프로토콜을 사용하여 TLServer로 명령어를 보내면 된다. (사용자는 실제로는 이더넷 및 TCP/IP 프로토콜 등에 대하여 잘 알지 못하여도 상관이 없다. 이더넷 및 TCP/IP 프로토콜등은 사용자가 프로그램밍하거나 반드시 상세한 기술적인 내용을 알아야만 하는 것은 아니다. 단지 통신을 위해 이러한 매개체를 이용하기만 하면 되는 것이다.) 클라이언트 프로그램으로부터 명령을 받은 TLServer PC는 RS232 또는 RS485 포트를 경유하여 PLC로부터 프로그램 또는 데이터를 읽거나 PLC에 쓰기를 수행한다. PLC로부터 읽은 데이터는 TCP/IP 프로토콜을 경유하여 이 작업을 요청한 클라이언트 프로그램에 전송하여 준다.

TLServer는 또한 TRiLOGI 자바 애플릿 (Java Applet)를 갖고 있는 웹페이지들에 여러 가지 인터넷 PLC 통신 서비스를 제공하는 웹서버이기도 하다. 이때 이러한 웹페이지는 Java 실행 가능한 웹 브라우저를 사용하여야 하며 TRiLOGI 자바 애플릿 (Java Applet)를 설치하여야 한다.

 

 PC와 Super PLC의 모뎀 통신                                                                            

격에 설치된 M-시리즈 PLC를 전화 공중망 (PSTN), 무선, 또는 무선전화망을 통하여 호스트 PC와 연결시킬 수 있다. 이것은 아래 그림과 같이 두 개의 모뎀(PLC RS232 시리얼 포트에 연결된 모뎀과 원격 호스트 PC에 연결될 모뎀)에 의해 통신이 이루어진다.

모뎀 1: 호스트 PC는 2400 bps 이상의 통신 속도를 갖고 있는 내장형 또는 외장형 모뎀을 사용한다. 이 모뎀을 모뎀의 매뉴얼에 따라 PC에 연결하고 전화선을 모뎀의 "라인(Line)"이라고 표시되어 있는 포트에 연결한다.

모뎀 2:
The PLC에 사용되는 모뎀은 반드시 외장형 모뎀이어야 하며 PLC의 RS232 포트에 연결한다.

TLServer 2.0 모뎀 지원

인터넷 TRiLOGI 버전 5.1에 포함되어 있는 TLServer 2.0은 다이얼 모뎀을 지원하고 있다. 사용자가 PLC와 통신하기를 원할 때면 언제든지 PLC의 모뎀에 연결하기 위해 TLServer의 기능을 사용할 수 있다. 모뎀 통신이 이루어지면 인터넷에 연결된 원격 TLServer PC는 인터넷을 통해 PLC와 통신을 할 수 있게된다.

사용자는 어떠한 이벤트가 있을 때 PLC가 자동으로 전화를 걸어 모뎀을 통해 TLServer와 연결(통신)할 수 있도록 쉽게 프로그램할 수 있다. 이것은 PLC 스스로가 원격 PC의 하드디스크 파일에 데이터를 저장한다든지 또는 데이터를 기존 하드디스크 파일에 추가한다든지 하는 파일 서비스 기능 또는 인터넷을 겨유하여 필요할 때 마다 지정된 사람에게 이메일을 보낸다든지 또는 호스트 PC와 리얼타임클럭(RTC: Real Time Clock)을 동기화시킨다든지 하는 것과 같이 많은 일을 PC에 실행 시킬 수 있도록 한다.

여기에 대한 많은 예제가 TRiLOGI 버전 5.1 이상의 소프트웨어에서 폴더  "C:\TRiLOGI\TL5\usr\File Services and Modem"에 포함되어 있다. 이러한 모든 예제는 매우 쉬우며 강력한 기능의 표준 TBASIC 명령어를 사용하여 작성된 Custom Function을 사용하여 만들었다.

 

 Super PLC의 파일 및 이메일 서비스                                                                 

TLServer의 새로운 버전 2.0은 시리얼 통신 포트를 통해 PLC에 많은 파일 및 이메일 서비스를 제공한다. 기본적으로 PLC는 "태그(tags)" (태그:  '<' 와 '>' 문자 사이에 ASCII 문자를 사용한 HTML 명령어>를 사용하여 TLServer에 서비스 요청을 한다. TLServer는 이 서비스 요청에 대해 만일 요청한 메시지가 유효한 명령어라면 즉각 실행한다. PLC는 TBASIC의 PRINT #n 명령어를 사용하여 태그 및 ASCII 문자를 쉽게 보낼 수 있다.

PLC는 TLServer에 서비스를 요청할 수 있는 기기들 중 하나이기 때문에 TLServer로부터 서비스를 요청할 때를 제외하고는 항상 TLServer에 링크되어있어야 할 필요는 없다. 모뎀등을 사용하여 전화선을 통하여 원격 PLC를 TLServer에 연결할 수 있다. 그리고 요청된 파일 또는 이메일 서비스를 실행한다. TLServer에 서비스 요청을 하려는 다른 PLC들의 TLServer로의 연결을 위해 작업 수행이 끝나면 스스로 TLServer와의 연결을 해제한다.

다음은 현재 TLServer 2.0이 Super PLC에 제공하는 지원하는 파일 및 이메일 서비스이다.

1.  파일에 데이터 쓰기
 (기존 파일의 경우 덮어쓰기를 한다.)

Format: 
  <WRITE [파일이름]> 
  data data data...
  data....
  </>

2.  파일에 데이이터를 추가하기
(새로운 데이터가 기존파일에 추가된다.)

Format: 
<APPEND [파일이름]> 
  data data data...
  data....
</>

3.  수신인에게 데이터를
     이메일로 보내기

Format: 
  <EMAIL [이메일주소]> 
  Sender: [sender email]
  Subject: [subject text]
  data data data...
  data....
  </>
4. 파일로부터 데이터 읽기 Format: 
  <READ [파일이름]> 
  </>
5. TLServer로부터 리얼타임클럭
    (RTC: Real Time Clock) 읽기
Format: 
  <READ RTC[]></>

  

 나 자신만의 GUI 애플릿 (Applet) 만들기                                                           

   

 

원격으로 M-s시리즈 super PLC를 프로그램, 모니터 그리고 제어하기 위하여 인터넷 TRiLOGI 소프트웨어를 사용하는 것 이외에 인터넷을 경유하여 PLC를 원격으로 제어하고 모니터링하고 데이터를 수집하기 위하여 GUI (Graphical User Interface)를 제공하는 자신만의 자바 애플릿 (Java applet)를 만들 수 있습니다.

자바 애플릿 (Java applet)은 원격 TLServer PC로부터 다운로드할 수 있으며 로칼 PC상의 소프트웨어를 설치할 필요없이 이 자바 애플릿만을 어떠한 웹 브라우저 상에서든 실행시킬 수 있습니다. 이것은 사용자에게 사이버 까페 (PC방) 또는 웹 브라우저를 사용할 수 있는 어떠한 장소에서든 고객 여러분의 장치 또는 기계를 제어하거나 모니터링할 수 있는 프로그램을 만들 수 있다는 것을 의미합니다.

Triangle Research International사는 Super PLC사용자에게 API 라이브러리를 제공하므로서 사용자 자신의 자바 애플릿 (Java applet)를 사용자 스스로가 매우 쉽게 만들 수 있도록 지원하고 있습니다. 이러한 자바 (Java) API 클래스 라이브러리는 인터넷을 경유하여 PLC를 모니터링하거나 제어하고 또한 PLC의 웹서버 ("TLServer")에 데이터를 저장 보관하는 로깅기능을 대단히 간단하게 할 수 있도록 지원하고 있습니다. 예를 들면, 아래 좌측 그림의 간단한 애플릿은 PLC입력 #1과 출력 #1를 기동시키는 푸쉬버튼의 로직 상태와 PLC의 내부 시간을 연속적으로 모니터링할 수 있는 것으로서 아주 간단하고 매우 빠르게 만들 수 있습니다.

Notes :
윈도우-CE상의 포켓 인터넷 익스플로러는 불행하게도 현재 자바 애플릿를 지원하고 있지 않습니다. 따라서 포켓 IE에서 자바 애플릿을 사용하기 위해서는 Jeode JVM와 같은 프로그램을 설치하여야만 자바 애플릿을 원격으로 패치(Fetch)할 수가 있습니다.

그러나 같은 자바 (Java) API 통신 라이브러리를 사용하여 자바 (Java) "어플리케이션"을 만들 수가 있으며 좌측 위 사진에서 보시는 바와같이 PDA에서 이것을 실행 시킬 수 있습니다. PC상에서 자바(Java) GUI 어플리케이션을 만들고 이것을 HP Jornada pocket PC등에 복사하여 놓으면 됩니다. 이 PDA는 무선 네트워크 통신을 통해 PLC를 원격으로 모니터링하고 제어할 수 있는 왼쪽에 있는 그림과 같은 애플릿의 기능을 갖게됩니다.

 

 API 통신 라이브러리 (comm Library)를 사용한 애플릿 예
 

일반적으로 웹 브라우저에서 실행시킬 수 있는 PLC 제어 GUI 애플릿을 자바 API 라이브러리를 이용하여 만든다는 것은 결코 쉬운 일이 아닙니다. 하지만 위의 그림에 있는 예제 애플릿은 우리의 API를 사용하여 매우 쉽게 만들 수가 있습니다. 이 애플릿은 원격 PLC로부터 리얼타임클럭 데이터 및 입력 #1과 출력 #1의 로직 상태를 원격 수신하여 계속적으로 디스플레이하는 것입니다. "Input #1"의 라벨은 초록 색의 밝기 차이를 이용하여 PLC의 입력 #1 (Input #1)의 ON/OFF상태를 표시합니다. "Output #1" 라벨을 클릭할 때 PLC의 출력 #1을 강제로 토글시키는 푸쉬버튼입니다. 출력 #1 (Output #1)의 상태는 적색 버튼의 밝기 차이에 의해 그 상태를 표시합니다.

이 예제 애플릿의 완전한 소스 코드 리스트를 이곳 아래에 올려 놓았습니다. 아래 많은 프로그램 문장들 중에서 굵은 파란색의 문자들 만이 실제로 API 라이브러리하고 관계된 것입니다. 나머지 부분은 대부분의 자바 프로그램머들에게 이미 익숙해있는 평범한 자바 AWT입니다. PLC 자바 통신 라이브러리 "PLCmon.jar"에 대하여 더 공부를 하고 싶으신 분은 여기를 클릭하시기 바랍니다.

여러분은 또한 다른 플랫폼 상에서 실행 시킬 수 있는 여러분 자신만의 자바 어플리케이션 프로그램을 만들 수 있습니다. 왼쪽 사진은 Personal Java JVM (Sun 사이트에서 무료로 다운로드 받을 수 있음)을 설치한 HP Jornada Pocket PC상에서 똑같은 자바 프로그램으로 실행되고 있는 것을 보여주고 있습니다. PLC의 입력 #1 (Input #1) 및 출력 #1 (Output #1)의 로직 상태, 그리고 PLC 리얼타임클럭의 시간을 원격으로 읽을 수 있으며 출력 #1 (Output #1) 라벨을 클릭하면 PLC 출력 #1을 강제로 토글시킬 수 있습니다.

API 통신 라이브러리는 PC상에서 자신만의 자바 프로그램을 쉽게 작성하고 테스트를 해볼 수 있도록 하여 줍니다. 또한 작성된 프로그램을 간단하게 다른 플랫폼 또는 PDA에 설치하고 실행 시킬 수 있습니다. PDA 사진을 클릭하시면 큰 PDA 사진을 보실 수 있습니다.

import PLCmon.*;
import java.awt.*;
import java.applet.*;

public class TestApplet extends Applet
{
    String URLString = "127.0.0.1:9080"; // a localhost connection
    String username = "samples";
    String password = "";

    int [] DM = new int[4000]; // place holder for the Data Memory DM[1] to DM[4000]
    ConnectTLServer ctlsvr;
    Color darkGreen = new java.awt.Color(0,128,0);
    Color darkRed = new java.awt.Color(128,0,0);
    public void init()
    {
        //{{INIT_CONTROLS
        setLayout(null);
        setSize(120,120);
        panel1.setLayout(null);
        add(panel1);
        panel1.setBackground(new java.awt.Color(255,255,128));
        panel1.setBounds(0,0,120,120);
        RTC.setEditable(false);
        RTC.setText("Hello");
        panel1.add(RTC);
        RTC.setBackground(java.awt.Color.black);
        RTC.setForeground(java.awt.Color.red);
        RTC.setFont(new Font("Dialog", Font.BOLD, 16));
        RTC.setBounds(20,20,87,24);
        clockLabel.setText("PLC\'s Clock");
        clockLabel.setAlignment(java.awt.Label.CENTER);
        panel1.add(clockLabel);
        clockLabel.setBounds(20,0,84,24);
        output1Button.setLabel("Output1");
        panel1.add(output1Button);
        output1Button.setBackground(new java.awt.Color(128,0,0));
        output1Button.setForeground(java.awt.Color.yellow);
        output1Button.setFont(new Font("Dialog", Font.BOLD, 12));
        output1Button.setBounds(20,80,84,22);
        input1Label.setText("Input #1");
        input1Label.setAlignment(java.awt.Label.CENTER);
        panel1.add(input1Label);
        input1Label.setBackground(new java.awt.Color(0,128,0));
        input1Label.setForeground(java.awt.Color.yellow);
        input1Label.setFont(new Font("Dialog", Font.BOLD, 12));
        input1Label.setBounds(20,48,84,22);
        //}}
       
        ctlsvr = new ConnectTLServer(URLString, username, password);
        MonitorThread mt = new MonitorThread();
        mt.start();
   
        //{{REGISTER_LISTENERS
        SymMouse aSymMouse = new SymMouse();
        output1Button.addMouseListener(aSymMouse);
        //}}
    }
   
    //{{DECLARE_CONTROLS
    java.awt.Panel panel1 = new java.awt.Panel();
    java.awt.TextField RTC = new java.awt.TextField();
    java.awt.Label clockLabel = new java.awt.Label();
    java.awt.Button output1Button = new java.awt.Button();
    java.awt.Label input1Label = new java.awt.Label();
    //}}
   

    class MonitorThread extends Thread {
        private Action monAction[] = new Action[10]; // Don't make these monAction[] variable public
        public void run() { // to avoid writing action[] variables in other threds
            while (true) { // run forever (until program exits)
                readRTC(); // add the list of actions you wish to monitor here
                readIO();
                try {
                    Thread.sleep(200); // update every 0.2 second
                } catch (Exception e){}
            }
        }
   
        void readIO() { // Read the logic state of the inputs and outputs
            monAction[0] = new Action(1,ActionConstant.READSINGLE,ActionConstant.INPUT,1,0); // Read INPUT[1]
            monAction[1] = new Action(1,ActionConstant.READSINGLE,ActionConstant.OUTPUT,1,0); // Read OUTPUT[1]
            try {
                ctlsvr.commAction(monAction, 2); // Execute the two READ actions defined above
                if ((monAction[0].value & 0x0001)!=0) { // Test bit 0 of 16-bit variable INPUT[1]
                    input1Label.setBackground(Color.green); // it is ON, light up the label in GREEN
                }
                else {
                    input1Label.setBackground(darkGreen); // it is OFF, dim the label as dark green.
                }
                if ((monAction[1].value & 0x0001)!=0) { // Test bit 0 of 16-bit variable OUTPUT[1]
                    output1Button.setBackground(Color.red); // it is ON, light up the label in GREEN
                }
                else {
                    output1Button.setBackground(darkRed); // it is OFF, dim the label as dark green.
                }
            }
            catch (Exception e) {
                RTC.setText(e.toString()); // show the error message
                System.out.println(e);
            }
        }

        public void readRTC() { // Read the read time clock: Hours, Minutes and Seconds.
                            // the returned value for READSINGLE is contained in the integer variable "value".
            monAction[0] = new Action(1,ActionConstant.READSINGLE,ActionConstant.TIME ,1,0); // Read Hour
            monAction[1] = new Action(1,ActionConstant.READSINGLE,ActionConstant.TIME, 2,0); // Read Minute
            monAction[2] = new Action(1,ActionConstant.READSINGLE,ActionConstant.TIME, 3,0); // Read Second
   
            try {
                ctlsvr.commAction(monAction, 3); // Execute 3 actions defined above
                String RTCvalue = monAction[0].value +":"+ monAction[1].value+":"+ monAction[2].value;
                RTC.setText(RTCvalue);
            }
            catch (Exception e) {
                RTC.setText(e.toString()); // show the error message
                System.out.println(e);
            }
        }
    }

    class SymMouse extends java.awt.event.MouseAdapter
    {
        public void mouseReleased(java.awt.event.MouseEvent event)
        {
            Object object = event.getSource();
            if (object == output1Button)
                output1Button_MouseReleased(event);
        }

        public void mousePressed(java.awt.event.MouseEvent event)
        {
            Object object = event.getSource();
            if (object == output1Button)
                output1Button_MousePressed(event);
        }
    }
   

    void output1Button_MousePressed(java.awt.event.MouseEvent event) {
        Action writeAction[] = new Action[10];
            // to do: code goes here.
        writeAction[0] = new Action(1,ActionConstant.READSINGLE,ActionConstant.OUTPUT ,1,0); // Read OUTPUT[1]
        try {
            ctlsvr.commAction(writeAction, 1); // Execute 1 action defined above
            writeAction[0].actionType = ActionConstant.WRITESINGLE; // change to WRITESINGLE OUTPUT
            writeAction[0].value ^= 0x0001; // Toggle OUTPUT[1] bit 0
            ctlsvr.commAction(writeAction, 1); // Execute the action;
        }
        catch (Exception e) {
            RTC.setText(e.toString()); // show the error message
            System.out.println(e);
        }
    }

    void output1Button_MouseReleased(java.awt.event.MouseEvent event)
    {
        // to do: code goes here.
    }
}