webOS 프로젝트

webOS를 활용한 HomeIoT : 스마트 가습기1 - 디바이스

하이하정 2021. 11. 27. 13:39

  • 전체 시습템 설계
  • 조명제어
  • 스마트 가습기
  • 수면 패턴 분석
  • 시스템 연동

 

ESP8266  개발환경 구축하기


1. Node MCU 와이파이 보드

Home IoT(가습기)를 만들기 위해 가습기 내부에 센서와 통신 기능을 내장하여 인터넷에 연결하는 기술이 필요합니다. 

이를 위해 아두이노 와이파이 보드(Node MCU 와이파이 보드)를 사용합니다.

 

이 보드의 특징은

- ESP8266 모듈이 내장되어 있으며, 아두이노를 활용하여 통신 등을 할 수 있습니다.

- 아두이노 스케치 환경을 지원합니다.

 

NodeMCU 보드는 다른 아두이노 계열의 보드들과 다르게 연결 후 아두이노 IDE에서 바로 업로드를 할 수 없습니다.따라서 ESP8266 칩에 대한 라이브러리를 설치해 NodeMCU 개발 보드를 위한 개발환경을 구축해주어야합니다.

 

2. 개발환경 구축하기

1) 라이브러리 설치하기

아두이노 IDE에서 파일 - 환경설정을 클릭 후 사진에 표시된 곳에 다음 링크를 적어줍니다.

http://arduino.esp8266.com/stable/package_esp8266com_index.json 

 

아두이노 IDE에서 툴-보드-보드 매니저를 클릭합니다.

 

보드매니저에서 'ESP8266'을 검색하여 'ESP8266 Community'를 설치해줍니다.

라이브러리 매니저에 'DHT11'을 검색하여 'DHT sensor library'를 설치해줍니다.

 

2) 보드 설정하기

아두이노 IDE에서 툴-보드-NodeMCU 1.0(ESP-12E Module)를 선택합니다. 

보드를 선태한 후 연결 포트를 확인 후 선택해주세요. (연결 포트는 장치관리자에서 확인 가능합니다.)

 

3) NodeMCU 개발보드 테스트하기

개발환경이 잘 구축되었나 확인해봅시다.

아두이노 IDE에서 파일-예제-01.Basics-Blink 를 선택합니다.

사진과 같이 내장 LED가 깜빡거리면 개발환경 구축 완성! 

 

회로구성


1. 회로 구성품

  • wifi 보드 : 아두이노 NodeMCU V1.0 와이파이 보드 /Lua WiFi ESP8266 - 12E CP2102 칩셋
  • 습도센서 : 아두이노 온습도센서 (DHT11)
  • 가습기 모듈 : 아두이노 초음파 가습기 모듈 (저희 동아리는 에듀이노에서 구매하였습니다.)

 

2. 회로도

위의 회로도를 참고하여 회로를 연결하세요.

습도센서나 가습기 모듈의 PIN은 사용할 핀번호로 임의로 정해주셔도 됩니다.

 

아래의 사진은 실제 회로 구성모습입니다.

 

코드


1.  클라이언트코드

↓전체 클라이언트코드

더보기
#include <ESP8266WiFi.h>
#include <WebSocketClient.h>
#include <ArduinoJson.h>
#include <string.h>

#include "DHT.h"

#define PIN_HUMD D5 // 가습기 제어 핀
#define PIN_DHT D2 // 습도 센서 핀
#define DHTTYPE DHT11
DHT dht(PIN_DHT, DHTTYPE);

// wifi 연결 정보
const char* ssid     = "Seoultech_dream";
const char* password = "";

// 서버 접속 정보
char path[] = "/";
char host[] = "10.50.51.32";
int port = 9999;

WiFiClient client;
WebSocketClient webSocketClient;

// JSON
StaticJsonDocument<200> jsonObj;

void setup() {
  // 습도 센서 설정
  dht.begin();
  
  // 가습기 설정
  pinMode(PIN_HUMD, OUTPUT);
  digitalWrite(PIN_HUMD, LOW);

  Serial.begin(115200);
  delay(10);

  // wifi 연결 코드
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  delay(1000);
  
  // Connect to the websocket server
  if (client.connect(host, port)) {
    Serial.println("Connected");
  } else {
    Serial.println("Connection failed.");
    while(1) {}
  }

  // Handshake with the server
  webSocketClient.path = path;
  webSocketClient.host = host;
  if (webSocketClient.handshake(client)) {
    Serial.println("Handshake successful");
  } else {
    Serial.println("Handshake failed.");
    while(1) {}  
  }
}

void printHumAndTem(float hum, float temp) {
  Serial.print("D_Humidity: ");
  Serial.print(hum);
  Serial.print(" %");
  Serial.print("D_Temperature: ");
  Serial.print(temp);
  Serial.println(" *C");
}

int sendCnt = 2;
const int maxSendCnt = 2;

void loop() {
  float currHum = dht.readHumidity();  // 센서의 습도를 읽어와 currHum에 저장한다.
  float currTemp = dht.readTemperature(); // 센서의 온도를 읽어와 currTemp에 저장한다.
  printHumAndTem(currHum, currTemp);
  delay(1000);
  
  String data;
  if(client.connected()){
    if(sendCnt == maxSendCnt) {
      // websocket으로 data를 보낸다.
      jsonObj["msgType"] = "sendValue";
      jsonObj["deviceType"] = "humd";
      jsonObj["currHum"] = currHum;
      jsonObj["currTemp"] = currTemp;
      
      String jsonString;
      serializeJson(jsonObj, jsonString);
      webSocketClient.sendData(jsonString);
      Serial.print("Send: "); Serial.println(jsonString);
      jsonObj.clear();
      sendCnt = 0;
    }

    // websocket에서 data를 받아온다.
    webSocketClient.getData(data);
    if(data.length() > 0) {
      Serial.print("getData: "); Serial.println(data);
      auto ret = deserializeJson(jsonObj, data);
      if(!String(jsonObj["msgType"]).compareTo("command") && !String(jsonObj["deviceType"]).compareTo("humd")) {
        if(!String(jsonObj["status"]).compareTo("on")){
          digitalWrite(PIN_HUMD, HIGH);
          Serial.println("humd On.");
        }
        else {
          digitalWrite(PIN_HUMD, LOW);
          Serial.println("humd Off.");
        }
        jsonObj.clear();
      }
    } // end-of-if(data.length() > 0)
  } // end-of-if(client.connected())
  delay(500);
  sendCnt++;
} // end-of-loop

 

 

 

1-1) 코드 상세 설명

// wifi 연결 정보
const char* ssid     = "Seoultech_dream";
const char* password = "";

// 서버 접속 정보
char path[] = "/";
char host[] = "10.50.51.32";
int port = 9999;

WiFiClient client;
WebSocketClient webSocketClient;

// JSON
StaticJsonDocument<200> jsonObj;

void setup() {
  // 습도 센서 설정
  dht.begin();
  
  // 가습기 설정
  pinMode(PIN_HUMD, OUTPUT);
  digitalWrite(PIN_HUMD, LOW);

  Serial.begin(115200);
  delay(10);

  // wifi 연결 코드
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  delay(1000);
  
  // Connect to the websocket server
  if (client.connect(host, port)) {
    Serial.println("Connected");
  } else {
    Serial.println("Connection failed.");
    while(1) {}
  }

  // Handshake with the server
  webSocketClient.path = path;
  webSocketClient.host = host;
  if (webSocketClient.handshake(client)) {
    Serial.println("Handshake successful");
  } else {
    Serial.println("Handshake failed.");
    while(1) {}  
  }
}

Arduino-sketch에 ESP8266 보드에 업로드 할 클라이언트 코드를 작성합니다.

와이파이 주소와 비밀번호 및 포트를 바꾸어줍니다.

ip주소는 각자의 서버가 연결된 주소로 바꾸어줍니다.

ip 주소는 명령창에 ipconfig 명령어를 통해 확인하거나, wifi 속성에서 확인할 수 있습니다. 

 

json 포맷으로 통신하기 위해 ArduinoJson 라이브러리를 다운받아주는 등 위 코드의 헤더파일을 저장해줍니다. 

시리얼 모니터에 'Handshake successful' 문구까지 출력되었다면 서버와 클라이언트의 연결이 성공한 것입니다.

 

void printHumAndTem(float hum, float temp) {
  Serial.print("D_Humidity: ");
  Serial.print(hum);
  Serial.print(" %");
  Serial.print("D_Temperature: ");
  Serial.print(temp);
  Serial.println(" *C");
}

int sendCnt = 2;
const int maxSendCnt = 2;

void loop() {
  float currHum = dht.readHumidity();  // 센서의 습도를 읽어와 currHum에 저장한다.
  float currTemp = dht.readTemperature(); // 센서의 온도를 읽어와 currTemp에 저장한다.
  printHumAndTem(currHum, currTemp);
  delay(1000);
  
  String data;
  if(client.connected()){
    if(sendCnt == maxSendCnt) {
      // websocket으로 data를 보낸다.
      jsonObj["msgType"] = "sendValue";
      jsonObj["deviceType"] = "humd";
      jsonObj["currHum"] = currHum;
      jsonObj["currTemp"] = currTemp;
      
      String jsonString;
      serializeJson(jsonObj, jsonString);
      webSocketClient.sendData(jsonString);
      Serial.print("Send: "); Serial.println(jsonString);
      jsonObj.clear();
      sendCnt = 0;
    }

    // websocket에서 data를 받아온다.
    webSocketClient.getData(data);
    if(data.length() > 0) {
      Serial.print("getData: "); Serial.println(data);
      auto ret = deserializeJson(jsonObj, data);
      if(!String(jsonObj["msgType"]).compareTo("command") && !String(jsonObj["deviceType"]).compareTo("humd")) {
        if(!String(jsonObj["status"]).compareTo("on")){
          digitalWrite(PIN_HUMD, HIGH);
          Serial.println("humd On.");
        }
        else {
          digitalWrite(PIN_HUMD, LOW);
          Serial.println("humd Off.");
        }
        jsonObj.clear();
      }
    } // end-of-if(data.length() > 0)
  } // end-of-if(client.connected())
  delay(500);
  sendCnt++;
} // end-of-loop

온/습도 모듈에서 온/습도 값을 읽어와 server로 보내줍니다.

가습기 모듈(Client)은 server에서 받은 on/off command로 작동합니다.

 ※ Server의 동작 설명은 Service 글을 참고해주세요 :)