이전 글 "아두이노 - ESP01 웹서버를 이용하여 웹페이지에서 디지털핀 원격제어, WiFiEsp.h"에서는 ESP01의 웹서버를 이용하여 웹페이지에 버튼의 상태를 보여줌으로써 웹페이지를 통해 아두이노의 디지털 핀을 제어할 수 있었다. 이번에는 웹페이지를 이용하여 공유기에 연결하기 위한 아이디와 비밀번호를 변경하고 변경된 새로운 아이디와 비밀번호로 공유기에 접속하도록 해보자. 이러한 기능은 ESP8266 / ESP32 개발 보드용 라이브러리 wifimanager에서 구현되고 있는 기능이지만 아두이노용 라이브러리는 찾을 수가 없었다. 이 기능은 스케치상에서 설정한 공유기 아이디와 비밀번호를 사용하지 못하는 경우(또는 연결 장소가 변경된 경우)에 아두이노 IDE에서 새로운 아이디와 비밀번호를 업로드하지 않고도 스마트폰과 ESP01의 soft AP 연결을 통해 아이디 및 비밀번호를 변경하고 공유기에 연결을 시킬 수 있게 된다.
아두이노에서 이를 구현하기 위해서는 WiFiEsp.h 라이브러리의 웹서버와 EEPROM 그리고 Flash Memory에서 html 코드를 읽도록 하는 RPOGMEM 지시어를 사용해야만 한다.
우선 작동 상황을 살펴보면 아래와 같다.
1. ESP01을 staion and soft AP 모드로 작동시킨다.
2. station 모드로 공유기에 연결한다. 만약 연결에 실패할 경우(약 10초 뒤) while 루프를 빠져나간다.
soft AP를 활성화시킨다.
3. 할당받은 ip주소를 확인하기 위해 스마트폰 와이파이 프로그램에서 soft AP 연결에 연결한다.
스마트폰 와이파이 연결용 프로그램에서 "esp01_AP"를 찾아 ESP01의 soft AP에 연결한 뒤 웹브라우저 주소 창에 "192.168.4.1/ip" 주소를 입력하여 ip주소 확인 페이지로 연결한다. 이때 station 모드가 공유기에 연결된 상태에 따라 표시하는 웹페이지 html이 선택적으로 전송된다.
3-1. 공유기에 연결된 경우
공유기에 연결이 된 상태이므로 공유기에서 할당받은 ip주소를 표시하고 공유기 연결을 변경할 경우를 위해 와이파이 설정 버튼을 표시한다.
와이파이 설정 버튼을 클릭할 경우 새로운 아이디와 비밀번호를 입력할 텍스트 상자를 표시한다.
3-2. 공유기에 연결이 안 된 경우
공유기 연결이 실패했으므로 ip주소를 표시하지 않고 와이파이 설정 버튼을 표시한다.
와이파이 설정 버튼을 클릭할 경우 새로운 아이디와 비밀번호를 입력할 텍스트 상자를 표시한다.
4. 저장 버튼을 클릭하면 아두이노 EEPROM에 아이디와 비밀번호 값이 저장되고 그 값을 이용하여 공유기 연결을 시도하고 연결에 성공하면 EEPROM에 아이디와 비밀번호를 저장한다.
5. 아두이노가 리셋이 되었을 경우 변경된 아이디와 비밀번호를 EEPROM에서 읽어와 공유기에 연결을 시도한다.
EEPROM 인덱스(0 ~ 1023) 별 저장 테이터를 아래와 같이 설정하기로 하자.
- EEPROM 초기 플래그 저장 주소: 1023
- 아이디 전체 크기 값 저장 주소: 1021
- 비밀번호 크기 값 저장: 1022
- 아이디 저장: 981 ~ 1000(20개 문자까지 저장)
- 비밀번호 저장: 1001 ~ 1020(20개 문자까지 저장)
상기 설정에 따라 아이디와 비밀번호를 변수 ssid와 pass에서 읽어와 EEPROM에 저장하는 코드를 사용자 함수 wifi_eeprom_write()로 아래와 같이 작성해 주었다.
void wifi_eeprom_write() { // 최초 초기화 시 또는 변경 후 연결 성공한 아이디 / 비밀번호 쓰기 String ssidTemp = ssid; String passTemp = pass; EEPROM.write(1021, ssidTemp.length()); // '\0'포함 안된 크기 저장 for (int i = 0; i < ssidTemp.length(); i++) EEPROM.write(981 + i, ssid[i]); EEPROM.write(1022, passTemp.length()); // '\0'포함 안된 크기 저장 for (int i = 0; i < passTemp.length(); i++) EEPROM.write(1001 + i, pass[i]); } |
EEPROM에서 아이디와 비밀번호를 읽어오는 코드를 사용자 함수 wifi_eeprom_read()로 아래와 같이 작성해 주었다.
void wifi_eeprom_read() { // 아두이노 리셋 시 저장된 아이디 / 비밀번호 읽기 uint8_t ssidSize = EEPROM.read(1021); for (int i = 0; i < ssidSize; i++) ssid[i] = EEPROM.read(981 + i); ssid[ssidSize] = '\0'; // 문자열 변경 반영 - 마지막에 써줌으로써 이전 문자열 지울 필요 없음 uint8_t passSize = EEPROM.read(1022); for (int i = 0; i < passSize; i++) pass[i] = EEPROM.read(1001 + i); pass[passSize] = '\0'; // 문자열 변경 반영 - 마지막에 써줌으로써 이전 문자열 지울 필요 없음 } |
setup() 함수에서 아이디 및 비밀번호를 저장하거나 읽도록 상기 코드를 적용해 주었다.
if(EEPROM.read(1023) != 1) { EEPROM.write(1023, 1); // eeprom 저장 플래그 wifi_eeprom_write(); // 최초 초기화 시 아이디 / 비밀번호 쓰기 } else { wifi_eeprom_read(); // 아두이노 리셋 시 저장된 아이디 / 비밀번호 읽기 } |
와이파이 연결 코드를 아이디 및 비밀번호를 변경하거나 ESP01을 초기화할 경우 다시 연결할 수 있도록 입력값이 있는 사용자 함수 wifi_connect(bool setup_ini)로 빼내 주었다. setup() 함수 내에서는 wifi_connect(true);로 사용하고 기타 다른 함수에서는 wifi_connect(false);로 사용하면 된다. setup() 함수 내에서 실행되는 경우에는 EEPROM에 아이디와 비밀번호를 쓰지 않도록 하고 기타 장소에서 실행될 경우 EEPROM에 써주기 위함이다.
void wifi_connect(bool setup_ini) { while ( status != WL_CONNECTED) { // 약 10초 동안 wifi 연결 시도 Serial.print(F("Attempting to connect to WPA SSID: ")); Serial.println(ssid); status = WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network if (!setup_ini) wifi_eeprom_write(); // setup 함수 이외의 아이디 / 비밀번호 변경 시 저장 if (status != WL_CONNECTED) { connectTowifi = false; Serial.println(F("connection failed")); break; // 연결 실패 시 빠져나간다. } else { IPAddress ip = WiFi.localIP(); Serial.print(F("IP Address: ")); stIp = toStringIp(ip); Serial.println(stIp); } } // IPAddress localIp(192, 168, 111, 111); // softAP 접속 IP 설정 // WiFi.configAP(localIp); WiFi.beginAP(ssid_AP, 10, pass_AP, ENC_TYPE_WPA2_PSK, false); // 10:채널, false: softAP와 station 동시 사용모드 IPAddress ap = WiFi.localIP(); Serial.print(F("AP Address: ")); Serial.println(ap); server.begin(); } |
와이파이를 통해 수신된 스트링 형식의 새로운 아이디와 비밀번호를 배열 ssid와 pass에 저장해주는 코드이다.
void stringTo(String ssidTemp, String passTemp) { // 스트링 SSID / PASS 배열에 저장 for (int i = 0; i < ssidTemp.length(); i++) ssid[i] = ssidTemp[i]; ssid[ssidTemp.length()] = '\0'; for (int i = 0; i < passTemp.length(); i++) pass[i] = passTemp[i]; pass[passTemp.length()] = '\0'; Serial.println(ssid); Serial.println(pass); } |
디지털 핀 제어와 와이파이 설정 페이지에 공통으로 사용되는 html 코드이다.
const char HTTP_HEAD[] PROGMEM = "<!DOCTYPE html><html lang=\"en\"><head>"
"<meta name=\"viewport\"content=\"width=device-width,initial-scale=1,user-scalable=no\"/><link rel=\"icon\" href=\"data:,\">";
const char HTTP_STYLE[] PROGMEM = "<style>"
".c{text-align:center;}div,"
"input{padding:5px;font-size:1em;}input{width:95%;}"
"body{text-align:center;font-family:verdana;}" // max-width:300px;
"button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%} "
"</style>";
const char HTTP_HEAD_END[] PROGMEM = "</head><body><div style=\"text-align:center;display:inline-block;min-width:260px;\">";
const char HTTP_END[] PROGMEM = "</div></body></html>\r\n";
디지털 핀 제어에 사용되는 html 코드이다.
const char BUTTON_TYPE[] PROGMEM = "<p><button style=\"width:40%;background-color:#12cb3d;\">ON</button><button style=\"margin-left:10%;width:40%;background-color:#1fa3ec;\">OFF</button></a></p>";
const char BUTTON_A_ON[] PROGMEM = "<p>Button A</p><a href=\"/A/0\"><button style=\"background-color:#12cb3d;\">ON</button></a></p>";
const char BUTTON_A_OFF[] PROGMEM = "<p>Button A</p><a href=\"/A/1\"><button style=\"background-color:#1fa3ec;\">OFF</button></a></p>";
const char BUTTON_B_ON[] PROGMEM = "<p>Button B</p><a href=\"/B/0\"><button style=\"background-color:#12cb3d;\">ON</button></a></p>";
const char BUTTON_B_OFF[] PROGMEM = "<p>Button B</p><a href=\"/B/1\"><button style=\"background-color:#1fa3ec;\">OFF</button></a></p>";
와이파이 설정에 사용되는 html 코드이다.
const char HTTP_PORTAL_OPTIONS[] PROGMEM = "<form action=\"/wifi\"method=\"get\"><button>Configure WiFi</button></form><br/>" // soft AP 페이지 초기 화면
"<form action=\"/r\"method=\"post\"><button>Reset</button></form>";
const char HTTP_IP_CHECK[] PROGMEM = "<form action=\"/ip\"method=\"get\"><button>IP Check</button></form><br/>";
const char HTTP_FORM_START[] PROGMEM = "<form method='get'action='wifisave'>";
const char HTTP_FORM_SSID[] PROGMEM = "<input id='s'name='s'length=20 placeholder='SSID'><br/>";
const char HTTP_FORM_PASS[] PROGMEM = "<input id='p'name='p'length=20 type='password'placeholder='password'><br/>";
const char HTTP_FORM_END[] PROGMEM = "<br/><button type='submit'>save</button></form>";
const char HTTP_SAVED[] PROGMEM = "<div>Credentials Saved<br/>Trying to connect ESP to network.<br/>Reconnect Soft AP if checking IP.</div><br/>";
사용방법
1. 스마트폰 와이파이 연결 프로그램에서 ESP01의 soft AP에 연결한다.
2. 웹브라우저 주소창에 "192.168.4.1/ip"를 입력한다.
현재 설정된 공유기 연결용 SSID와 와이파이가 연결된 경우 IP주소가 표시된다.
와이파이가 연결되지 않은 경우라면 "Connection failed"라는 메시지가 표시된다.
3. "Configure WiFi" 버튼을 클릭한다.
4. 새로운 아이디와 비밀번호를 입력하고 "save"버튼을 클릭한다.
5. 상기와 같은 메시지가 출력되면서 ESP01은 새로운 아이디와 비밀번호로 공유기에 연결을 시도하게 되고 기존에 연결된 soft AP 연결이 끊어지게 되므로 스마트폰 와이파이 연결 프로그램에서 다시 ESP01의 soft AP에 연결해 주어야 한다.
6. 공유기에서 할당받은 ip주소를 확인하기 위해 웹브라우저 주소창에 "192.168.4.1/ip"를 입력하고 새로운 ip주소를 확인한다.
새로운 주소가 표시되었다면 ESP01이 station모드로 현재 공유기에 연결된 것이므로 soft AP의 연결을 종료한다.
* Reset 버튼을 클릭하게 되면 현재 저장되어 있는 아이디와 비밀번호로 와이파이 재 연결을 시도하고 아래와 같이 표시된다.
아래 스케치를 업로드하고 테스트해보자.
#include "WiFiEsp.h"
#include <EEPROM.h>
#include <SoftwareSerial.h>
#define rxPin 3
#define txPin 2
SoftwareSerial esp01(txPin, rxPin); // SoftwareSerial NAME(TX, RX);
char ssid[21] = "SK_WiFiGIGA40F7"; // your network SSID (name)
char pass[21] = "1712037218"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
bool connectTowifi = true;
char ssid_AP[] = "esp01_AP"; // your network SSID (name)
char pass_AP[] = "1234test"; // your network password
#define ledPin 13
#define digiPin 7
WiFiEspServer server(80);
bool button_a = LOW; // off
bool button_b = LOW; // off
// 공통 html
const char HTTP_HEAD[] PROGMEM = "<!DOCTYPE html><html lang=\"en\"><head>"
"<meta name=\"viewport\"content=\"width=device-width,initial-scale=1,user-scalable=no\"/><link rel=\"icon\" href=\"data:,\">";
const char HTTP_STYLE[] PROGMEM = "<style>"
".c{text-align:center;}div,"
"input{padding:5px;font-size:1em;}input{width:95%;}"
"body{text-align:center;font-family:verdana;}" // max-width:300px;
"button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%} "
"</style>";
const char HTTP_HEAD_END[] PROGMEM = "</head><body><div style=\"text-align:center;display:inline-block;min-width:260px;\">";
const char HTTP_END[] PROGMEM = "</div></body></html>\r\n";
// 디지털핀 원격제어 html
const char BUTTON_TYPE[] PROGMEM = "<p><button style=\"width:40%;background-color:#12cb3d;\">ON</button><button style=\"margin-left:10%;width:40%;background-color:#1fa3ec;\">OFF</button></a></p>";
const char BUTTON_A_ON[] PROGMEM = "<p>Button A</p><a href=\"/A/0\"><button style=\"background-color:#12cb3d;\">ON</button></a></p>";
const char BUTTON_A_OFF[] PROGMEM = "<p>Button A</p><a href=\"/A/1\"><button style=\"background-color:#1fa3ec;\">OFF</button></a></p>";
const char BUTTON_B_ON[] PROGMEM = "<p>Button B</p><a href=\"/B/0\"><button style=\"background-color:#12cb3d;\">ON</button></a></p>";
const char BUTTON_B_OFF[] PROGMEM = "<p>Button B</p><a href=\"/B/1\"><button style=\"background-color:#1fa3ec;\">OFF</button></a></p>";
// wifi 설정 html
const char HTTP_PORTAL_OPTIONS[] PROGMEM = "<form action=\"/wifi\"method=\"get\"><button>Configure WiFi</button></form><br/>" // soft AP 페이지 초기 화면
"<form action=\"/r\"method=\"post\"><button>Reset</button></form>";
const char HTTP_IP_CHECK[] PROGMEM = "<form action=\"/ip\"method=\"get\"><button>IP Check</button></form><br/>";
const char HTTP_FORM_START[] PROGMEM = "<form method='get'action='wifisave'>";
const char HTTP_FORM_SSID[] PROGMEM = "<input id='s'name='s'length=20 placeholder='SSID'><br/>";
const char HTTP_FORM_PASS[] PROGMEM = "<input id='p'name='p'length=20 type='password'placeholder='password'><br/>";
const char HTTP_FORM_END[] PROGMEM = "<br/><button type='submit'>save</button></form>";
const char HTTP_SAVED[] PROGMEM = "<div>Credentials Saved<br/>Trying to connect ESP to network.<br/>Reconnect Soft AP if checking IP.</div><br/>";
String stIp = "000.000.000.000" ;
String toStringIp(IPAddress ip) { // 32비트 ip 주소를 스트링으로 변환하는 함수
String res = "";
for (int i = 0; i < 3; i++) {
res += String((ip >> (8 * i)) & 0xFF) + ".";
}
res += String(((ip >> 8 * 3)) & 0xFF);
return res;
}
void stringTo(String ssidTemp, String passTemp) { // 스트링 SSID / PASS 배열에 저장
for (int i = 0; i < ssidTemp.length(); i++) ssid[i] = ssidTemp[i];
ssid[ssidTemp.length()] = '\0';
for (int i = 0; i < passTemp.length(); i++) pass[i] = passTemp[i];
pass[passTemp.length()] = '\0';
Serial.println(ssid);
Serial.println(pass);
}
void wifi_connect(bool setup_ini) {
while ( status != WL_CONNECTED) { // 약 10초동안 wifi 연결 시도
Serial.print(F("Attempting to connect to WPA SSID: "));
Serial.println(ssid);
status = WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network
if (!setup_ini) wifi_eeprom_write(); // setup 함수 이외의 아이디 / 비밀번호 변경시 저장
if (status != WL_CONNECTED) {
connectTowifi = false;
Serial.println(F("connection failed"));
break; // 연결 실패시 빠져나간다.
} else {
IPAddress ip = WiFi.localIP();
Serial.print(F("IP Address: "));
stIp = toStringIp(ip);
Serial.println(stIp);
}
}
// IPAddress localIp(192, 168, 111, 111); // softAP 접속 IP 설정
// WiFi.configAP(localIp);
WiFi.beginAP(ssid_AP, 10, pass_AP, ENC_TYPE_WPA2_PSK, false); // 10:채널, false: softAP와 station 동시 사용모드
IPAddress ap = WiFi.localIP();
Serial.print(F("AP Address: "));
Serial.println(ap);
server.begin();
}
void wifi_eeprom_read() { // 아두이노 리셋시 저장된 아이디 / 비밀번호 읽기
uint8_t ssidSize = EEPROM.read(1021);
for (int i = 0; i < ssidSize; i++) ssid[i] = EEPROM.read(981 + i);
ssid[ssidSize] = '\0'; // 문자열 변경 반영 - 마지막에 써줌으로써 이전 문자열 지울필요 없음
uint8_t passSize = EEPROM.read(1022);
for (int i = 0; i < passSize; i++) pass[i] = EEPROM.read(1001 + i);
pass[passSize] = '\0'; // 문자열 변경 반영 - 마지막에 써줌으로써 이전 문자열 지울필요 없음
}
void wifi_eeprom_write() { // 최초 초기화시 또는 변경 후 연결 성공한 아이디 / 비밀번호 쓰기
String ssidTemp = ssid;
String passTemp = pass;
EEPROM.write(1021, ssidTemp.length()); // '\0'포함 안된 크기 저장
for (int i = 0; i < ssidTemp.length(); i++) EEPROM.write(981 + i, ssid[i]);
EEPROM.write(1022, passTemp.length()); // '\0'포함 안된 크기 저장
for (int i = 0; i < passTemp.length(); i++) EEPROM.write(1001 + i, pass[i]);
}
void setup() {
Serial.begin(9600); // initialize serial for debugging
if(EEPROM.read(1023) != 1) {
EEPROM.write(1023, 1); // eeprom 저장 플래그
wifi_eeprom_write(); // 최초 초기화시 아이디 / 비밀번호 쓰기
}
else {
wifi_eeprom_read(); // 아두이노 리셋시 저장된 아이디 / 비밀번호 읽기
}
pinMode(ledPin, OUTPUT);
pinMode(digiPin, OUTPUT);
digitalWrite(ledPin, LOW);
digitalWrite(digiPin, LOW);
esp01.begin(9600); //와이파이 시리얼
WiFi.init(&esp01); // initialize ESP module
Serial.println(ssid);
Serial.println(pass);
wifi_connect(true); // 와이파이 연결, true: setup() 함수에서 실행 false: 기타
}
void loop() {
WiFiEspClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
bool esp01Reset = false;
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
String income_wifi = client.readStringUntil('\n');
Serial.println(income_wifi);
bool ip = false, wifi = false, reset = false, save = false;
if (income_wifi.indexOf(F("A/1")) != -1) {
Serial.println(F("button_A on"));
button_a = HIGH;
digitalWrite(ledPin, button_a);
} else if (income_wifi.indexOf(F("A/0")) != -1) {
Serial.println(F("button_A off"));
button_a = LOW;
digitalWrite(ledPin, button_a);
} else if (income_wifi.indexOf(F("B/1")) != -1) {
Serial.println(F("button_B on"));
button_b = HIGH;
digitalWrite(digiPin, button_b);
} else if (income_wifi.indexOf(F("B/0")) != -1) {
Serial.println(F("button_B off"));
button_b = LOW;
digitalWrite(digiPin, button_b);
} else if (income_wifi.indexOf(F("/ip")) != -1) ip = true;
else if (income_wifi.indexOf(F("/wifi?")) != -1) wifi = true;
else if (income_wifi.indexOf(F("POST /r")) != -1) reset = true;
else if (income_wifi.indexOf(F("wifisave?s=")) != -1) save = true;
client.flush();
client.println(F("HTTP/1.1 200 OK\nContent-type:text/html\nConnection: close\r\n"));
String page;
page = (const __FlashStringHelper *)HTTP_HEAD;
page += (const __FlashStringHelper *)HTTP_STYLE;
page += (const __FlashStringHelper *)HTTP_HEAD_END;
if (ip) {
page += F("<p>SSID: ");
page += ssid;
page += F("</p>");
if (status == WL_CONNECTED) {
page += F("<p>IP Address: ");
page += stIp;
page += F("</p>");
} else page += F("<p>Connection failed</p>");
page += (const __FlashStringHelper *)HTTP_PORTAL_OPTIONS;
}else if (wifi) {
page += (const __FlashStringHelper *)HTTP_IP_CHECK;
page += (const __FlashStringHelper *)HTTP_FORM_START;
page += (const __FlashStringHelper *)HTTP_FORM_SSID;
page += (const __FlashStringHelper *)HTTP_FORM_PASS;
page += (const __FlashStringHelper *)HTTP_FORM_END;
}else if (reset) {
page += F("<p>ESP01 will be reset....</p>");
page += (const __FlashStringHelper *)HTTP_IP_CHECK;
page += (const __FlashStringHelper *)HTTP_PORTAL_OPTIONS;
esp01Reset = true;
}else if (save) {
page += (const __FlashStringHelper *)HTTP_SAVED;
page += (const __FlashStringHelper *)HTTP_IP_CHECK;
String ssidTemp = income_wifi.substring(16, income_wifi.indexOf("&p="));
String passTemp = income_wifi.substring(income_wifi.indexOf("&p=") +3, income_wifi.indexOf("HTTP/1.1")-1);;
stringTo(ssidTemp, passTemp); // SSID / PASS 스트링을 배열에 저장
esp01Reset = true;
}else {
page += F("<h3>ESP01 Digital Pin Control</h3>");
page += (const __FlashStringHelper *)BUTTON_TYPE;
if (button_a == HIGH) page += (const __FlashStringHelper *)BUTTON_A_ON;
else page += (const __FlashStringHelper *)BUTTON_A_OFF;
if (button_b == HIGH) page += (const __FlashStringHelper *)BUTTON_B_ON;
else page += (const __FlashStringHelper *)BUTTON_B_OFF;
}
page += (const __FlashStringHelper *)HTTP_END;
client.print(page);
client.println();
client.println();
delay(1);
break;
}
}
client.stop();
Serial.println(F("Client disconnected"));
if (esp01Reset) {
if (WiFi.disconnect() == WL_DISCONNECTED) status = 0;
WiFi.init(&esp01); // initialize ESP module
wifi_connect(false);
}
}
if (Serial.available() > 0){ // EEPROM 초기값 반영
String temp = Serial.readStringUntil('\n');
if (temp == "reset") {
EEPROM.write(1023, 0);
Serial.println(F("EEPROM will be reset"));
}
}
}
웹페이지 응답 코드가 있는 아두이노 와이파이 제어에서 사용할 수 있는 연결 도우미 앱입니다.
https://play.google.com/store/apps/details?id=com.tistory.postpop.MCUWiFi
특징:
1. 스마트폰에서 아두이노 웹서버에 연결할 때 에러 메세지 출력 및 연결 가이드 제시
2. 아두이노 웹서버의 html 페이지 연결시 스마트폰의 웹브라우저 대신 앱 내부 웹 뷰어를 통해 연결 및 표시
3. 앱 실행전 스마트폰의 와이파이 실행 유무에 따라 앱 종료시 와이파이 설정 페이지 이동
자세한 설명은 아래 포스트를 참조하세요.
[Arduino] - 아두이노 와이파이 연결 도우미 앱
관련 글
[arduino] - 아두이노 - EEPROM 사용하기
[arduino] - 아두이노 - 문자열의 이해와 표현 방법
[arduino] - 아두이노 - 메모리(SRAM) 공간 확보를 위한 PROGMEM과 F() 매크로의 사용
[arduino] - 아두이노 - 와이파이 원격제어, ESP01 WiFiEsp.h 라이브러리 webserver
'Arduino' 카테고리의 다른 글
Setting up Wi-Fi module ESP01 and basic code for Arduino remote control (0) | 2022.11.16 |
---|---|
아두이노 - 와이파이, ESP01 wifi 모듈 무선 원격제어 그리고 시리얼 통신 - 6편 (9) | 2022.06.08 |
arduino - Simple Melody 이용 피에조 부저 멜로디 코딩하기, Esp01, EEPROM (0) | 2020.09.19 |
ESP8266 / ESP32 - SPIFFS 파일시스템 라이브러리 예제 및 사용방법 (4) | 2020.03.22 |
아두이노 - ESP01 웹서버를 이용하여 웹페이지에서 디지털핀 원격제어, WiFiEsp.h (4) | 2019.11.19 |
아두이노 - 메모리(SRAM) 공간 확보를 위한 PROGMEM과 F() 매크로의 사용 (0) | 2019.11.17 |
아두이노 - 문자열의 이해와 표현 방법 (2) | 2019.11.14 |
아두이노 - EEPROM 사용하기 (0) | 2019.11.12 |