[본 프로젝트 목적]
본 프로젝트에서는 MQTT프로토콜을 사용하여 nodeMCU에 있는 1개의 LED, 1개의 USB LED를 웹 페이지에서 조작할수 있으며 CDS를 통해서 조도 값을 DHT22를 통해서 온습도 값을 읽어들여서 웹 페이지에 표시할 것입니다. 이런 통신은 MQTT기반으로 제작합니다. 본 웹페이지를 서버는 Flask를 라즈베리파이에 올려서 작동시킬 것입니다..
[최종 작동영상]
[동작 구조]
[설치]
[Raspberry pi] :: raspberry pi의 터미널에 접속
sudo apt-get install python-pip :: install python package manager
sudo pip install falsk :: flask 설치
[Raspberry pi] :: raspberry pi에 MQTT Broker 설치
cd ~
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
cd /etc/apt/sources.list.d/
sudo wget http://repo.mosquitto.org/debian/mosquitto-stretch.list
sudo apt-get update
cd ~
sudo dpkg -i libssl1.0.0_1.0.1t-1+deb8u6_armhf.deb
wget http://ftp.nz.debian.org/debian/pool/main/libw/libwebsockets/libwebsockets3_1.2.2-1_armhf.deb
sudo dpkg -i libwebsockets3_1.2.2-1_armhf.deb
sudo apt-get install mosquitto mosquitto-clients
[Raspberry pi] :: raspberry pi에 mosquitto 설치 되었는지 확인
sudo /etc/init.d/mosquitto status
service mosquito status
service mosquito start
[nodeMCU Code]
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <ESP8266HTTPClient.h> #include "DHT.h"
#define D0 16 #define D1 5 #define D2 4 #define D3 0 #define D4 2 #define D5 14 #define D6 12 #define D7 13 #define D8 15 #define RELAY1_PIN D1 #define RELAY_OFF HIGH // HIGH 신호이면 릴레이 동작하지 않음 #define RELAY_ON LOW // LOW 신호이면 릴레이 동작함 int cdsPin = A0; DHT dht(D2, DHT22); const char* ssid = "여러분의 값을 입력하세요"; const char* password = "여러분의 값을 입력하세요"; char* topic = "nodemcu.iot.csee/1"; // #로 하면 모든 토픽으로부터 수신을 한다. char* server = "192.168.137.250"; //MQTT broker address char message_buff[100]; //initialise storage buffer char data[100] = {0}; WiFiClient wifiClient; //클라이언트로 작동 int ledPin = D0; //GPIO 13 int usbledPin = D1; // USB LED 를 위해서 float humidity, temperature; int light_val;
void callback(char* topic, byte* payload, unsigned int length){ int i = 0; Serial.println("Message arrived: topic: " + String(topic)); Serial.println("Length: "+ String(length,DEC)); for(i=0; i<length; i++){ message_buff[i] = payload[i]; } message_buff[i]= '\0';
String msgString = String(message_buff); Serial.println("Payload: "+ msgString); int state = digitalRead(ledPin); int usb_state = digitalRead(usbledPin); if (msgString == "led"){ digitalWrite(ledPin, !state); Serial.println("Toggle LED"); } else if ( msgString == "ledon"){ digitalWrite(ledPin, HIGH); Serial.println("LED ON"); } else if ( msgString == "ledoff"){ digitalWrite(ledPin, LOW); Serial.println("LED OFF"); } else if ( msgString == "usbledon"){ // usb 동작 부분 digitalWrite(RELAY1_PIN, RELAY_ON); Serial.println("USB LED ON!"); } else if ( msgString == "usbledoff"){ digitalWrite(RELAY1_PIN, RELAY_OFF); Serial.println("USB LED OFF!"); } else if ( msgString == "usbled"){ digitalWrite(RELAY1_PIN, !usb_state); Serial.println("USB LED Toggle"); } }
PubSubClient client(server, 1883, callback, wifiClient); void setup() { Serial.begin(115200); delay(10); pinMode(ledPin, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(ledPin, LOW); //LED off pinMode(RELAY1_PIN, OUTPUT); digitalWrite(RELAY1_PIN, RELAY_OFF);
//Connect to wifi my network; Serial.println(); Serial.println(); Serial.println("Connecting to "); Serial.println(ssid); //wifi에 연결을 시도한다. WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.println("."); }
//연결되면 접속한 IP가 뭔지 출력한다. Serial.println(""); Serial.println("WiFi Connected"); Serial.println(WiFi.localIP());
//Connection to broker if (client.connect("arduinoClient4")){ client.publish("nodemcu/3", "Hello World"); client.subscribe(topic); // nodemcu.iot.csee/1 client.subscribe("nodemcu.iot.csee/1/light"); Serial.println("브로커 연결에 성공했습니다."); }else{ Serial.println("브로커 연결에 실패했습니다....."); } } void loop() { humidity = dht.readHumidity(); temperature = dht.readTemperature(); light_val = analogRead(cdsPin);
if(isnan(humidity) || isnan(temperature)) Serial.println("Failed to read from DHT sensor!"); String payload = ""; payload += humidity; payload += ","; payload += temperature; payload += ","; payload += light_val; payload.toCharArray(data, (payload.length()+1)); client.publish("iot/1/sensors", data); client.loop(); } |
함수 설명
callback 함수
- 함수 원형 :: callback(char* topic, byte* payload, unsigned int length)
- subscribe한 topic에 대해서 publish를 통해 메시지가 전달된다면 실행되는 함수이다.
- PubSubClient.h에 속한 파일이다.
- topic : subscribe 한 topic
- length : payload의 길이
- callback함수 작동 : msgString에 publish한 message가 저장되어 있다. if 조건문을 지나면서 publish한 message가 led인지, ledon인지, ledoff인지, 등등 어떤 message가 전달되어 왔는가를 확인하는 것이다. 해당되는 조건문에 들어가면 digitalWrite를 이용여 전송된 message에 맞게 led가 동작시키는 것이다.
loop 함수
- DHT22와 CDS를 통한 온 습도 조도 값
[읽은 값 변수에 저장하기]
humidity = dht.readHumidity();
temperature = dht.readTemperature();
light_val = analogRead(cdsPin);
dht객체에서의 readHumidity와 readTemperature함수를 호출해서 리턴되는 습도와 온도 값을 humidity와 temperature값에 저장한다.
analogRead함수에서 리턴되는 조도 값을 light_val 변수에 저장한다.
[오류 체크하기]
if(isnan(humidity) || isnan(temperature))
isnan()은 괄호 안에 있는 변수가 숫자가 아닌 경우에 오류가 True가 되며 if문 안의 값이 실행된다. 즉 온 습도값을 정상적으로 읽지 못하면 if문이 실행된다.
[String으로 전환하여 publish하기]
[html - sample]
<html> <head> <meta charset="utf-8"> <!-- 합쳐지고 최소화된 최신 CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> <!-- 부가적인 테마 --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css"> <!-- 합쳐지고 최소화된 최신 자바스크립트 --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script> function onLED(){ // location.href = "light/ledon"; location.href = "/nodemcu.iot.csee/1/light/ledon"; } function offLED(){ // location.href = "light/ledoff"; location.href = "/nodemcu.iot.csee/1/light/ledoff"; } function toggleLED(){ location.href = "/nodemcu.iot.csee/1/light/led"; } function onUSBLED(){ location.href= "/nodemcu.iot.csee/1/light/usbledon"; } function offUSBLED(){ location.href= "/nodemcu.iot.csee/1/light/usbledoff"; } function toggleUSBLED(){ location.href= "/nodemcu.iot.csee/1/light/usbled"; } </script> <link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet"> /head> <body> <h3>실전 프로젝트 IoT</h3> <p> MQTT를 이용한 nodemcu 컨트롤 </p> <a href="/nodemcu.iot.csee/1" class="btn btn-primary" role="button">Home으로 이동</a> <br> <ul class="sensorList"> <li> LED 켜고 끄기 ver2 <br><br> <button type="button" class="btn btn-primary" onclick="onLED()"> LED On </button> <button type="button" class="btn btn-primary" onclick="offLED()" > LED Off </button> <button type="button" class="btn btn-primary" onclick="toggleLED()"> LED Toggle </button> {% if flag == 1 %} <strong style="color:red" > led on </strong> {% else %} <strong style="color:green"> led off </strong> {% endif %} </li> </ul> <ul> <li> USB LED 켜고 끄기 - 1217 오후ver <br><br> <button type="button" class="btn btn-primary" onclick="onUSBLED()"> USB LED On </button> <button type="button" class="btn btn-primary" onclick="offUSBLED()"> USB LED Off </button> <button type="button" class="btn btn-primary" onclick="toggleUSBLED()"> USB LED Toggle </button> {% if flag2 == 1 %} <strong style="color:red"> usb led on </strong> {% else %} <strong style="color:green"> usb led off </strong> {% endif %} </li> </ul> <!-- jQuery (부트스트랩의 자바스크립트 플러그인을 위해 필요합니다) --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script> <script type="text/javascript"> $( function(){ $("#toggle_led").change(function(){ window.location.href="/led"; } ) } ) </script> </body> </html> |
[참고 사이트]
저 또한 공부하면서 글을 작성하였습니다. 다음 사이트를 참고하였습니다.
https://randomnerdtutorials.com/raspberry-pi-publishing-mqtt-messages-to-esp8266/ ::: Raspberry Pi Publishing MQTT Messages to ESP8266
https://blog.naver.com/cosmosjs/221041652734 ::: 파이썬과 Flask를 이용한 나만의 웹앱 만들기(23): MQTT를 이용하여 NodeMCU(ESP8266) LED 제어하기
http://alnova2.tistory.com/710 ::: [Arduino] WiFly Shield에서 MQTT 사용하기
https://nodemcu.readthedocs.io/en/master/en/modules/mqtt/ ::: Nodemcu 공식 documentation
'Project > 완료 프로젝트' 카테고리의 다른 글
🚀백준 300문제 풀이 후기 (14) | 2020.03.07 |
---|---|
🏆️ 한국컴퓨터종합학술대회(KCC) 2019 학부생 논문경진대회에서 우수상을 수상하기까지 (0) | 2019.12.10 |
🏆️ 제6회 개발보안 경진대회 수상 후기 (9) | 2019.12.07 |
🐋 2019 웨일 확장앱 콘테스트 개발 이야기 (0) | 2019.12.03 |
Covenant - 정직한 교육이 세상을 바꿉니다. (9) | 2017.08.20 |