이더넷 쉴드 사용

아두이노와 인터넷을 연결해서 사용할 수 있다면 아두이노를 다양하게 활용할 수 있을 것.

이더넷 모듈이나 쉴드와 접근가능한 IP가 있다면 쉽게 인터넷으로 통신할 수 있음.

아두이노 1
브레드보드 1
이더넷 쉴드 1
점퍼 케이블 4
RGB LED 1
330ohm 저항 3

우리는 RGB LED가 없어 LED 3개로 활용해 보도록 한다.

회로도

브레드보드 레이아웃

/*
 이더넷 쉴드를 이용한 웹서버 만들기 스케치입니다.

 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 modified 15 Nov 2014
 by Soohwan Kim 

 본 스케치는 위즈네트 아카데미를 참고하였습니다.
 http://wiznetacademy.com/
 */

#include <SPI.h>
#include <Ethernet.h>

#if defined(WIZ550io_WITH_MACADDRESS) //WIZ550io에 표시된 MAC 주소를 사용한다면
;
#else
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //mac 주소 입력
#endif

IPAddress ip(192,168,1,7);  //로컬 네트워크에서 유일한 IP를 사용해야 합니다.
IPAddress gateway( 192, 168, 1, 1 );
IPAddress subnet( 255, 255, 255, 0 );
// fill in your Domain Name Server address here:
IPAddress myDns(8, 8, 8, 8); // google puble dns

EthernetServer server(80); //80은 포트번호
void check_led_status();

#define RED_PORT 46     //RED rgb 핀
#define GREEN_PORT 44   //GREEN rgb 핀
#define BLUE_PORT 42    //BLUE rgb 핀

void setup() {
  Serial.begin(9600);
   while (!Serial) {
    ; //시리얼 포트가 연결 될 때까지 기다림, 레오나르도 경우만 필요
  }

  pinMode(RED_PORT, OUTPUT);    //RED 핀 출력 설정
  digitalWrite(RED_PORT, HIGH); //RED 핀 초기 설정으로 켜놓기

  pinMode(GREEN_PORT, OUTPUT);  //GREEN 핀 출력 설정
  pinMode(BLUE_PORT, OUTPUT);   //BLUE 핀 출력 설정

//이더넷 디바이스 초기화
#if defined __USE_DHCP__
#if defined(WIZ550io_WITH_MACADDRESS) //WIZ550io에 할당된 맥 주소를 사용할 경우
  Ethernet.begin();
#else
  Ethernet.begin(mac);
#endif  
#else
#if defined(WIZ550io_WITH_MACADDRESS) 
  Ethernet.begin(ip, myDns, gateway, subnet);
#else
  Ethernet.begin(mac, ip, myDns, gateway, subnet);
#endif  
#endif 

  //서버 연결 시작
  server.begin();
  Serial.println("WebServerControlLED");
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop() {

  //수신 클라이언트가 있는 지 확인
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    //http 요청이 빈 라인으로 끝났을 때 
    boolean currentLineIsBlank = true;
      String buffer = ""; //버퍼 선언
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        buffer += c;    //버퍼 할당
        Serial.write(c);

        if (c == '\n' && currentLineIsBlank) {
          //표준 http 응답 헤더 전송 시작
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          //본문(상황에 맞는 웹 페이지) 전달
          //client.println("<!DOCTYPE HTML>");, HTML5 사용시
          client.println("<html>");  //웹 페이지 작성은 HTML사용
          client.println("<body>");

          //LED에 상황을 판단한후 상태를 알림
      if (digitalRead(RED_PORT)>0) {   //빨간 불이면
            client.println("LED is <font color='red'>RED</font>"); //웹페이지에 LED is RED라고 표시, RED는 빨간색
          } else if (digitalRead(GREEN_PORT)>0) { 
            client.println("LED is <font color='green'>GREEN</font>");
          } else if (digitalRead(BLUE_PORT)>0) {
            client.println("LED is <font color='blue'>BLUE</font>");
          } else {
            client.println("LED is <font color='black'>OFF</font>");
          }

          //색 선택 부분 만들기
          client.println("<br />");
          client.println("<FORM method=\"get\" action=\"/led.cgi\">");
          client.println("<P> <INPUT type=\"radio\" name=\"status\" value=\"1\">RED");
          client.println("<P> <INPUT type=\"radio\" name=\"status\" value=\"2\">GREEN");
          client.println("<P> <INPUT type=\"radio\" name=\"status\" value=\"3\">BLUE");
          client.println("<P> <INPUT type=\"radio\" name=\"status\" value=\"0\">OFF");
          client.println("<P> <INPUT type=\"submit\" value=\"Submit\"> </FORM>");

          client.println("</body>");
          client.println("</html>");
          break;
        }
        if (c == '\n') {          
          currentLineIsBlank = true;
          buffer="";
        } 
        else if ( c == '\r') {
          //빨간 불을 선택하면
      if(buffer.indexOf("GET /led.cgi?status=1")>=0){
        //빨간 불 킴
        digitalWrite(RED_PORT, HIGH);
            digitalWrite(GREEN_PORT, LOW);
            digitalWrite(BLUE_PORT, LOW);

            //두번째 페이지 전송
        client.println("HTTP/1.1 200 OK");
        client.println("Content-Type: text/html");
        client.println();
        client.println("<html>");
        client.println("<body>");

        if (digitalRead(RED_PORT)>0) {
              client.println("LED is <font color='red'>RED</font>");
            } else if (digitalRead(GREEN_PORT)>0) { 
              client.println("LED is <font color='green'>GREEN</font>");
            } else if (digitalRead(BLUE_PORT)>0) {
              client.println("LED is <font color='blue'>BLUE</font>");
            } else {
              client.println("LED is <font color='black'>OFF</font>");
            }

            client.println("<br />");
        client.println("<a href=\"/led.htm\">Go to control-page</a>"); //다시 처음 페이지로 

        client.println("</body>");
        client.println("</html>");
        currentLineIsBlank = false;
        break;
       }

           //초록을 선택하면
           if(buffer.indexOf("GET /led.cgi?status=2")>=0){
         //초록 핀 킴
         digitalWrite(RED_PORT, LOW);
             digitalWrite(GREEN_PORT, HIGH);
             digitalWrite(BLUE_PORT, LOW);

             client.println("HTTP/1.1 200 OK");
             client.println("Content-Type: text/html");
         client.println();
         client.println("<html>");
         client.println("<body>");

         if (digitalRead(RED_PORT)>0) {
               client.println("LED is <font color='red'>RED</font>");
             } else if (digitalRead(GREEN_PORT)>0) { 
               client.println("LED is <font color='green'>GREEN</font>");
             } else if (digitalRead(BLUE_PORT)>0) {
               client.println("LED is <font color='blue'>BLUE</font>");
             } else {
               client.println("LED is <font color='black'>OFF</font>");
             }

         client.println("<br />");
         client.println("<a href=\"/led.htm\">Go to control-page</a>");

         client.println("</body>");
         client.println("</html>");
         currentLineIsBlank = false;
         break;
        }

            //파란 색을 선택하면
            if(buffer.indexOf("GET /led.cgi?status=3")>=0){
          digitalWrite(RED_PORT, LOW);
              digitalWrite(GREEN_PORT, LOW);
              digitalWrite(BLUE_PORT, HIGH);

          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<html>");
          client.println("<body>");

          if (digitalRead(RED_PORT)>0) {
                client.println("LED is <font color='red'>RED</font>");
              } else if (digitalRead(GREEN_PORT)>0) { 
                client.println("LED is <font color='green'>GREEN</font>");
              } else if (digitalRead(BLUE_PORT)>0) {
                client.println("LED is <font color='blue'>BLUE</font>");
              } else {
                client.println("LED is <font color='black'>OFF</font>");
              }

          client.println("<br />");
          client.println("<a href=\"/led.htm\">Go to control-page</a>");

          client.println("</body>");
          client.println("</html>");
          currentLineIsBlank = false;
          break;
        }

            //off를 선택했을 때
        if(buffer.indexOf("GET /led.cgi?status=0")>=0){
          digitalWrite(RED_PORT ,LOW);
              digitalWrite(GREEN_PORT, LOW);
              digitalWrite(BLUE_PORT, LOW);

          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
             client.println();
          client.println("<html>");
          client.println("<body>");

          if (digitalRead(RED_PORT)>0) {
                client.println("LED is <font color='red'>RED</font>");
              } else if (digitalRead(GREEN_PORT)>0) { 
                client.println("LED is <font color='green'>GREEN</font>");
              } else if (digitalRead(BLUE_PORT)>0) {
                client.println("LED is <font color='blue'>BLUE</font>");
              } else {
                client.println("LED is <font color='black'>OFF</font>");
              }

          client.println("<br />");
          client.println("<a href=\"/led.htm\">Go to control-page</a>");

          client.println("</body>");
          client.println("</html>");
          currentLineIsBlank = false;
          break;
        }
    } else{ //if( c != '\r') {

          currentLineIsBlank = false;
        }
      }
    }

    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

인터넷은 TCP/IP 프로토콜 기반의 네트워크. 아두이노와 이더넷 쉴드를 사용하기 위해 TCP/IP프로토콜 기반으로 하기 때문에 몇가지 초기 설정이 필요하다.

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
  1. MAC address : 물리적 네트워크에서 TCP/IP사용시 각 기기를 구별할 수 있는 고유한 주소가 필요. 해당 주소를 mac address라고 함.
IPAddress ip(192,168,1,7);  //로컬 네트워크에서 유일한 IP를 사용해야 합니다.
IPAddress gateway( 192, 168, 1, 1 );
IPAddress subnet( 255, 255, 255, 0 );
// fill in your Domain Name Server address here:
IPAddress myDns(8, 8, 8, 8); // google puble dns
  1. IP address : 네트워크 상에서 host를 구별하기 위한 수. 스케치 내부에서 ip주소를 할당해 주어야 함.
  2. gateway : 다른 네트워크 host와 통신시 중간에 gateway를 거쳐야 함.
  3. subnet : 현재 네트워크가 자신이 속한 네트워크인지 아닌지 구분하기 위해 사용.
  4. dns : 사람들이 IP주소를 기억하기 쉽게 바꾼 주소를 의미
  5. dns server address : dns가 dns server를 통하여 ip 주소로 변환되는데 이때 dns server의 주소를 의미.

이더넷쉴드를 사용하기 위해 아래 두개의 라이브러리가 필요.

#include <SPI.h>
#include <Ethernet.h>

하지만 WIZ550io를 사용한다면 제조사에서 제공되는 라이브러리로 대체 하여야 함. 스케치 버전에 맞는 라이브러리 사용.

클라이언트가 요청이 있으면 버퍼에 메세지를 저장합니다. 만약 다음 행 (\n)문자를 받고 다음 행이 비어있음이 확인되면 메세지가 다 전달된 것입니다. 이런 약속이 바로 http 프로토콜입니다.