ESP8266/ESP32 모듈 관련 자료는 전용 게시판으로 모두 이동되었습니다. 아래 문서의 최신 업데이트는 ESP8266 전용 게시판에서 확인하세요.

ESP8266 활용 가이드 목차

홈 오토메이션이나 다양한 IoT 프로젝트에서 WiFi 모듈의 필요성은 두말할 나위가 없습니다만 가장 큰 문제는 가격과 크기일 것입니다. WiFi 실드나 Serial WiFi 고급형 모듈은 가격과 크기 때문에 여러 프로젝트에 사용하기에는 좀 부담스럽죠. 그런 점에서 ESP8266 Serial WiFi 모듈의 장점이 빛납니다. WiFi 실드의 1/10, 고급형 Serial Wifi 모듈의 1/5 정도의 가격이면 되니까요. 비록 국내에서 구매가 안되고, 사용하기가 까다롭긴 하지만요.

지난 글에서 ESP8266 모듈의 기본 사용법에 대해 다루었는데, 모듈의 Serial Baudrate(통신속도)가 115200 으로 맞춰져 있어 사용하기가 여간 까다로운게 아니었습니다. 일반적으로 Bluetooth 모듈 사용할 때 쓰는 SoftwareSerial 라이브러리는 19200 속도까지만 지원하므로 HardwareSerial을 사용해야 하고 (PC에서 업로드 할 때는 모듈의 전원을 차단해야 함) 아두이노 Pro Mini 3.3v와 같이 8MHz 로 동작하는 보드에서는 115200 속도를 아예 사용할 수가 없습니다.

그래서 이번 글에서는 펌웨어 업데이트를 통해 ESP8266 모듈의 Serial 통신속도를 9600으로 맞추고 Bluetooth 모듈처럼 간단하게 연결해서 사용하는 방법을 다루고자 합니다.

(매뉴얼 작성에 redflag(지운아빠)님께서 많은 도움을 주셨습니다. 이 자리를 빌어 감사의 인사를 전합니다.)

1. 펌웨어 업데이트

먼저 아래 링크에서 펌웨어 업데이트 툴을 받습니다. (Windows 용)

https://docs.google.com/file/d/0B3dUKfqzZnlwVGc1YnFyUjgxelE/edit

실행파일 외에 링크에 포함된 .bin 파일은 최신으로 받아서 적용하셔야 합니다. 아래 링크에서 ESP8266_AT_V00180902_02_baudrate watchdog added 버전의 바이너리 파일을 받으세요. 이 버전으로 업데이트 하면 기본 baudrate 가 9600 으로 설정됩니다.

https://docs.google.com/file/d/0B3dUKfqzZnlwdUJUc2hkZDUyVjA/edit

이제 FTDI 모듈을 준비합니다. FTDI 모듈을 3.3v로 셋업하시고 아래 그림과 같이 6개의 핀을 연결해줍니다.

IMG_6499 ESP8266_V091

  • FTDI –> ESP8266
  • VCC (3.3v) –> VCC
  • VCC (3.3v) –> CH_PD
  • GND –> GND
  • GND –> GPIO0
  • TX –> URXD
  • RX –> UTXD

ESP8266 모듈의 8개의 핀 중 6개의 핀을 연결해줘야 합니다. 주의하실 점은 CH_PD 는 VCC, GPIO0 는 GND로 연결한다는 점입니다. CH_PD는 chip enable 핀으로 항상 VCC 로 연결되어야 합니다.(Flash boot 및 update mode 모드 상태로 설정) GPIO0 핀은 LOW status일 때 update 모드로 들어가도록 해줍니다. 따라서 펌웨어 업데이트 할 때는 GPIO0 핀을 GND로 묶어주고 일반적인 동작모드에서는 연결을 해제해 줍니다.

이제 앞서 다운로드 받은 펌웨어 업데이트 프로그램을 실행합니다. (esp8266_flasher.exe)

esp8266-update-02

먼저 1번 항목에 다운로드 받은 바이너리 파일(v0.9.2.2 AT Firmware.bin) 경로와 파일명을 입력해 줘야 합니다. BIN 버튼을 누르면 선택할 수 있는데 경로에 공백이나 2바이트 문자가 포함된 경우 인식이 안될 수 있습니다. 적당히 파일 경로를 바꿔주고 선택해줍니다.

2번 항목에 FTDI 모듈의 COM 포트를 입력해줍니다. FTDI 모듈을 연결하고 [내 컴퓨터 – 마우스 우클릭 – 속성 – 장치관리자] 에 들어가셔서 COM 포트 확인하시면 됩니다.

3번을 누르면 다운로드가 시작될 겁니다. 정상적으로 연결된 경우 99% 까지 진행되고 Leaving… 메시지까지 보일겁니다. 그럼 펌웨어 업데이트는 완료됩니다.

2. 아두이노와 연결

이제 ESP8266 모듈을 9600 통신속도로 사용할 수 있으므로 블루투스 모듈처럼 디지털 핀 2개에 TX, RX를 연결하고 SoftwareSerial 라이브러리로 사용할 수 있습니다.

ESP8266 – 아두이노를 다음과 같이 연결합니다. VCC – 3.3v, GND – GND 연결을 하고 TX, RX를 임의의 디지털핀에 연결합니다. 전 TX – D2, RX – D3 로 연결했습니다. 아래 그림에서는 초록색, 파란색 라인이 D0, D1 에 연결되어 있는데 이걸 바꿔주면 됩니다. 그리고 CH_PD – 3.3v로 연결해줍니다. GPIO0 핀은 연결할 필요가 없습니다.

weather-display1-569x390

그리고 ESP8266 모듈은 동작전압이 3.3v 이므로 5V 동작전압의 보드에서는 level shifting을 해주어야 합니다. 전 5v-3.3v level shift 모듈을 사용했지만 저항 2개를 이용해서 간단히 회로 만드셔도 됩니다. WiFi RX – 아두이노 TX 연결하는 선만 해주면 됩니다. 아래 링크 아래부분 댓글 참고. 
http://www.esp8266.com/viewtopic.php?f=8&t=6&sid=49f5396903eb3e078ccd6a2132be50cb 

3. 라이브러리 설치

인터넷 상에 대부분 소스들이 HardwareSerial 을 통해 115200 속도로 연결한 상태에서 작성한 소스입니다. 사용상 편의를 위해 9600 속도로 맞추었으므로 여기에 맞는 라이브러리를 사용해야 합니다. 아래 ESP8266 라이브러리는 SoftwareSerial을 통해 모듈을 제어할 수 있도록 작성된 라이브러리입니다.

https://github.com/Diaoul/arduino-ESP8266

라이브러리를 다운로드 받아 설치하시면 됩니다. 라이브러리에 포함된 예제 소스 Complete.ino 파일에는 거의 모든 라이브러리 사용법이 포함되어 있습니다. 소스를 분석해서 다양하게 활용하시면 됩니다.

4. 기본 HTTP Request – HTTP Response 예제

라이브러리를 설치하고 아래 예제를 실행해 볼겁니다. 상단의 SSID, PASS, DST_IP (목적지 URL 또는 IP) 를 자신의 환경에 맞게 수정하고 SoftwareSerial(2, 3); 코드에서 모듈의 TX, RX 핀이 연결된 핀 번호 바꿔주세요.

#include <SoftwareSerial.h>

#include "ESP8266.h"

#define SSID "xxxxxxxx"
#define PASS "xxxxxxxx"
#define DST_IP "220.181.111.85" //baidu.com

SoftwareSerial esp8266Serial = SoftwareSerial(2, 3);
ESP8266 wifi = ESP8266(esp8266Serial);

void setup()
{
    Serial.begin(9600);

    // ESP8266
    esp8266Serial.begin(9600);
    wifi.begin();
    wifi.setTimeout(1000);

    /****************************************/
    /******       Basic commands       ******/
    /****************************************/
    // test
    Serial.print("test: ");
    Serial.println(getStatus(wifi.test()));

    // restart
    Serial.print("restart: ");
    Serial.println(getStatus(wifi.restart()));

    // getVersion
    char version[16] = {};
    Serial.print("getVersion: ");
    Serial.print(getStatus(wifi.getVersion(version, 16)));
    Serial.print(" : ");
    Serial.println(version);


    /****************************************/
    /******        WiFi commands       ******/
    /****************************************/
    // joinAP
    Serial.print("joinAP: ");
    Serial.println(getStatus(wifi.joinAP(SSID, PASS)));


    /****************************************/
    /******       TCP/IP commands      ******/
    /****************************************/
    // connect
    Serial.print("connect: ");
    Serial.println(getStatus(wifi.connect(ESP8266_PROTOCOL_TCP, DST_IP, 80)));

    // send
    Serial.print("send: ");
    Serial.println(getStatus(wifi.send("GET / HTTP/1.0\r\n\r\n")));

}

void loop()
{
    /****************************************/
    /******        WiFi commands       ******/
    /****************************************/

    // read data
    unsigned int id;
    int length;
    int totalRead;
    char buffer[300] = {};

    if ((length = wifi.available()) > 0) {
      id = wifi.getId();
      totalRead = wifi.read(buffer, 300);

      if (length > 0) {
        Serial.print("Received ");
        Serial.print(totalRead);
        Serial.print("/");
        Serial.print(length);
        Serial.print(" bytes from client ");
        //Serial.print("from client ");
        Serial.print(id);
        Serial.print(": ");
        Serial.println((char*)buffer);
      }
    }
}

String getStatus(bool status)
{
    if (status)
        return "OK";

    return "KO";
}

String getStatus(ESP8266CommandStatus status)
{
    switch (status) {
    case ESP8266_COMMAND_INVALID:
        return "INVALID";
        break;

    case ESP8266_COMMAND_TIMEOUT:
        return "TIMEOUT";
        break;

    case ESP8266_COMMAND_OK:
        return "OK";
        break;

    case ESP8266_COMMAND_NO_CHANGE:
        return "NO CHANGE";
        break;

    case ESP8266_COMMAND_ERROR:
        return "ERROR";
        break;

    case ESP8266_COMMAND_NO_LINK:
        return "NO LINK";
        break;

    case ESP8266_COMMAND_TOO_LONG:
        return "TOO LONG";
        break;

    case ESP8266_COMMAND_FAIL:
        return "FAIL";
        break;

    default:
        return "UNKNOWN COMMAND STATUS";
        break;
    }
}

String getRole(ESP8266Role role)
{
    switch (role) {
    case ESP8266_ROLE_CLIENT:
        return "CLIENT";
        break;

    case ESP8266_ROLE_SERVER:
        return "SERVER";
        break;

    default:
        return "UNKNOWN ROLE";
        break;
    }
}

String getProtocol(ESP8266Protocol protocol)
{
    switch (protocol) {
    case ESP8266_PROTOCOL_TCP:
        return "TCP";
        break;

    case ESP8266_PROTOCOL_UDP:
        return "UDP";
        break;

    default:
        return "UNKNOWN PROTOCOL";
        break;
    }
}
  • wifi.joinAP : AP(공유기)에 연결
  • wifi.connect(ESP8266_PROTOCOL_TCP, DST_IP, 80) : 특정 서버와의 연결 설정, 연결에 성공하면 linked 상태가 됨
  • wifi.send(“GET / HTTP/1.0\r\n\r\n”) : 특정 주소로 Request를 전송
  • loop() 함수 안에서 request 날린 페이지의 응답을 버퍼로 읽어옵니다.
  • wifi.close() : 연결 설정을 해제합니다. unlink 상태가 됩니다.

Serial Monitor를 통해 모듈 Setup, Request 과정과 Response 데이터가 출력되는 과정을 확인하실 수 있습니다.

코드를 보시면…  loop() 함수 안에서 response 데이터를 계속 읽어와서 출력하도록 되어 있는데 일정 크기 이상은 읽어들이질 못합니다. Response 데이터가 크기가 크기 때문에 조금씩 읽어 들여야 하는데 현재 소스는 뭔가 문제가 있는 것 같습니다. 데이터를 아두이노로 다 읽어들이기 보다는 라이브러리에서 제공하는  find 함수들을 이용해서 원하는 문자열을 찾아나가는 방식으로 수정해서 사용하시길 권합니다.

더 상세한 내용과 다른 활용법은 더 테스트 해보고 추가하겠습니다.  라이브러리에 포함된 Complete.ino 파일을 참고하면 다양하게 활용할 수 있습니다.

참고자료 :