본문 바로가기

ESP32

ESP32 MQTT 메시지를 게시하고 토픽을 구독하는 방법

반응형

 

 

ESP32 MQTT – Arduino IDE로 게시 및 구독

 

이 프로젝트는 MQTT 통신 프로토콜을 ESP32와 함께 사용하여 메시지를 게시하고 토픽을 구독하는 방법을 보여줍니다. 예를 들어, Node-RED 대시보드에 BME280 센서 판독값을 게시하고 ESP32 출력을 제어합니다. ESP32는 Arduino IDE를 사용하여 프로그래밍합니다.

 

 

프로젝트 개요

 

이 예에서는 MQTT 통신 프로토콜을 사용하여 ESP32 출력을 제어하고 ESP32에서 센서 판독값을 수신하는 Node-RED 애플리케이션이 있습니다. Node-RED 애플리케이션은 Raspberry Pi에서 실행됩니다.

 

동일한 Raspberry Pi에 설치된 Mosquitto 브로커를 사용합니다. 브로커는 모든 메시지를 수신하고, 메시지를 필터링하고, 누가 관심이 있는지 결정하고, 모든 구독된 클라이언트에 메시지를 게시하는 역할을 합니다.

 

다음 그림은 이 튜토리얼에서 수행할 작업의 개요를 보여줍니다.

 

 

  • Node-RED 애플리케이션은 토픽 esp32/output에 메시지("on" 또는 "off")를 게시합니다. ESP32는 해당 토픽에 구독되어 있습니다. 따라서 LED를 켜거나 끄기 위해 "on" 또는 "off" 메시지를 수신합니다.
  •  
  • ESP32는 esp32/temperature 토픽에 온도를 게시하고 esp32/humidity 토픽에 습도를 게시합니다. Node-RED 애플리케이션은 해당 토픽에 구독되어 있습니다. 따라서 예를 들어 차트나 게이지에 표시할 수 있는 온도 및 습도 판독값을 수신합니다.

 

참고: MQTT와 함께 ESP8266 및 Node-RED를 사용하는 방법에 대한 유사한 튜토리얼도 있습니다.

 

필수 조건

 

  • Raspberry Pi에 익숙해야 합니다. Raspberry Pi 시작하기를 읽어보세요.
  • Raspberry Pi에 Raspbian 운영 체제가 설치되어 있어야 합니다. Raspbian Lite 설치, SSH 활성화 및 연결을 읽어보세요.
  • Pi에 Node-RED와 Node-RED 대시보드를 설치해야 합니다.
  • MQTT가 무엇이고 어떻게 작동하는지 알아보세요.

 

홈 오토메이션을 좋아하고 Node-RED, Raspberry Pi, ESP8266 및 Arduino에 대해 자세히 알고 싶다면 저희 코스인 Node-RED, ESP8266 및 Arduino로 홈 오토메이션 시스템 구축을 추천합니다. ESP32에 전념하는 코스도 있습니다. Arduino IDE로 ESP32 배우기 코스에 등록하세요.

 

필요한 부품

 

다음은 회로를 만드는 데 필요한 부품입니다(아래 링크를 클릭하여 Maker Advisor에서 최저가를 찾아보세요):

 

 

  • Raspberry Pi – 최고의 Raspberry Pi 3 스타터 키트 읽기
  • ESP32 DOIT DEVKIT V1 보드 – ESP32 개발 보드 리뷰 및 비교 읽기
  • BME280 센서 모듈
  • 1x 5mm LED
  • 1x 220Ω 저항기
  • 브레드보드
  • 점퍼 와이어

 

이전 링크를 사용하거나 MakerAdvisor.com/tools로 바로 이동하여 프로젝트에 필요한 모든 부품을 최저가로 찾을 수 있습니다!

 

BME280 센서 모듈 소개

 

BME280 센서 모듈은 온도, 습도, 압력을 읽습니다. 압력은 고도에 따라 변하기 때문에 고도를 추정할 수도 있습니다. 그러나 이 튜토리얼에서는 온도와 습도만 읽습니다. 이 센서 모듈에는 여러 버전이 있지만 아래 그림에 표시된 버전을 사용합니다.

 

 

센서는 SPI 또는 I2C 통신 프로토콜을 사용하여 통신할 수 있습니다(이 센서의 모듈은 I2C로만 통신하며, 여기에는 4개의 핀만 있습니다).

 

SPI 통신 프로토콜을 사용하려면 다음 핀을 사용합니다.

 

  • SCK – SPI 클록 핀입니다.
  • SDO – MISO
  • SDI – MOSI
  • CS – 칩 선택

 

I2C 통신 프로토콜을 사용하려면 센서는 다음 핀을 사용합니다.

 

  • SCK – SCL 핀
  • SDI – SDA 핀

 

회로도

 

BME280 센서 모듈과 I2C 통신을 사용합니다. 이를 위해 다음 회로도에 표시된 대로 센서를 ESP32 SDA 및 SCL 핀에 연결합니다.

 

또한 GPIO 4에 연결된 LED인 ESP32 출력을 제어합니다.

 

 

다음은 회로의 모습입니다.

 

 

Arduino IDE 준비

 

Arduino IDE용 애드온이 있어 Arduino IDE와 해당 프로그래밍 언어를 사용하여 ESP32를 프로그래밍할 수 있습니다. 아직 준비하지 않았다면 다음 튜토리얼 중 하나를 따라 Arduino IDE를 ESP32와 함께 작동하도록 준비합니다.

 

Windows 지침 - Arduino IDE의 ESP32 보드

Mac 및 Linux 지침 - Arduino IDE의 ESP32 보드

 

ESP32 애드온이 설치되었는지 확인한 후 이 튜토리얼을 계속 진행할 수 있습니다.

 

PubSubClient 라이브러리 설치

 

PubSubClient 라이브러리는 MQTT를 지원하는 서버와 간단한 게시/구독 메시징을 수행하기 위한 클라이언트를 제공합니다(기본적으로 ESP32가 Node-RED와 통신할 수 있도록 함).

 

  1. 여기를 클릭하여 PubSubClient 라이브러리를 다운로드합니다. 다운로드 폴더에 .zip 폴더가 있어야 합니다.
  2. .zip 폴더의 압축을 풀면 pubsubclient-master 폴더가 나옵니다.
  3. 폴더 이름을 pubsubclient-master에서 pubsubclient로 바꿉니다.
  4. pubsubclient 폴더를 Arduino IDE 설치 라이브러리 폴더로 옮깁니다.
  5. 그런 다음 Arduino IDE를 다시 엽니다.

 

라이브러리에는 여러 예제 스케치가 들어 있습니다. Arduino IDE 소프트웨어 내에서 파일 > 예제 > PubSubClient를 참조하세요.

 

중요: PubSubClient는 ESP32와 완벽하게 호환되지 않지만, 이 튜토리얼에서 제공하는 예제는 테스트 중에 매우 안정적으로 작동합니다.

 

BME280 라이브러리 설치

 

BME280 센서 모듈에서 판독값을 얻으려면 Adafruit_BME280 라이브러리를 사용합니다. 다음 단계에 따라 Arduino IDE에 라이브러리를 설치하세요.

 

  1. 여기를 클릭하여 Adafruit-BME280 라이브러리를 다운로드하세요. 다운로드 폴더에 .zip 폴더가 있어야 합니다.
  2. .zip 폴더의 압축을 풀면 Adafruit-BME280-Library-master 폴더가 나옵니다.
  3. 폴더 이름을 Adafruit-BME280-Library-master에서 Adafruit_BME280_Library로 바꿉니다.
  4. Adafruit_BMPE280_Library 폴더를 Arduino IDE 설치 라이브러리 폴더로 옮깁니다.
  5. 마지막으로 Arduino IDE를 다시 엽니다.

 

또는 Sketch > Include Library > Manage Libraries로 이동하여 "adafruit bme280"을 입력하여 라이브러리를 검색할 수 있습니다. 그런 다음 설치를 클릭합니다.

 

Adafruit_Sensor 라이브러리 설치

 

BME280 라이브러리를 사용하려면 Adafruit_Sensor 라이브러리도 설치해야 합니다. 다음 단계에 따라 라이브러리를 설치합니다.

 

  • 여기를 클릭하여 Adafruit_Sensor 라이브러리를 다운로드합니다. 다운로드 폴더에 .zip 폴더가 있어야 합니다.
  • .zip 폴더의 압축을 풀면 Adafruit_Sensor-master 폴더가 나옵니다.
  • 폴더 이름을 Adafruit_Sensor-master에서 Adafruit_Sensor로 바꿉니다.
  • Adafruit_Sensor 폴더를 Arduino IDE 설치 라이브러리 폴더로 옮깁니다.
  • 마지막으로 Arduino IDE를 다시 엽니다.

 

코드 업로드

 

이제 다음 코드를 ESP32에 업로드할 수 있습니다. 코드에는 변경해야 할 부분에 주석이 달려 있습니다. 코드를 자신의 SSID, 비밀번호, Raspberry Pi IP 주소로 편집해야 합니다.

 

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

// Replace the next variables with your SSID/Password combination
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Add your MQTT Broker IP address, example:
//const char* mqtt_server = "192.168.1.144";
const char* mqtt_server = "YOUR_MQTT_BROKER_IP_ADDRESS";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

//uncomment the following lines if you're using SPI
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
float temperature = 0;
float humidity = 0;

// LED Pin
const int ledPin = 4;

void setup() {
  Serial.begin(115200);
  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  //status = bme.begin();  
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  pinMode(ledPin, OUTPUT);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  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());
}

void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();

  // Feel free to add more if statements to control more GPIOs with MQTT

  // If a message is received on the topic esp32/output, you check if the message is either "on" or "off". 
  // Changes the output state according to the message
  if (String(topic) == "esp32/output") {
    Serial.print("Changing output to ");
    if(messageTemp == "on"){
      Serial.println("on");
      digitalWrite(ledPin, HIGH);
    }
    else if(messageTemp == "off"){
      Serial.println("off");
      digitalWrite(ledPin, LOW);
    }
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      // Subscribe
      client.subscribe("esp32/output");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  long now = millis();
  if (now - lastMsg > 5000) {
    lastMsg = now;
    
    // Temperature in Celsius
    temperature = bme.readTemperature();   
    // Uncomment the next line to set temperature in Fahrenheit 
    // (and comment the previous temperature line)
    //temperature = 1.8 * bme.readTemperature() + 32; // Temperature in Fahrenheit
    
    // Convert the value to a char array
    char tempString[8];
    dtostrf(temperature, 1, 2, tempString);
    Serial.print("Temperature: ");
    Serial.println(tempString);
    client.publish("esp32/temperature", tempString);

    humidity = bme.readHumidity();
    
    // Convert the value to a char array
    char humString[8];
    dtostrf(humidity, 1, 2, humString);
    Serial.print("Humidity: ");
    Serial.println(humString);
    client.publish("esp32/humidity", humString);
  }
}

 

이 코드는 MQTT 프로토콜을 통해 esp32/temperature 및 esp32/humidity 토픽에 온도 및 습도 판독값을 게시합니다.

 

ESP32는 esp32/output 토픽에 구독되어 Node-RED 애플리케이션에서 해당 토픽에 게시한 메시지를 수신합니다. 그런 다음 수신된 메시지에 따라 LED를 켜거나 끕니다.

 

MQTT 토픽 구독

 

reconnect() 함수에서 MQTT 토픽을 구독할 수 있습니다. 이 경우 ESP32는 esp32/output에만 구독됩니다.

 

client.subscribe("esp32/output");

 

callback() 함수에서 ESP32는 구독된 토픽의 MQTT 메시지를 수신합니다. MQTT 토픽과 메시지에 따라 LED를 켜거나 끕니다.

 

// 토픽 esp32/output에서 메시지를 수신하면 메시지가 "켜짐"인지 "꺼짐"인지 확인합니다.
// 메시지에 따라 출력 상태를 변경합니다.

if (String(topic) == "esp32/output") {
  Serial.print("Changing output to ");
  if (messageTemp == "on") {
    Serial.println("on");
    digitalWrite(ledPin, HIGH);
  }
  else if (messageTemp == "off") {
    Serial.println("off");
    digitalWrite(ledPin, LOW);
  }
}

 

 

MQTT 메시지 게시

 

loop()에서 5초마다 새로운 판독값이 게시됩니다.

 

if (now - lastMsg > 5000) { ... }

 

기본적으로 ESP32는 섭씨로 온도를 전송하지만 마지막 줄의 주석 처리를 해제하여 화씨로 온도를 전송할 수 있습니다.

 

// Temperature in Celsius
temperature = bme.readTemperature(); 
// Uncomment the next line to set temperature in Fahrenheit 
// (and comment the previous temperature line)
//temperature = 1.8 * bme.readTemperature() + 32; // Temperature in Fahrenheit

 

온도 float 변수를 char 배열로 변환해야 esp32/temperature 토픽에 온도 판독값을 게시할 수 있습니다.

 

// Convert the value to a char array
char tempString[8];
dtostrf(temperature, 1, 2, tempString);
Serial.print("Temperature: ");
Serial.println(tempString);
client.publish("esp32/temperature", tempString);

 

같은 프로세스를 반복하여 esp32/humidity 토픽에 습도 판독값을 게시합니다.

 

humidity = bme.readHumidity();
// Convert the value to a char array
char humString[8];
dtostrf(humidity, 1, 2, humString);
Serial.print("Humidity: ");
Serial.println(humString);
client.publish("esp32/humidity", humString);

 

Node-RED 흐름 만들기

 

흐름을 만들기 전에 Raspberry Pi에 다음을 설치해야 합니다.

 

  • Node-RED
  • Node-RED 대시보드
  • Mosquitto Broker

 

그런 다음 제공된 Node-RED 흐름을 가져옵니다. GitHub 저장소로 이동하거나 아래 그림을 클릭하여 원시 파일을 보고 제공된 코드를 복사합니다.

 

 

그런 다음 Node-RED 창에서 오른쪽 상단 모서리에 있는 메뉴를 선택하고 가져오기 > 클립보드로 이동합니다.

 

 

그런 다음 제공된 코드를 붙여넣고 가져오기를 클릭합니다.

 

 

다음 노드가 로드되어야 합니다.

 

 

변경한 후 배포 버튼을 클릭하여 모든 변경 사항을 저장합니다.

 

 

Node-RED UI

 

이제 Node-RED 애플리케이션이 준비되었습니다. Node-RED UI에 액세스하고 애플리케이션이 어떻게 보이는지 확인하려면 로컬 네트워크의 모든 브라우저에 액세스하여 다음을 입력합니다.

 

http://Your_RPi_IP_address:1880/ui

 

귀하의 애플리케이션은 다음 그림과 같이 표시되어야 합니다. 스위치로 LED를 켜고 끌 수 있고, 차트에서 온도 판독값을 보고 게이지에서 습도 값을 볼 수 있습니다.

 

 

데모

 

다음 비디오에서 라이브 데모를 시청하세요.

 

Arduino IDE 직렬 모니터를 열어 수신 및 게시되는 MQTT 메시지를 살펴보세요.

 

 

 

마무리

 

요약하면 Node-RED와 MQTT 통신 프로토콜을 사용하여 ESP32로 조명을 켜고 센서를 모니터링할 수 있는 기본 개념을 보여드렸습니다. 이 예제를 사용하여 자체 홈 자동화 시스템에 통합하거나, 더 많은 출력을 제어하거나, 다른 센서를 모니터링할 수 있습니다.

 

다음도 읽어보시면 좋을 듯합니다.

 

  • Arduino IDE 코스로 ESP32 배우기
  • ESP32 및 ESP8266을 사용한 Alexa(Echo) - 음성 제어 릴레이
  • 올인원 ESP32 기상 관측소 실드 만들기
  • ESP32에서 Google 시트에 센서 판독값 게시
  • ESP32와 DHT11 DHT22 온도 습도 웹 서버
  • Arduino IDE를 사용한 ESP32 웹 서버

 

이 튜토리얼이 도움이 되었기를 바랍니다.

 

읽어주셔서 감사합니다. 배움을 멈추지 마세요. 하지 않은 일에 대한 후회의 고통은 도전과 실패에 따른 고통보다 훨씬 큽니다. 고통은 죽는 순간까지 떠나지 않습니다.

 

읽어주셔서 감사합니다.

반응형

더욱 좋은 정보를 제공하겠습니다.~ ^^