ESP32/ESP32-WROOM-32

ESP-WROOM-32 보드 사용하기 2편(WIFI)

원원 2024. 5. 19. 00:59

안녕하세요. 오늘은 ESP32보드로 WIFI기능을 사용해보겠습니다. 

먼저 WIFI기능을 사용하기전에 알아야 할 개념과 WIFI를 이용해서 WEB으로 통신을 할것이므로 HTTP에 대해서도 알아보겠습니다.

1. ESP32 WIFI mode에는 3가지가 있습니다
1) AP(Access Point) MODE : 다른 디바이스들이 연결가능한 모드입니다. (공유기와 유사합니다)
예를들어 WIFI가 없는 곳에서 ESP32를 AP모드로 만들고 핸드폰에서 ESP32와 연결한다음 ESP32로부터 데이터를 받을 수 있습니다. 
2) STA(station) MODE : 공유기에 접속할수있는 모드입니다. 
3) STA+AP MODE : AP모드와 STA모드 모두를 사용할 수 있는 모드입니다.
예를들어 초기에 STA모드로 설정하여 WIFI에 연결하고 WIFI연결이 실패했을때 AP모드로 설정합니다. 그리고나서 핸드폰으로 ESP32와 연결을해서 ESP32에게 다른 WIFI의 SSID와 PASSWORD를 알려주면 ESP32가 다시 STA모드로 WIFI연결을 시도하게 할 수도 있습니다.

2. 고정IP/동적IP 설정 (STA모드 사용시)
1) 동적 IP : ESP32의 주소를 공유기가 정해서 할당해주게 됩니다.
2) 고정 IP : 디바이스에서 사용하고싶은 IP를 정해서 공유기에게 요청합니다

3. 포트번호설정
1) 사용하는 프로토콜에 맞게 포트번호를 설정해줘야합니다. 해당 글에서는 HTTP 프로토콜을 사용할것입니다 (80번)

4. HTTP통신 기본동작 (ESP32입장)
1) ESP32 -> 공유기 [접속시도]
2) 클라이언트 요청 대기 [request]
3) 요청 처리 (get or post)
4) 응답전송 (Response)
5) 연결 종료

5. HTTP프로토콜에서의 GET/POST방식(클라이언트가 서버로 요청을 보낼 때 사용)
1) GET 방식 : URL의 끝에 데이터 첨부하여 전송
2) POST 방식 : 요청 본문에 데이터를 포함하여 전송


예제1) Hello world 출력하기
(STA방식, 동적IP, GET방식 )
코드에서 ssid, password변수에 연결할 ID랑 PASSWORD 적어주면 됩니다
ESP32->공유기 접속을 시도합니다. 접속이 안된다면 "."을 계속 출력하고 접속이 된다면 부여받은 IP를 표시해줍니다.
loop()문에서 클라이언트를 연결했는지 확인합니다. 연결확인이 되면 클라이언트에서 요청한 데이터를 읽어서 시리얼모니터에 표시해주고 클라이언트에게 Hello world를 보내줍니다

#include <WiFi.h>

const char* ssid     = "my_wifi";
const char* password = "12345678";

WiFiServer server(80);


void setup() {
  Serial.begin(115200);
  Serial.println(String("Connect try : ") + ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  while(WiFi.status() != WL_CONNECTED )
  {
    delay(500);
    Serial.println(".");
  }
  Serial.print(String("WIFI conneted\n IP : "));
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop() {
  WiFiClient client = server.available();

  if(!client)
  {
    return;
  }
  Serial.println("Clienct connected");
  client.setTimeout(10000);
  
  while(client.available())
  {
    Serial.write(client.read());
  }
  client.print("Hello world");
}

- Reset시 시리얼모니터(wifi 연결 성공시)

- 클라이언트의 요청이후 수신받은데이터 

- 클라이언트의 요청시 수신받은 Hello world 

PC
핸드폰


수신받은 데이터에 GET / HTTP/1.1 부분이 있습니다. 여기서 클라이언트가 요청한 URL에 따라서 데이터가 나옵니다
예) 192.168.0.6/ABCD 입력

GET /뒤에나온 문자열로 ESP32에서 원하는 동작을 하면 됩니다.
그리고 컴퓨터나 핸드폰에서 ESP32에서 보냈던 데이터를 읽을때 인터넷을 사용하므로 HTTP 문법에 맞게 ESP32가 보내주면 버튼이나 그래프같은 UI를 클라이언트가 볼 수도 있습니다.


예제2) 하이퍼링크 클릭해서 LED 표시하기
(STA방식, 고정IP, GET방식 )

#include <WiFi.h>

const char* ssid     = "my_wifi";
const char* password = "12345678";

WiFiServer server(80);


void setup() {
  pinMode(15,OUTPUT);
  Serial.begin(115200);
  Serial.println(String("Connect try : ") + ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  while(WiFi.status() != WL_CONNECTED )
  {
    delay(500);
    Serial.println(".");
  }
  Serial.print(String("WIFI conneted\n IP : "));
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop() {
  WiFiClient client = server.available();
  String request = "";

  if(!client)
  {
    return;
  }
  Serial.println("Clienct connected");
  while(client.available())
  {
    char c = client.read();
    request += c;
  }
  Serial.println(request);

  if(request.indexOf("GET /H") != -1)
  {
    digitalWrite(15,HIGH);
  }
  else if(request.indexOf("GET /L") != -1)
  {
    digitalWrite(15,LOW);
  }

  client.println("HTTP/1.1 200 OK");
  client.println("Content-type:text/html");
  client.println();
  client.print("<link rel=\"shortcut icon\" href=\"#\">");
  client.print("Click <a href=\"/H\">here</a> to turn the LED on pin 15 on.<br>");
  client.print("Click <a href=\"/L\">here</a> to turn the LED on pin 15 off.<br>");
  client.println();
  client.stop();
}

하이퍼링크를 만들어서 클라이언트가 here를 클릭하면 led를 on/off 했습니다.


예제3) 입력창에 글자를 입력해서 LED 표시하기
(STA방식, 동적 IP, POST방식 )

아래의 함수에 handle을 만들어서 넘겨주면 손쉽게 처리할수있습니다.
"/"는 루트 디렉토리를 의미합니다
  server.on("/", handleRoot);
  server.on("/led", handleLed);

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>

const char* ssid = "my_wifi";
const char* password = "12345678";

WebServer server(80);

void handleRoot() {
    String postForms = "<html>\
    <head>\
      <title>ESP32 POST </title>\
      <style>\
        body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
      </style>\
    </head>\
    <body>\
      <h1> Title </h1><br>\
      led1 status = $$led$$\
      <form method=\"post\" action=\"/led\">\
        <br>0 = led OFF, 1 = led ON<br>\
        <input type=\"text\" name=\"led1\" value=\"\"><br>\
        <input type=\"submit\" value=\"Submit\">\
      </form>\
    </body>\
  </html>";

  bool myled = digitalRead(15);
  if(myled)
  {
    postForms.replace("$$led$$","ON");
  }
  else
  {
    postForms.replace("$$led$$","OFF");
  }
  server.send(200, "text/html", postForms);
}

void handleLed() {
  for(int i=0; i<server.args() ; i++)
  {
    Serial.print(server.argName(i));
    Serial.print(",");
    Serial.print(server.arg(i));
    Serial.println();
    if(server.argName(i) == "led1")
    {
      if(server.arg(i) == "0")
      {
        digitalWrite(15,LOW);
      }
      else if(server.arg(i) == "1")
      {
        digitalWrite(15,HIGH);
      }
    }
  }
  String res = "<meta http-equiv=\"refresh\" content=\"0; url=http://"+WiFi.localIP().toString()+"\">";
  server.send(200, "text/html",res);
}

void handleNotFound() {
  String message = "File Not Found\n\n";
  server.send(404, "text/plain", message);
}

void setup(void) {
  pinMode(15,OUTPUT);
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp32")) {
    Serial.println("MDNS responder started");
  }

  server.on("/", handleRoot);
  server.on("/led", handleLed);


  server.on("/inline", []() {
    server.send(200, "text/plain", "this works as well");
  });

  server.onNotFound(handleNotFound);

  server.begin();
}

void loop(void) {
  server.handleClient();
}


참고글 : https://bota.tistory.com/2157