반응형

전편에 이어 NodeMcu 1.0(ESP8266)의 soft AP에 wifi를 연결하여 원격제어하는 방법에 대해 살펴 보겠다. 

 

 

 

가변저항 핀      -> NodeMcu ADC(analog digital converter) 핀 A0

PWM 제어 LED  -> PWM 핀 GPIO 4 (D2)

LED                  -> GPIO 5 (D1)

 

 

 

NodeMcu는 esp8266 칩셋 기반 개발 보드이다. 보드 자체가 아두이노를 대체할 수 있도록 각종 라이브러리가 제공되고  esp8266 칩셋이 장착되어 있어 wifi 기능이 기본 제공된다. 

 

보드 자체에 칩셋이 장착되어 있으므로 ESP-01과 아두이노와의 연결에 사용했던 시리얼 통신이 필요없고 더군다나 AT command를 사용하지 않고 라이브러리로 제어가 가능하게 되어 아두이노 기반 ESP-01 wifi에 비해 성능이 향상되는 결과가 되었다. 

 

 

ESP-01 모듈 자체도 아두이노 IDE를 통해 프로그래밍 하고 자체 GPIO를 제어 할 수 있으나 아두이노 IDE와 연결함에 있어 USB TTL CONVERTOR를 통해야 하는 불편함과 GPIO를 2개만 지원하는 단점이 있었다. 

 

NodeMcu의 와이파이를 사용하기 위해서는 "ESP8266WiFi.h" 라이브러리를 사용해야 한다. 

이 라이브러리는 "ESP8266WiFiAP.h", "WiFiClient.h", "WiFiServer.h"를 포함하고 있어 soft AP, 서버에 연결하기위한 클라이언트 그리고 서버를 구성 할 수 있다. 

 

참조 페이지

https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html

 

아래 NodeMcu soft AP 기본 코드를 업로드 해보자.

esp8266_wifi_test.zip
0.00MB

#include <ESP8266WiFi.h>

#define AP_SSID  "Esp12"

#define AP_PASS  "1234test"

 

String income_wifi = ""; // 와이파이 수신 스트링 저장 변수

 

WiFiServer server(80);

 

void setup() {

  Serial.begin(115200);

  WiFi.softAP(AP_SSID, AP_PASS);  // WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();

  Serial.print("AP IP address: ");

  Serial.println(myIP);

  server.begin();

}

 

void loop() {

  WiFiClient client = server.available(); // 서버가 작동하면 client 생성

  if(client.available()) {                       // 클라이언트에 데이터가 있으면

    income_wifi = client.readStringUntil('\r');

    Serial.println(income_wifi);

  }

  client.stop();

 

}

 

업로드 후 스마트폰에서 soft AP에 연결하고 웹브라우저 주소창에 192.168.4.1을 입력해보자.

 

아래 그림과 같이 아두이노 시리얼 모니터에 "GET / HTTP/1.1"이 표시 되고 192.168.4.1/hi를 입력하면 "GET /hi HTTP/1.1"이 출력되는것을 볼 수 있다. 

 

 

전편에 살펴 보았듯이 이렇게 들어오는 데이터를 parsing하여 원격제어 코드를 작성해주면 되는데, 전편에서는 데이터의 전송에 관하여 설명을 하지 않았었다. 

 

 

 

와이파이 연결을 통한 원격제어에 있어서 NodeMcu에서 스마트폰으로 데이터를 전송하는 방법이 기존의 블루투스 연결 방식과는 다르다. 블루투스를 사용할 경우에는 전송하고 싶은 데이터가 있다면 btSerial.print() 함수를 통해 전송 코드가 작동할 때마다 능동적으로 보낼수가 있었다. 일단 보내고 나면 나머지는 스마트폰에서 알아서 할 일이다.  하지만, 와이파이를 통해 전송하고자 할 때에는 보내고 싶다고 보내지는게 아니다. 여기에는 서버의 특성이 적용되게 되는데, 이를 이해하기 위해서는 Master와 Slave 개념을 이해해야 한다. 

 

우리가 인터넷을 할 때 서버에 수시로 접속하게 되는데, 서버에 접속하려 하면 아이디와 패스워드를 묻는다. 이러한 절차 때문에 서버가 상위의 위치에 있다고 생각할 수 있다. 하지만 서버는 Slave이며 사용자는 Master가 된다. 아이디와 패스워드를 묻는건 Master의 자격을 묻는것일 뿐이고 Master의 자격이 확인되면 Master의 요구에 따라서만 프로그램된 대로 동작하게 된다. 물론, 권한을 벗어나는 요구는 무시될 것이다. 이 얘기는 사용자(웹브라우저 또는 Master)가 요청을 했을때만 클라이언트 클래스를 통해 서버에 연결되고 그 연결을 통해서만 데이터를 전송할 수 있게된다. 즉 서버가 보내고 싶다고 데이터를 전송할 수 있는게 아니다.  또한 서버 입장에서는 Master와 상시 연결된 상태가 아니기 때문에 어떤 클라이언트를 통해 데이터를 보내야 제대로 전달할 수 있는지도 알수가 없다. 그러므로 서버로 부터 생성된 데이터를 실시간으로 받기 위해서는 사용자(Master)가 실시간으로 연결 요청을 해야만 서버로 부터 데이터를 받을 수 있게 된다. 안드로이드 앱에는 일정 간격으로 사용자의 입력 없이도 응답요청을 하도록 프로그램 되어있다. 이 응답요청으로 서버에서 생성된 데이터를 전송 할 수 있게 되는데 코드 상에 그 일정 간격의 사이동안 생성된 데이터 값을 대기 시키기위한 전송용 버퍼가 필요하게 된다. 

 

 

 

 

들어온 데이터를 parsing하는 방법 및 수신부 코드 설명은 전편에서 다루었기에 데이터 전송 코드만 다루도록 하겠다. 또한 가변저항 제어권 관련 코드는 "아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 4편 및 5편"에 설명 되어 있다. 

 

비밀번호 없이 Soft AP를 구성하고 싶다면 아래 코드를 변경해 주면 된다.

 

WiFi.softAP(AP_SSID, AP_PASS); -> WiFi.softAP(AP_SSID); 

 

Soft AP의 기본 ip 주소 192.168.4.1을 변경해주고 싶다면 아래 코드를 추가해 주면 된다. 

 

IPAddress local_IP(192,168,4,22);

IPAddress gateway(192,168,4,9);

IPAddress subnet(255,255,255,0);

 

iFi.softAPConfig(local_IP, gateway, subnet);

esp8266_wifi_test_static_ip.zip
0.00MB

#include <ESP8266WiFi.h>

#define AP_SSID  "Esp12"

#define AP_PASS  "1234test"

 

IPAddress local_IP(192,168,4,22);

IPAddress gateway(192,168,4,9);

IPAddress subnet(255,255,255,0);

 

String income_wifi = ""; // 와이파이 수신 스트링 저장 변수

 

WiFiServer server(80);

 

void setup() {

  Serial.begin(115200);

  WiFi.softAPConfig(local_IP, gateway, subnet);

  WiFi.softAP(AP_SSID, AP_PASS);  // WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();

  Serial.print("AP IP address: ");

  Serial.println(myIP);

  server.begin();

}

 

void loop() {

  WiFiClient client = server.available(); // client 시작

  if(client.available()) {

    income_wifi = client.readStringUntil('\r');

    Serial.println(income_wifi);

  }

  client.stop();

}

 

참조 페이지

https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/soft-access-point-class.html

 

데이터 수신을 위해 안드로이드 앱은 100 밀리초마다 응답요청을 서버에 보내도록 프로그램되어 있다. 이를 스케쥴 웹요청이라 하겠으며 사용자가 버튼을 클릭하거나 슬라이드를 움직일때의 요청을 사용자 웹요청이라 하겠다.

 

우선, 코드에서 사용할 와이파이 원격제어 프로토콜에 관해 살펴보자.

arduino bluetooth controller PWM 안드로이드 앱의 wifi를 이용한 원격제어용 프로토콜은 다음과 같다. 

 

arduino bluetooth controller PWM - 아두이노 원격제어 안드로이드 앱 버전 3.5 다운로드

arduino bluetooth controller PWM 매뉴얼

(*** 상기앱의 와이파이 연결은 안드로이드8 [갤럭시S7]이하 버전에서만 작동합니다 ***)

 

 

 

데이터 수신용 프로토콜

디지털 버튼 제어 프로토콜: "%%F0" + 스트링 값 + "%%F1"

                                         스트링 값 = "10" 버튼1 off, 스트링 값 = "11" 버튼1 on, "20" 버튼2 off, "21" 버튼2 on, ......

PWM 값 프로토콜: 1번 슬라이드 "%%F31" + 스트링 값 + "%%F1"

                           2번 슬라이드 "%%F32" + 스트링 값 + "%%F1"

                           3번 슬라이드 "%%F33" + 스트링 값 + "%%F1"

 

데이터 전송용 프로토콜: 블루투스 연결과는 달리 전송데이터가 한꺼번에 전송되어 각각 데이터의 구분이 필요하다.

스케쥴 요청 구분 코드: "%%F5"

디지털 버튼 echo 프로토콜: "%%F0" + 스트링 값 + "%%P1"

PWM 값 echo 프로토콜: "%%F3" + 스트링 값(슬라이드 번호+PWM) + "%%E1"

PWM 값 slide 프로토콜: "%%F4" + 스트링 값(슬라이드 번호+PWM) + "%%S1"

 

서버에서 응답으로 데이터를 보낼때는 응답헤더로 "HTTP/1.1 200 OK"를 보내줘야 한다. 웹브라우저가 "HTTP/1.1 200 OK"를 받게 되면 뒤따르는 값을 데이터로 인식하여 웹브라우저에 표시하게 된다. 응답헤더가 없으면 표시 되지 않는다(데이터를 받지 못한다). 또한, 응답헤더가 중복될 경우 중복된 응답 헤더는 데이터로 취급된다.  

 

 

중복을 방지하기 위해 사용자 웹요청 응답코드는 선행코드로서 반드시 client.println("HTTP/1.1 200 OK\r\n");를 먼저 써주도록 했으며 스케쥴 웹요청 응답값은 임시 저장 변수에 저장만 해주면 된다. 

 

client.println("HTTP/1.1 200 OK\r\n"); // 사용자 웹요청시 응답 헤더

send_pin_echo(pin_val);

 

스케쥴 요청 구분 코드 "%%F5"를 정하게 된 이유는 루트값인 "/ HTTP/1.1"로 할 경우 비 사용자가 soft AP(http://192.168.4.1)의 루트에 접속할 경우 의도치 않게 전송할 데이터값이 비 사용자에게로 전달되어 정작 사용자는 데이터를 받지 못하는 경우가 발생할 수 있다. 이를 방지하기위해 설정한 것이다. 가변저항이 연결된 상태에서는 가변저항 값이 수시로 변하므로 이 값이 계속해서 스마트폰에 전송되게 되는데, 이 때 http://192.168.4.1/%%F5를 입력하고 연타를 계속하고 있으면 타이밍이 맞아져서 데이터 가로채기를 할 수 있게 된다. 하지만 이처럼 %%F5를 입력하고 데이터를 가로챈다면 의도된 접속으로 간주해야 하고 막을 방법은 없다. 

 

 

 

수신된 데이터중에 스케쥴 요청 구분 코드 "%%F5"가 확인 되면 데이터 전송용 아래 코드가 실행되고 전송 데이터를 저장하는 변수(send_pin, send_Pwm_echo, send_Pwm_slide, send_text)에 값이 있을 경우에 한꺼번에 전송하게 된다.

 

else if (income_wifi.indexOf("%%F5") != -1) { // 스케쥴 접속확인 응답, 텍스트 및 로컬값 전송

  client.println("HTTP/1.1 200 OK\r\n");      // 스케쥴 웹요청시 응답 헤더 

  if (send_pin != "") { client.print(send_pin); send_pin = ""; }  // 전송할 핀 상태 값이 있으면 

  if (send_Pwm_echo != "") { client.print(send_Pwm_echo); send_Pwm_echo = "";  }  // 전송할 PWM 상태(echo) 값이 있으면

  if (send_Pwm_slide != "") { client.print(send_Pwm_slide); send_Pwm_slide = "";  }   // 전송할 PWM 바 상태 값이 있으면

  if (send_text != "") { client.print(send_text);  send_text = "";  }                           // 전송할 텍스트가 있으면

}

 

 

 

 

 

 

안드로이드 앱에서 버튼을 클릭했을 때 사용자 웹요청 응답코드로 void send_pin_echo() 함수를 설정했다면 이 때는 클라이언트가 연결된 상태이므로 if (client.connected())  client.print(s_temp);가 실행되게 된다. 반면에 시리얼 모니터에서 스트링 on으로 입력하여 LED를 켜고 상태 변화를 전송한다면(클라이언트가 연결안된상태에서) else  send_pin = s_temp; 코드가 실행되어 send_pin 변수에 저장되어 스케쥴 웹요청이 있을 때까지 대기 하게 된다.

 

void send_pin_echo(uint8_t pin_val){

  String s_temp ="";

  s_temp += "%%F0";

  s_temp += pin_val;

  s_temp += "%%P1";

  if (client.connected())  client.print(s_temp); // 사용자 웹요청 응답

  else  send_pin = s_temp;                       // 스케쥴 웹요청 응답

}

이로써 전편에 이어 추가된 코드들의 설명은 마쳤다. 이 글에서 빠진 설명은 이전 글들을 참조하기 바란다.

 

* 위에서 가변저항의 경우 값이 조금씩 계속해서 변한다고 언급했다. 이렇게 변한 값은 시리얼 모니터에 계속 출력되게 된다. 테스트를 위해 아두이노 시리얼 모니터를 계속 켜놓아 데이터가 계속 쌓에게 되면 시리얼 모니터가 멈추고 모듈이 강제 리부팅 되는 경우가 있다.  

 

안드로이드앱으로 연결된 상태라면 앱의 슬라이드 바에 가변저항 값이 표시 되므로 코드상 가변저항 값의 시리얼 모니터 출력 코드를 주석처리 해주고 확인은 스마트 폰으로 하면 될 것이다. 

 

이제 아래 전체 코드를 NodeMcu에 업로드 하고 arduino bluetooth controller PWM 안드로이드 앱을 통하여 제어를 해보자

 

스마트폰의 와이파이로 NodeMcu soft AP에 연결하거나 안드로이드 앱에서 와이파이 아이콘을 클릭하면 와이파이 세팅화면이 나오는데 여기에서 연결을 시켜준다. 

(*** 상기 앱에서 와이파이 연결은 안드로이드8 [갤럭시S7]이하 버전에서만 작동합니다 ***)

 

 

 

아래의 화면이 나오면 ip 입력창에 설정된 NodeMcu soft AP 주소를 입력하고 Confirm을 클릭한다.

 

 

Confirm을 클릭하면 안드로이드 앱은 soft AP주소로 100 밀리초마다 응답요청을 하게 되고 응답 수신을 하게 되면 와이파이 연결이 잘 되고 있는것으로 판단하고 연결된 soft AP 주소, 와이파이 원격제어 종료 아이콘 및 응답수신 진행 카운터를 표시하게 된다. 

 

8초동안 응답요청에 대한 응답 수신을 받지 못 할경우 와이파이 연결이 끊긴것으로 보고 와이파이 연결 아이피 주소와 연결끊기 아이콘 및 응답수신 카운터는 표시가 되지 않는다. 

 

안드로이드 앱의 와이파이 원격제어 프로세스를 정지시키고자 한다면 빨간색 플러그 아이콘을 클릭하면 스케쥴 응답요청 및 전송 프로세스는 모두 정지 된다.

 

 

 

영상을 보면 PWM LED의 밝기 조절이 블루투스 이용할 때 보다 부드럽지 못하다. 전송되는 데이터 양의 차이와 테이터 전송 간격 때문에 발생하는 현상이다. 블루투스 연결을 이용하게 되면 실시간으로 부드럽게 밝기가 조절되는걸 느낄수 있다. 

arduino_remote_control_esp8266_poten.zip
0.00MB

 

아래는 가변저항 제어관련 코드를 지운 NodeMcu 와이파이 제어용 코드이다. 

arduino_remote_control_esp8266.zip
0.00MB

 

최신 업데이트 유료앱(모든 안드로이드 버전 와이파이 연결 지원)

https://postpop.tistory.com/175

 

ADUCON - Arduino wireless remote control application

Arduino remote control app using a wireless module available in Arduino. Bluetooth 2.0 Classic / 4.0 BLE : HC-05, HC-06, HM-10, AT-09, BT05, ESP32, etc. Wi-Fi : ESP01, ESP8266 NodeMcu, ESP32, etc. https://play.google.com/store/apps/details?id=com.tistory.p

postpop.tistory.com

 

https://postpop.tistory.com/176

 

ADUPAD - Arduino wireless remote control PAD application

Arduino remote control PAD app using a wireless module available in Arduino. Bluetooth 2.0 Classic / 4.0 BLE : HC-05, HC-06, HM-10, AT-09, BT05, ESP32, etc. Wi-Fi : ESP01, ESP8266 NodeMcu, ESP32, etc. https://play.google.com/store/apps/details?id=io.kodula

postpop.tistory.com

 

 

관련 글

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 1편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 2편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 3편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 4편

[arduino] - 아두이노 - 안드로이드를 이용한 무선 원격제어 그리고 시리얼 통신 - 5편

[arduino] - 블루투스 4.0 BLE 이용 아두이노 및 ESP32 원격제어

 

[arduino] - 아두이노 - 시리얼통신 주요함수와 예제, String class

[arduino] - 아두이노 - ESP01 wifi 모듈 무선 원격제어 그리고 시리얼 통신 - 6편

[arduino] - ESP8266 - NodeMcu 1.0 와이파이 이용 원격제어(soft AP, wifi)

[arduino] - ESP32 - Dev Module 와이파이 이용 원격제어(soft AP, wifi)

 

arduino bluetooth controller PWM - 아두이노 원격제어 안드로이드 앱 버전 3.5 다운로드

arduino bluetooth controller PWM 매뉴얼

 

 

+ Recent posts