오늘은 ESP32를 통해 집에 직접 스마트홈을 구축하는 과정에 대해 기록한다.
먼저 IoT란 Internet of Things라는 뜻으로 사물이 인터넷으로 연결되는 것을 의미한다.
이렇게 사물에 인터넷을 연결하기 위해서는 사물을 작동시킬 수 있고 인터넷과 연결될 수 있는 제어 보드가 필요하다.
여기에 적합한 보드 중 아두이노 ESP32라는 와이파이 모듈이 탑재되어 공식 사이트에서 구매할 수 있는 보드도 있지만, 돈이 많지 않기에 비슷한 모델을 선택했다.
중국에 있는 테그선전이라는 회사에서 제작한 ESP32 Goouuu 개발보드를 사용한다.
위 사진과 동일하게 생겼고 ESP32 칩에 연결할 수 있는 핀들을 쉽게 결선할 수 있고 전원 공급과 코딩을 쉽게할 수 있도록 제작된 보드이다.
이 보드를 통해 릴레이를 사용하거나 서보모터를 이용하여 방의 전등 스위츠를 조작할 수 있다.
릴레이란 높은 전압을 입력받아 수도꼭지가 열리듯이 신호를 주면 스위치가 열려 이어진 선으로 전류가 흐르게 되는 모듈이다. 이러한 릴레이 모듈을 사용하게 되면 방에 있는 스위치를 뜯어서 220V 전선 작업을 해야하므로 위험요소가 많다. 따라서 나중에 기회가 된다면 충분한 지식을 가진 상태로 릴레이로 전원을 작동시켜볼 것이다.
그래서 이번 포스팅에서는 서보모터를 이용하여 스위치를 제어할 수 있도록 제작하기로 하였다.
먼저 서보모터와 ESP32 보드를 서로 연결시켜주어야 하는데 아래 결선도와 같이 결선해주었다.
위 사진과 같이 ESP32 칩 G27번핀에 서보모터를 연결하고 G15에 네오픽셀을 결선해주었다.
이때, 네오픽셀은 Dout가 아닌 Din으로 연결해주어야 함을 유의해야 한다.
기존에는 서보모터를 돌려 스위치를 작동시켜 켜고 끌 예정이였지만, 추가적으로 침대 쪽에 네오픽셀을 달아 무드등을 구현해주려고 네오픽셀을 추가하였다.
이제 ESP32 칩에 코드를 작성하여 플래쉬를 하기 전 IoT 작업을 미리 해야한다.
IoT를 위해서는 서버가 필요한데 대표적으로 아두이노에서 IoT를 구현할 때 사용하는 서버는 Arduino IoT Cloud와 Blynk가 있다.
저자는 Blynk를 사용하여 IoT를 구현하고자 한다.
https://blynk.cloud 주소로 들어가면 다음과 같이 로그인을 해야한다.
로그인을 완료하면 템플릿(프로젝트)을 하나 만들어주어야 한다.
Blynk에서 템플릿은 각 디바이스에서 사용할 수 있는 핀들과 다양한 정보들을 정의하는 공간이라고 볼 수 있다.
우측 상단에 New Template 버튼을 클릭하여 새로운 템플릿을 제작한다.
먼저 기본적으로 템플릿의 이름을 지정하고 중요한 부분은 HARDWARE(하드웨어)와 CONNECTION TYPE(연결 방식)이다.
하드웨어는 ESP32 칩을 통해 Bylnk 와 통신을 해줄 것이기 때문에 ESP32로 지정하고 연결 방식은 특별한 방식이 아니라면 WiFi로 설정한다.
Description(설명)은 굳이 작성하지 않아도 된다.
새로운 템플릿을 만들게 되면 다음과 같이 Datastreams(데이터 스트림) 등을 설정할 수 있는 화면이 나온다.
이제 서보모터와 네오픽셀을 작동시킬 가상 핀을 구성해야 한다.
여기서 가상핀이란 아두이노나 ESP32에 센서와 통신할 수 있는 핀이 있듯이 Blynk에서는 보이지 않는 가상 핀을 만들어 센서 값이나 대시보드의 값을 ESP32 또는 아두이노와 통신하기 위한 것이다.
Datastreams 탭으로 들어가면 다음과 같이 새로운 데이터스트림을 제작할 수 있다.
New Datastream을 눌러 Virtual Pin(가상 핀)을 클릭하여 가상 핀을 만든다.
먼저 첫 번째 가상 핀의 이름은 불을 껐다 켤 수 있도록 Light로 한다.
여기서 중요한 것은 값을 어떤 형식으로 가져오고 최소 최대 값을 미리 지정해야한다는 것이다.
DATA TYPE(자료 유형)은 Integer로 정수형 데이터만 송수신할 수 있도록 지정하고, MIN(최소값) MAX(최대값)은 각각 0과 1로 지정한다.
0과 1로 지정을 하면 참과 거짓을 쉽게 나눌 수 있기 때문이다.
이를 통해서 버튼을 눌러 활성화되면 ESP32에 1이 전송되고 한번 더 누르면 비활성화되어 0이 전송된다.
그렇다면 DATA TYPE(자료 유형)을 Boolean(부울) 형식으로 바꾸면 되지 않느냐는 의문을 가질 수 있지만, Blynk에서 지원하는 가상 핀의 자료형은 Integer(정수형), Dobule(부동소수점), String(문자형) 3가지만 지원하기에 Boolean을 구현할 수 있는 자료형은 Integer이 적합하기에 Integer을 통해 Boolean 자료형의 방식을 구현한다.
다음과 같이 두 가지 가상 핀을 제작한다. (Light, Servo)
두 가상 핀은 동일한 자료형과 최소 최대값을 가지고 있어야 한다.
Servo핀은 서보모터를 움직일 수 있게 하기 위한 핀이다.
(주의할 점은 Servo에 각도 값을 넣는 것은 프로그래밍 과정에서 작성해야 하고 여기서는 편의를 위해서 0,1로 데이터를 전송하고 ESP32에서 지정된 값만큼 움직일 수 있도록 구현한다)
이제 우측 상단에 Save 버튼을 클릭해서 템플릿 데이터를 저장한다.
좌측 Devices 탭으로 들어가서 새로운 디바이스(기기)를 하나 만들어준다.
우측 상단의 New Device 버튼을 클릭하여 새로운 디바이스를 만들 수 있다.
새로운 디바이스를 만들기 위해서는 아래와 같이 템플릿에서 가져올 것인지 직접 입력한 것인지 물어본다.
하지만 이전 단계에서 템플릿을 구현하였기에 From template 버튼을 클릭하여 다음 단계로 이동한다.
From template 버튼을 클릭하여 어떤 템플릿을 사용하여 기기를 제작할 것인지 물어보는데 다음과 같이 이전에 제작한 Velog(이름이 다를 수 있음)라는 템플릿을 사용하여 Velog라는 기기를 제작할 수 있다.
기기명은 템플릿 명과 기본적으로 동일해지지만 직접 변경할 수 있다.
디바이스를 제작하면 다음과 같이 기본적인 대시보드와 업타임을 확인할 수 있는데, 현재 대시보드에 할수 있는게 없다.
웹 대시보드에서 ESP32를 제어하는 방법도 있지만 이 글에서는 모바일 Blynk에서 작동을 구현할 것이다.
따라서 휴대전화에 스토어에 들어가 Blynk를 검색하여 어플리케이션을 다운로드 해준다.
(안르도이드 스토어에서도 있다)
설치를 마치고 열면 로그인 후 다음과 같이 제작한 디바이스가 보인다.
제작한 디바이스인 Velog를 터치하여 설정을 해줄 것이다.
우측 상단 초록색 배경의 설정 모양 버튼을 터치하면
대시보드를 꾸밀 수 있는 화면으로 전환되고 하단의 +버튼을 터치하면
Button을 터치하여 새로운 버튼을 하나 만들어준다.
새로 만든 버튼을 하나 누르면 버튼에 대한 동작을 설정할 수 있는데
위 사진과 같이 DataStream을 Light로 해주고 MODE를 Switch로 설정한다.
따라서 방금 제작한 버튼은 Light(불)을 제어할 수 있는 버튼이 된 것이고 Switch로 설정하여야 눌렀을 때 ON(켜짐) 상태가 유지된다.
동일한 방법으로 Servo 버튼도 제작한다.
위 사진과 같이 버튼 두개를 제작해주었다면 좌측 X버튼을 클릭해 나간다.
이제 Blynk 기본 설정을 마쳤다.
마지막 단계인 프로그래밍을 통해 ESP32에 소스코드를 작성하여 플래쉬 해주겠다.
아두이노 IDE가 기본적으로 설치되어 있다는 전제로 작성하였습니다.
(아두이노 2.0.0 버전 이상 기준)
아두이노 IDE를 실행하고 우측 라이브러리를 다운로드 받을 수 있는 탭으로 이동한다.
검색창에 위와 같이 Blynk를 입력하여 Volodymyr Shymanskyy가 제작한 라이브러리를 다운로드 한다.
다운로드를 완료하면 다음과 같이 File -> Examples -> Blynk -> Boards_WiFi -> ESP32_WiFi 예제를 클릭해서 열어준다.
위와 같이 코드가 나오는데 ESP32에서 네오픽셀과 서보모터를 작동시키려면 추가적인 라이브러리가 필요하다.
https://github.com/RoboticsBrno/ServoESP32/releases/tag/v1.1.1 깃허브로 들어가 Source code 버튼을 클릭하여 라이브러리를 다운로드 하고
라이브러리 매니저에 neo pixel 를 검색하여 Adafruit가 제작한 라이브러리를 설치해준다.
다시 Blynk 홈페이지에서 디바이스를 누르고 Device Info 버튼을 클릭하여 Firmware Configuration(펌웨어 구성요소)을 복사한다.
(각각의 디바이스마다 다르므로 주의하세요)
이제 아래의 코드를 이해하면서 입력하여 보드에 업로드를 해준다.
/* Device에 Device Info탭에 있는 Firmware Confirguration 항목에 있는 내용 붙여넣기 */
//#define BLYNK_TEMPLATE_ID "TMPxxxxxx"
//#define BLYNK_TEMPLATE_NAME "Device"
//#define BLYNK_AUTH_TOKEN "YourAuthToken"
/* 라이브러리 정의 */
#include <WiFi.h> // Blynk 작동을 위한 필수 라이브러리
#include <WiFiClient.h> // Blynk 작동을 위한 필수 라이브러리
#include <BlynkSimpleEsp32.h> // Blynk 작동을 위한 필수 라이브러리
#include <Adafruit_NeoPixel.h> // 네오픽섹을 사용하기 위한 라이브러리
#include <ESP32_Servo.h> // ESP32에서 서보모터를 사용하기 위한 라이브러리
// 연결할 와이파이 설정
char ssid[] = "와이파이 이름";
char pass[] = "와이파이 비밀번호";
#define PIN 15 // 네오픽셀이 결선 된 핀 번호
#define NUM 30 // 연결 된 내오픽셀의 픽셀 개수
static const int servoPin = 27; // 서보모터의 핀 번호
Servo servo1; // 라이브러리의 Servo를 servo1으로 객체 정의
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM,PIN, NEO_GRB + NEO_KHZ800); // 네오픽셀을 사용하기 위해 네오픽셀 클래스 가져오기, 괄호에는 클래스를 가져오기 위한 필수 인자들이 기입되어 있음.
void setup()
{
// 디버깅 콘솔 (9600보레이트로 통신)
Serial.begin(9600);
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass); // Blynk 시작
pixels.begin(); // 네오픽셀 시작
}
void loop()
{
Blynk.run(); // Blynk 데이터 송수신
}
// 가상핀 V0번에 쓰기 이벤트 발생 시 실행되는 함수
BLYNK_WRITE(V0)
{
int value = param.asInt(); // 전송 된 가상핀의 값을 value라는 변수에 저장
servo1.attach(servoPin); // 서보에 전원 인가
if(value == 1){ // 전송 값이 1이라면
servo1.write(180); // 서보 180도 회전
}else servo1.write(0); // 아니라면 0도 회전
delay(500); // 500ms 기다린 후
servo1.detach(); // 서보 전원 해제
}
// 가상핀 V1번에 쓰기 이벤트 발생 시 실행되는 함수
BLYNK_WRITE(V1)
{
int value = param.asInt(); // 전송 된 가상핀의 값을 value라는 변수에 저장
if(value == 1) static1(255, 111, 0); // static1 함수를 실행키기 (부드러운 노란색)
else static1(0,0,0); // static1 함수를 실행시켜 네오픽셀 R,G,B 값을 각각 0,0,0으로 설정
}
// 네오픽셀을 제어하기 위한 함수
void static1(int r, int g, int b) { // R,G,B 인자 가져오기
for (int i = 0; i <= NUM; i++) { // 네오픽셀 개수만큼 켜주어야 하기에 반복문
pixels.setPixelColor(i, pixels.Color(r, g, b)); // 네오픽셀 반복문 주소에 인자로 받은 값들을 빛으로 표현
pixels.show(); // 설정된 픽셀을 보여주기
}
}
위와 같이 코드를 작성하면 다음 영상처럼 작동한다.
https://youtu.be/_S13KnjoMeQ