이 튜토리얼에서는 아두이노 Uno R4 WiFi를 웹 서버로 만드는 방법을 배울 것입니다. PC나 스마트폰의 웹 브라우저를 통해 아두이노 웹 서버에서 호스팅하는 웹 페이지에 접근함으로써, 아두이노에서 값을 읽거나 심지어 제어할 수 있게 됩니다. 아두이노 Uno WiFi를 프로그래밍하여 달성할 내용의 개요는 다음과 같습니다:
1 | × | Arduino UNO R4 WiFi | Amazon | |
1 | × | USB Cable Type-C | 쿠팡 | Amazon | |
1 | × | (Optional) 9V Power Adapter for Arduino | Amazon | |
1 | × | (Recommended) Screw Terminal Block Shield for Arduino UNO R4 | 쿠팡 | Amazon | |
1 | × | (Recommended) Breadboard Shield For Arduino UNO R4 | 쿠팡 | Amazon | |
1 | × | (Recommended) Enclosure For Arduino UNO R4 | Amazon | |
공개: 이 섹션에서 제공된 링크 중 일부는 제휴 링크입니다. 이 링크를 통해 구매한 경우 추가 비용없이 수수료를 받을 수 있습니다. 지원해 주셔서 감사합니다.
이것은 비교적 간단합니다. 아두이노 코드는 다음과 같은 작업을 수행합니다:
웹 브라우저로부터 HTTP 요청을 기다리는 웹 서버를 만듭니다.
웹 브라우저로부터 요청을 받으면, 아두이노는 다음 정보로 응답합니다:
아래는 위의 작업을 수행하는 아두이노 코드입니다:
#include <WiFiS3.h>
const char ssid[] = "YOUR_WIFI";
const char pass[] = "YOUR_WIFI_PASSWORD";
int status = WL_IDLE_STATUS;
WiFiServer server(80);
float getTemperature() {
return 26.9456;
float temp_x100 = random(0, 10000);
return temp_x100 / 100;
}
void setup() {
Serial.begin(9600);
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION)
Serial.println("Please upgrade the firmware");
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(10000);
}
server.begin();
printWifiStatus();
}
void loop() {
WiFiClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
String HTTP_header = client.readStringUntil('\n');
if (HTTP_header.equals("\r"))
break;
Serial.print("<< ");
Serial.println(HTTP_header);
}
}
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
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();
}
}
void printWifiStatus() {
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("signal strength (RSSI):");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");
}
위의 코드를 복사하여 Arduino IDE에서 엽니다
코드 내의 와이파이 정보(SSID 및 비밀번호)를 귀하의 것으로 변경합니다
Arduino IDE에서 Upload 버튼을 클릭하여 코드를 Arduino에 업로드합니다
시리얼 모니터를 엽니다
시리얼 모니터에서 결과를 확인하세요.
Attempting to connect to SSID: YOUR_WIFI
IP Address: 192.168.0.2
signal strength (RSSI):-39 dBm
표시된 IP 주소를 메모하고, 스마트폰이나 PC의 웹 브라우저 주소창에 이 주소를 입력하십시오.
그 결과, 시리얼 모니터에 다음과 같은 출력이 표시됩니다.
Attempting to connect to SSID: YOUR_WIFI
IP Address: 192.168.0.2
signal strength (RSSI):-41 dBm
New HTTP Request
<< GET / HTTP/1.1
<< Host: 192.168.0.2
<< Connection: keep-alive
<< Cache-Control: max-age=0
<< Upgrade-Insecure-Requests: 1
<< User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
<< Accept: text/html,application/xhtml+xml,application/xml
<< Accept-Encoding: gzip, deflate
<< Accept-Language: en-US,en;q=0.9
IP 주소를 사용하여 웹 브라우저에 접속하면, 아두이노 보드에 대한 정보를 표시하는 매우 기본적인 웹 페이지가 제시됩니다. 페이지는 다음과 같이 보일 것입니다:
이 웹 페이지를 그래픽 사용자 인터페이스(UI)로 멋지게 보이게 하려면 이 튜토리얼의 마지막 부분을 확인하세요.
아두이노에 연결된 것을 제어하는 것은 단순히 값을 읽는 것보다 조금 더 도전적입니다. 그 이유는 아두이노가 웹 브라우저로부터 받은 요청을 이해해야만 어떤 조치를 취할지 알 수 있기 때문입니다. 이 경우 아두이노 코드가 하는 일은 다음과 같습니다:
웹 브라우저로부터 HTTP 요청을 수신하기 위해 웹 서버를 만듭니다.
웹 브라우저로부터 받은 요청을 다음과 같이 처리합니다:
HTTP 요청 헤더를 읽습니다.
필요한 구체적인 제어 명령을 결정하기 위해 HTTP 요청 헤더를 분석합니다.
받은 제어 명령에 따라 아두이노에 연결된 장치나 대상을 제어합니다.
HTTP 응답을 보냅니다.
필요한 경우, 제어 상태에 대한 정보를 표시하기 위해 HTML 내용이 포함된 HTTP 응답 본문을 추가로 보낼 수 있습니다.
더 포괄적이고 자세한 예시를 원한다면, 아래에 나열된 튜토리얼을 확인하는 것을 추천합니다:
앞서 설명한 대로, 최소한의 콘텐츠를 가진 간단한 웹 페이지를 만들고 싶다면 HTML을 직접 Arduino 코드에 내장할 수 있습니다.
그러나 더 정교하고 인상적인 웹 페이지를 만들고 싶고 컨텐츠의 양이 많은 경우, 모든 HTML, CSS, 그리고 Javascript를 아두이노 코드에 직접 포함시키는 것은 불편해집니다. 이러한 상황에서 코드를 관리하는 다른 접근 방식을 사용할 수 있습니다:
아두이노 코드는 이전과 마찬가지로 .ino 파일에 배치될 것입니다.
HTML 코드(HTML, CSS, Javascript)는 별도의 .h 파일에 배치될 것입니다. 이렇게 하면 웹 페이지 내용을 아두이노 코드와 분리하여 관리하고 수정하기가 더 쉬워집니다.
이를 위해서는 두 가지 주요 단계를 수행해야 합니다:
로컬 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.
아래에 제공된 코드를 복사하여 만든 파일에 붙여넣으세요.
#include <WiFiS3.h>
#include "index.h"
const char ssid[] = "YOUR_WIFI";
const char pass[] = "YOUR_WIFI_PASSWORD";
int status = WL_IDLE_STATUS;
WiFiServer server(80);
float getTemperature() {
float temp_x100 = random(0, 10000);
return temp_x100 / 100;
}
void setup() {
Serial.begin(9600);
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION)
Serial.println("Please upgrade the firmware");
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(10000);
}
server.begin();
printWifiStatus();
}
void loop() {
WiFiClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
String HTTP_header = client.readStringUntil('\n');
if (HTTP_header.equals("\r"))
break;
Serial.print("<< ");
Serial.println(HTTP_header);
}
}
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
float temp = getTemperature();
String html = String(HTML_CONTENT);
html.replace("TEMPERATURE_MARKER", String(temp, 2));
client.println(html);
client.flush();
delay(10);
client.stop();
}
}
void printWifiStatus() {
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("signal strength (RSSI):");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");
}
아래 코드를 복사하여 index.h에 붙여넣으세요.
const char *HTML_CONTENT = R""""(
REPLACE_YOUR_HTML_CONTENT_HERE
)"""";
아래의 REPLACE_YOUR_HTML_CONTENT_HERE 라인을 이전에 준비한 HTML 내용으로 대체하십시오. 줄 바꿈 문자에 문제가 없습니다. 아래는 index.h 파일의 예입니다:
const char *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";
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();
}
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);
}
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 버튼을 클릭하여 아두이노에 코드를 업로드합니다
이전과 같이 웹 브라우저를 통해 아두이노 보드의 웹 페이지에 접근합니다. 아래와 같이 보일 것입니다:
보다 포괄적이고 상세한 설명을 원하신다면, Arduino - DS18B20 온도 센서를 통한 웹 튜토리얼을 참조해 주세요.
※ NOTE THAT:
index.h 파일 내의 HTML 내용에 변경 사항을 적용하지만 ArduinoGetStarted.com.ino 파일은 수정하지 않으면, 아두이노 IDE는 코드를 컴파일하고 ESP32에 업로드할 때 HTML 내용을 새롭게 하거나 업데이트하지 않습니다.
이 상황에서 아두이노 IDE로 HTML 내용을 업데이트하려면, ArduinoGetStarted.com.ino 파일에 수정 사항을 적용해야 합니다. 예를 들어, 빈 줄을 추가하거나 코멘트를 삽입할 수 있습니다. 이러한 조치는 프로젝트에 변경 사항이 있었다는 것을 IDE에 알리며, 업데이트된 HTML 내용이 업로드에 포함되도록 합니다.