이 튜토리얼에서는 아두이노 Uno R4 WiFi를 웹 서버로 만드는 방법을 배울 것입니다. PC나 스마트폰의 웹 브라우저를 통해 아두이노 웹 서버에서 호스팅하는 웹 페이지에 접근함으로써, 아두이노에서 값을 읽거나 심지어 제어할 수 있게 됩니다. 아두이노 Uno WiFi를 프로그래밍하여 달성할 내용의 개요는 다음과 같습니다:
아두이노 웹 서버 - 단일 페이지: 이것은 웹 인터페이스를 통해 아두이노의 센서 값을 모니터링할 수 있게 해줍니다.
아두이노 웹 서버 - 단일 페이지: 웹 브라우저를 사용하여 아두이노를 제어할 수 있는 기능을 활성화할 것입니다.
아두이노 웹 서버 - 단일 페이지: 아두이노 IDE 내에서 다른 파일로 HTML 내용(HTML, CSS, 및 자바스크립트)을 분리하는 방법을 배울 것입니다.
아두이노 웹 서버 - 다중 페이지: 이 단계에서는 index.html, temperature.html, led.html, error_404.html, error_405.html 등과 같은 여러 페이지를 만들 것입니다..., 그리고 더 많은 페이지를 생성합니다.
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
아두이노에서 웹을 통해 센서 값 읽기
이것은 비교적 간단합니다. 아두이노 코드는 다음과 같은 작업을 수행합니다:
웹 브라우저로부터 HTTP 요청을 기다리는 웹 서버를 만듭니다.
웹 브라우저로부터 요청을 받으면, 아두이노는 다음 정보로 응답합니다:
HTTP 헤더
HTTP 본문: 이것은 HTML 내용과 센서에서 읽은 값을 포함합니다.
아래는 위의 작업을 수행하는 아두이노 코드입니다:
/* * 이 아두이노 코드는 newbiely.kr 에서 개발되었습니다 * 이 아두이노 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino/arduino-web-server */#include <WiFiS3.h>constchar ssid[] = "YOUR_WIFI"; // 네트워크 SSID(이름)을 바꾸세요constchar pass[] = "YOUR_WIFI_PASSWORD"; // 네트워크 비밀번호를 바꾸세요 (WPA용이나 WEP의 키로 사용하세요)intstatus = WL_IDLE_STATUS;WiFiServer server(80);floatgetTemperature() {return 26.9456;// 여기에 센서 구현을 넣으세요// 온도 값을 시뮬레이트합니다float temp_x100 = random(0, 10000); // 0에서 10000까지의 무작위 값return temp_x100 / 100; // 0에서 100까지의 시뮬레이트된 온도 값을 float 형태로 반환합니다}voidsetup() {//시리얼을 초기화하고 포트가 열릴 때까지 기다립니다:Serial.begin(9600);String fv = WiFi.firmwareVersion();if (fv < WIFI_FIRMWARE_LATEST_VERSION)Serial.println("Please upgrade the firmware");// WiFi 네트워크에 연결을 시도합니다:while (status != WL_CONNECTED) {Serial.print("Attempting to connect to SSID: ");Serial.println(ssid);// WPA/WPA2 네트워크에 연결합니다. 오픈 또는 WEP 네트워크를 사용하는 경우 이 줄을 변경하세요:status = WiFi.begin(ssid, pass);// 연결을 위해 10초간 대기합니다:delay(10000); } server.begin();// 이제 연결되었으므로 상태를 출력합니다:printWifiStatus();}voidloop() {// 들어오는 클라이언트를 청취합니다WiFiClient client = server.available();if (client) {// HTTP 요청 헤더를 한 줄씩 읽습니다while (client.connected()) {if (client.available()) {String HTTP_header = client.readStringUntil('\n'); // HTTP 요청의 헤더 줄을 읽습니다if (HTTP_header.equals("\r")) // HTTP 요청의 끝break;Serial.print("<< ");Serial.println(HTTP_header); // 시리얼 모니터에 HTTP 요청을 출력합니다 } }// HTTP 응답을 보냅니다// HTTP 응답 헤더를 보냅니다 client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // 응답 완료 후 연결이 닫힙니다 client.println(); // HTTP 헤더와 본문 사이의 구분자// HTTP 응답 본문을 보냅니다 client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<head>"); client.println("<link rel=\"icon\" href=\"data:,\">"); client.println("</head>"); client.println("<p>"); client.print("Temperature: <span style=\"color: red;\">");float temperature = getTemperature(); client.print(temperature, 2); client.println("°C</span>"); client.println("</p>"); client.println("</html>"); client.flush();// 웹 브라우저가 데이터를 받는 시간을 줍니다delay(10);// 연결을 닫습니다: client.stop(); }}voidprintWifiStatus() {// 보드의 IP 주소를 출력합니다:Serial.print("IP Address: ");Serial.println(WiFi.localIP());// 수신된 신호 강도를 출력합니다:Serial.print("signal strength (RSSI):");Serial.print(WiFi.RSSI());Serial.println(" dBm");}
Message (Enter to send message to 'Arduino Uno' on 'COM15')
New Line
9600 baud
Arduino Uno R4 WiFi - Web Server
Connecting to YOUR_WIFI_SSID
connected!
IP address: 192.168.0.254
Starting web server on IP: 192.168.0.254
=== Web Server Ready! ===
Visit: http://192.168.0.254
Ln 11, Col 1
Arduino Uno on COM15
2
표시된 IP 주소를 메모하고, 스마트폰이나 PC의 웹 브라우저 주소창에 이 주소를 입력하십시오.
그 결과, 시리얼 모니터에 다음과 같은 출력이 표시됩니다.
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Uno
Newbiely.ino
···
8Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Uno' on 'COM15')
New Line
9600 baud
Arduino Uno R4 WiFi - Web Server
Connecting to YOUR_WIFI_SSID
connected!
IP address: 192.168.0.254
Starting web server on IP: 192.168.0.254
=== Web Server Ready! ===
Visit: http://192.168.0.254
Method: GET
Requested path: /
Client disconnected
Ln 11, Col 1
Arduino Uno on COM15
2
IP 주소를 사용하여 웹 브라우저에 접속하면, 아두이노 보드에 대한 정보를 표시하는 매우 기본적인 웹 페이지가 제시됩니다. 페이지는 다음과 같이 보일 것입니다:
이 웹 페이지를 그래픽 사용자 인터페이스(UI)로 멋지게 보이게 하려면 이 튜토리얼의 마지막 부분을 확인하세요.
웹을 통해 아두이노 제어하기
아두이노에 연결된 것을 제어하는 것은 단순히 값을 읽는 것보다 조금 더 도전적입니다. 그 이유는 아두이노가 웹 브라우저로부터 받은 요청을 이해해야만 어떤 조치를 취할지 알 수 있기 때문입니다. 이 경우 아두이노 코드가 하는 일은 다음과 같습니다:
웹 브라우저로부터 HTTP 요청을 수신하기 위해 웹 서버를 만듭니다.
웹 브라우저로부터 받은 요청을 다음과 같이 처리합니다:
HTTP 요청 헤더를 읽습니다.
필요한 구체적인 제어 명령을 결정하기 위해 HTTP 요청 헤더를 분석합니다.
받은 제어 명령에 따라 아두이노에 연결된 장치나 대상을 제어합니다.
HTTP 응답을 보냅니다.
필요한 경우, 제어 상태에 대한 정보를 표시하기 위해 HTML 내용이 포함된 HTTP 응답 본문을 추가로 보낼 수 있습니다.
더 포괄적이고 자세한 예시를 원한다면, 아래에 나열된 튜토리얼을 확인하는 것을 추천합니다:
앞서 설명한 대로, 최소한의 콘텐츠를 가진 간단한 웹 페이지를 만들고 싶다면 HTML을 직접 Arduino 코드에 내장할 수 있습니다.
그러나 더 정교하고 인상적인 웹 페이지를 만들고 싶고 컨텐츠의 양이 많은 경우, 모든 HTML, CSS, 그리고 Javascript를 아두이노 코드에 직접 포함시키는 것은 불편해집니다. 이러한 상황에서 코드를 관리하는 다른 접근 방식을 사용할 수 있습니다:
아두이노 코드는 이전과 마찬가지로 .ino 파일에 배치될 것입니다.
HTML 코드(HTML, CSS, Javascript)는 별도의 .h 파일에 배치될 것입니다. 이렇게 하면 웹 페이지 내용을 아두이노 코드와 분리하여 관리하고 수정하기가 더 쉬워집니다.
이를 위해서는 두 가지 주요 단계를 수행해야 합니다:
HTML 콘텐츠 준비 중
아두이노 프로그래밍
HTML 컨텐츠 준비하기
로컬 PC에 UI 디자인용 HTML 내용(HTML, CSS 및 Javascript 포함)이 담긴 HTML 파일을 생성하세요.
HTML 파일 내에서 Arduino에서 오는 데이터가 표시될 곳에는 임의의 값을 사용하세요.
만족할 때까지 테스트하고 수정하세요.
HTML 파일에서 Arduino에서 온 데이터가 표시될 곳에 임의의 값을 예를 들어, TEMPERATURE_MARKER와 같은 특별한 이름으로 교체하세요. 나중에 Arduino 코드에서 String.replace("TEMPERATURE_MARKER", real_value); 함수를 사용하여 Arduino에서 제공한 값을 업데이트할 것입니다.
Arduino IDE에서 .h 파일에 HTML 내용을 넣을 것입니다. 다음 단계를 참조하세요.
아두이노 프로그래밍
아두이노 IDE를 열고 새 스케치를 만듭니다. 이름을 지정하세요. 예를 들어, ArduinoGetStarted.com.ino.
아래에 제공된 코드를 복사하여 만든 파일에 붙여넣으세요.
/* * 이 아두이노 코드는 newbiely.kr 에서 개발되었습니다 * 이 아두이노 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino/arduino-web-server */#include <WiFiS3.h>#include"index.h"constchar ssid[] = "YOUR_WIFI"; // 네트워크 SSID (이름)를 변경하십시오.constchar pass[] = "YOUR_WIFI_PASSWORD"; // 네트워크 비밀번호를 변경하십시오. (WPA 사용 시, 또는 WEP 키로 사용)intstatus = WL_IDLE_STATUS;WiFiServer server(80);floatgetTemperature() {// 여기에 센서 구현을 넣으세요.// 온도 값을 시뮬레이션합니다.float temp_x100 = random(0, 10000); // 0부터 10000까지의 임의의 값return temp_x100 / 100; // 0부터 100까지의 시뮬레이션된 온도값을 float로 반환}voidsetup() {//시리얼을 초기화하고 포트가 열릴 때까지 기다립니다:Serial.begin(9600);String fv = WiFi.firmwareVersion();if (fv < WIFI_FIRMWARE_LATEST_VERSION)Serial.println("Please upgrade the firmware");// WiFi 네트워크에 연결을 시도합니다:while (status != WL_CONNECTED) {Serial.print("Attempting to connect to SSID: ");Serial.println(ssid);// WPA/WPA2 네트워크에 연결합니다. 오픈 또는 WEP 네트워크를 사용하는 경우 이 줄을 변경하십시오:status = WiFi.begin(ssid, pass);// 연결을 위해 10초간 대기합니다:delay(10000); } server.begin();// 이제 연결되었으므로 상태를 출력합니다:printWifiStatus();}voidloop() {// 들어오는 클라이언트를 청취합니다WiFiClient client = server.available();if (client) {// 한 줄씩 HTTP 요청 헤더를 읽습니다while (client.connected()) {if (client.available()) {String HTTP_header = client.readStringUntil('\n'); // HTTP 요청의 헤더 줄을 읽습니다.if (HTTP_header.equals("\r")) // HTTP 요청의 끝break;Serial.print("<< ");Serial.println(HTTP_header); // 시리얼 모니터에 HTTP 요청을 출력합니다. } }// HTTP 응답을 보냅니다.// HTTP 응답 헤더를 보냅니다. client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // 응답 완료 후 연결이 종료됩니다. client.println(); // HTTP 헤더와 본문 사이의 구분자// HTTP 응답 본문을 보냅니다.float temp = getTemperature();String html = String(HTML_CONTENT); html.replace("TEMPERATURE_MARKER", String(temp, 2)); // 마커를 실제 값으로 바꿉니다. client.println(html); client.flush();// 웹 브라우저가 데이터를 받는 시간을 줍니다.delay(10);// 연결을 종료합니다: client.stop(); }}voidprintWifiStatus() {// 보드의 IP 주소를 출력합니다:Serial.print("IP Address: ");Serial.println(WiFi.localIP());// 수신 신호 강도를 출력합니다:Serial.print("signal strength (RSSI):");Serial.print(WiFi.RSSI());Serial.println(" dBm");}
코드에서 WiFi 정보(SSID 및 비밀번호)를 자신 것으로 변경하세요
Arduino IDE에서 index.h 파일을 생성하세요:
시리얼 모니터 아이콘 바로 아래에 있는 버튼을 클릭하고 새 탭을 선택하거나 Ctrl+Shift+N 키를 사용하세요.
파일 이름을 index.h로 지정하고 OK 버튼을 클릭하세요.
아래 코드를 복사하여 index.h에 붙여넣으세요.
/* * 이 아두이노 코드는 newbiely.kr 에서 개발되었습니다 * 이 아두이노 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino/arduino-web-server */constchar *HTML_CONTENT = R""""(REPLACE_YOUR_HTML_CONTENT_HERE)"""";
아래의 REPLACE_YOUR_HTML_CONTENT_HERE 라인을 이전에 준비한 HTML 내용으로 대체하십시오. 줄 바꿈 문자에 문제가 없습니다. 아래는 index.h 파일의 예입니다:
/* * 이 아두이노 코드는 newbiely.kr 에서 개발되었습니다 * 이 아두이노 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino/arduino-web-server */constchar *HTML_CONTENT = R""""(<!DOCTYPE html><html><head><title>Arduino - Web Temperature</title><meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7"><meta charset="utf-8"><link rel="icon" href="https://diyables.io/images/page/diyables.svg"><style>body { font-family: "Georgia"; text-align: center; font-size: width/2pt;}h1 { font-weight: bold; font-size: width/2pt;}h2 { font-weight: bold; font-size: width/2pt;}button { font-weight: bold; font-size: width/2pt;}</style><script>var cvs_width = 200, cvs_height = 450;function init() { var canvas = document.getElementById("cvs"); canvas.width = cvs_width; canvas.height = cvs_height + 50; var ctx = canvas.getContext("2d"); ctx.translate(cvs_width/2, cvs_height - 80); update_view(TEMPERATURE_MARKER);}function update_view(temp) { var canvas = document.getElementById("cvs"); var ctx = canvas.getContext("2d"); var radius = 70; var offset = 5; var width = 45; var height = 330; ctx.clearRect(-cvs_width/2, -350, cvs_width, cvs_height); ctx.strokeStyle="blue"; ctx.fillStyle="blue";//5-step Degree var x = -width/2; ctx.lineWidth=2;for (var i = 0; i <= 100; i+=5) { var y = -(height - radius)*i/100 - radius - 5; ctx.beginPath(); ctx.lineTo(x, y); ctx.lineTo(x - 20, y); ctx.stroke(); }//20-step Degree ctx.lineWidth=5;for (var i = 0; i <= 100; i+=20) { var y = -(height - radius)*i/100 - radius - 5; ctx.beginPath(); ctx.lineTo(x, y); ctx.lineTo(x - 25, y); ctx.stroke(); ctx.font="20px Georgia"; ctx.textBaseline="middle"; ctx.textAlign="right"; ctx.fillText(i.toString(), x - 35, y); }// shape ctx.lineWidth=16; ctx.beginPath(); ctx.arc(0, 0, radius, 0, 2 * Math.PI); ctx.stroke(); ctx.beginPath(); ctx.rect(-width/2, -height, width, height); ctx.stroke(); ctx.beginPath(); ctx.arc(0, -height, width/2, 0, 2 * Math.PI); ctx.stroke(); ctx.fillStyle="#e6e6ff"; ctx.beginPath(); ctx.arc(0, 0, radius, 0, 2 * Math.PI); ctx.fill(); ctx.beginPath(); ctx.rect(-width/2, -height, width, height); ctx.fill(); ctx.beginPath(); ctx.arc(0, -height, width/2, 0, 2 * Math.PI); ctx.fill(); ctx.fillStyle="#ff1a1a"; ctx.beginPath(); ctx.arc(0, 0, radius - offset, 0, 2 * Math.PI); ctx.fill(); temp = Math.round(temp * 100) / 100; var y = (height - radius)*temp/100.0 + radius + 5; ctx.beginPath(); ctx.rect(-width/2 + offset, -y, width - 2*offset, y); ctx.fill(); ctx.fillStyle="red"; ctx.font="bold 34px Georgia"; ctx.textBaseline="middle"; ctx.textAlign="center"; ctx.fillText(temp.toString() + "°C", 0, 100);}window.onload = init;</script></head><body><h1>Arduino - Web Temperature</h1><canvas id="cvs"></canvas></body></html>)"""";
이제 코드를 두 파일에 가지고 있습니다: ArduinoGetStarted.com.ino와 index.h
아두이노 IDE에서 Upload 버튼을 클릭하여 아두이노에 코드를 업로드합니다
이전과 같이 웹 브라우저를 통해 아두이노 보드의 웹 페이지에 접근합니다. 아래와 같이 보일 것입니다:
index.h 파일 내의 HTML 내용에 변경 사항을 적용하지만 ArduinoGetStarted.com.ino 파일은 수정하지 않으면, 아두이노 IDE는 코드를 컴파일하고 ESP32에 업로드할 때 HTML 내용을 새롭게 하거나 업데이트하지 않습니다.
이 상황에서 아두이노 IDE로 HTML 내용을 업데이트하려면, ArduinoGetStarted.com.ino 파일에 수정 사항을 적용해야 합니다. 예를 들어, 빈 줄을 추가하거나 코멘트를 삽입할 수 있습니다. 이러한 조치는 프로젝트에 변경 사항이 있었다는 것을 IDE에 알리며, 업데이트된 HTML 내용이 업로드에 포함되도록 합니다.