Мультисенсорный шилд ESP8266 с Node-RED

В этом проекте вы узнаете, как интегрировать Мультисенсорный шилд ESP8266 для платы Wemos D1 Mini с Node-RED. Мультисенсорный шилд ESP8266 установит MQTT-соединение с Raspberry Pi, на котором работают Node-RED и MQTT-брокер Mosquitto.

Мультисенсорный шилд ESP8266 с Node-RED

Обзор проекта

Мультисенсорный шилд ESP8266 состоит из датчика температуры, датчика движения, фоторезистора (LDR) и 3-контактного разъёма, к которому можно подключить любое выходное устройство, например модуль реле.

Мультисенсорный шилд с обозначениями компонентов

Мы будем использовать Mosquitto брокер, установленный на том же Raspberry Pi, на котором работает Node-RED. Брокер отвечает за приём всех сообщений, их фильтрацию, определение того, кто в них заинтересован, и публикацию сообщений для всех подписанных клиентов. Чтобы узнать больше о MQTT, вы можете прочитать: Что такое MQTT и как он работает.

На следующей схеме показан обзор того, что мы будем делать в этом руководстве.

Диаграмма MQTT -- обзор проекта
  • Приложение Node-RED публикует сообщения (»on» или «off») в топике esp8266/output. ESP8266 подписан на этот топик. Таким образом, он получает сообщение с «on» или «off» для включения или выключения выхода.

  • ESP8266 публикует температуру в топике esp8266/temperature и освещённость в топике esp8266/ldr. Приложение Node-RED подписано на эти топики. Таким образом, оно получает показания температуры и освещённости, которые отображаются на графике и индикаторе.

  • Node-RED подписан на топик esp8266/motion. ESP8266 публикует в этом топике при обнаружении движения. Когда движение обнаружено, сообщение «MOTION DETECTED!» отображается в течение 10 секунд в текстовом виджете Node-RED Dashboard.

Рекомендуемое чтение: ESP32 MQTT -- Публикация и подписка с Arduino IDE

Предварительные требования

Если вам нравится домашняя автоматизация и вы хотите узнать больше о Node-RED, Raspberry Pi, ESP8266 и Arduino, мы рекомендуем скачать наш курс: Создайте систему домашней автоматизации с помощью Node-RED, ESP8266 и Arduino.

Ресурсы

Все ресурсы, необходимые для сборки этого проекта, вы можете найти по ссылкам ниже (или вы можете посетить проект на GitHub):

Схема

Вы можете собрать мультисенсорный шилд на печатной плате или собрать схему мультисенсорного шилда на макетной плате.

Вот список деталей, которые вам понадобятся для сборки схемы:

Вы можете воспользоваться ссылками выше или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все детали для ваших проектов по лучшей цене!

После того как вы собрали все необходимые детали, соберите схему, следуя приведённой ниже схеме:

Схема мультисенсорного шилда Wemos D1 Mini

Вот как выглядит схема на макетной плате:

Мультисенсорный шилд на макетной плате

В качестве альтернативы вы можете изготовить печатную плату для WeMos D1 Mini (узнайте, как Мультисенсорный шилд ESP8266):

Сборка мультисенсорного шилда ESP8266 WeMos D1 Mini

Вот как выглядит схема с использованием печатной платы шилда с 3D-печатным корпусом:

Мультисенсорный шилд с реле в 3D-печатном корпусе

Подготовка Arduino IDE

Мы будем программировать ESP8266 с помощью Arduino IDE. Чтобы загрузить код на ESP8266 через Arduino IDE, вам необходимо установить дополнение ESP8266 (Как установить плату ESP8266 в Arduino IDE). Вам также потребуется установить три дополнительные библиотеки для запуска кода на ESP8266.

Установка библиотеки PubSubClient

Библиотека PubSubClient предоставляет клиент для простого обмена сообщениями по принципу публикации/подписки с сервером, поддерживающим MQTT (по сути, позволяет вашему ESP8266 взаимодействовать с Node-RED).

  1. Нажмите здесь, чтобы скачать библиотеку PubSubClient. У вас должен появиться файл .zip в папке «Загрузки».

  2. Распакуйте файл .zip – у вас должна появиться папка pubsubclient-master.

  3. Переименуйте папку из pubsubclient-master в pubsubclient.

  4. Переместите папку pubsubclient в папку libraries вашей установки Arduino IDE.

Библиотека OneWire

  1. Нажмите здесь, чтобы скачать библиотеку OneWire. У вас должен появиться файл .zip в папке «Загрузки».

  2. Распакуйте файл .zip – у вас должна появиться папка OneWire-master.

  3. Переименуйте папку из OneWire-master в OneWire.

  4. Переместите папку OneWire в папку libraries вашей установки Arduino IDE.

Библиотека Dallas Temperature

  1. Нажмите здесь, чтобы скачать библиотеку DallasTemperature. У вас должен появиться файл .zip в папке «Загрузки».

  2. Распакуйте файл .zip – у вас должна появиться папка Arduino-Temperature-Control-Library-master.

  3. Переименуйте папку из Arduino-Temperature-Control-Library-master в DallasTemperature.

  4. Переместите папку DallasTemperature в папку libraries вашей установки Arduino IDE.

  5. Наконец, перезапустите Arduino IDE.

Загрузка кода

Скопируйте следующий код в Arduino IDE. Код хорошо прокомментирован в тех местах, где вам нужно внести изменения. Вам необходимо отредактировать код, указав свой SSID, пароль и IP-адрес MQTT-брокера (IP-адрес Raspberry Pi).

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

// Загрузка библиотек
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Замените на свои учётные данные сети
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Измените переменную на IP-адрес вашего Raspberry Pi, чтобы подключиться к MQTT-брокеру
const char* mqtt_server = "REPLACE_WITH_YOUR_MQTT_BROKER";
// Пример IP MQTT-брокера
//const char* mqtt_server = "192.168.1.144";

// Инициализация espClient. Измените имя espClient, если у вас несколько ESP в системе домашней автоматизации
WiFiClient espClient;
PubSubClient client(espClient);

// Переменная для хранения показаний температуры
String temperatureString = "";

// Установка GPIO для: выходной переменной, светодиода статуса, PIR-датчика движения и LDR
const int output = 15;
const int statusLed = 12;
const int motionSensor = 5;
const int ldr = A0;
// Хранение текущего состояния выхода
String outputState = "off";

// GPIO, к которому подключён DS18B20
const int oneWireBus = 4;
// Настройка экземпляра oneWire для связи с любыми устройствами OneWire
OneWire oneWire(oneWireBus);
// Передача ссылки oneWire датчику Dallas Temperature
DallasTemperature sensors(&oneWire);

// Таймеры -- вспомогательные переменные
unsigned long now = millis();
unsigned long lastMeasure = 0;
boolean startTimer = false;
unsigned long currentTime = millis();
unsigned long previousTime = 0;

// Не изменяйте функцию ниже.
// Эта функция подключает ваш ESP8266 к роутеру
void setup_wifi() {
  delay(10);
  // Начинаем подключение к WiFi-сети
  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.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
}

// Эта функция выполняется, когда какое-либо устройство публикует сообщение в топик, на который подписан ваш ESP8266
// Измените функцию ниже, чтобы добавить логику в вашу программу, чтобы при публикации устройством сообщения
// в топик, на который подписан ваш ESP8266, вы могли выполнить какое-либо действие
void callback(String 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();

  // Вы можете добавить больше условий if для управления большим количеством GPIO через MQTT
  // Если сообщение получено в топике esp8266/output, проверяем, является ли оно on или off.
  // Переключает выход в соответствии с полученным сообщением
  if(topic=="esp8266/output"){
    Serial.print("Changing output to ");
    if(messageTemp == "on"){
      digitalWrite(output, LOW);
      Serial.print("on");
    }
    else if(messageTemp == "off"){
      digitalWrite(output, HIGH);
      Serial.print("off");
    }
  }
  Serial.println();
}

// Эта функция переподключает ваш ESP8266 к MQTT-брокеру
// Измените функцию ниже, если хотите подписаться на больше топиков с вашим ESP8266
void reconnect() {
  // Цикл до успешного переподключения
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Создание случайного ID клиента
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Попытка подключения
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Подписка или переподписка на топик
      // Вы можете подписаться на больше топиков (для управления большим количеством выходов)
      client.subscribe("esp8266/output");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Ожидание 5 секунд перед повторной попыткой
      delay(5000);
    }
  }
}

// Проверяет, было ли обнаружено движение и активированы ли датчики. Затем запускает таймер.
ICACHE_RAM_ATTR void detectsMovement() {
  Serial.println("MOTION DETECTED!");
  client.publish("esp8266/motion", "MOTION DETECTED!");
  previousTime = millis();
  startTimer = true;
}

void setup() {
  // Запуск датчика DS18B20
  sensors.begin();

  // Последовательный порт для отладки
  Serial.begin(115200);

  // Режим PIR-датчика движения, затем установка функции прерывания и режима RISING
  pinMode(motionSensor, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

  // Инициализация выходной переменной и светодиода как OUTPUT
  pinMode(output, OUTPUT);
  pinMode(statusLed, OUTPUT);
  digitalWrite(output, HIGH);
  digitalWrite(statusLed, LOW);

  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  // Переменная таймера с текущим временем
  now = millis();

  // Публикация новых показаний температуры и LDR каждые 30 секунд
  if (now - lastMeasure > 30000) {
    lastMeasure = now;
    sensors.requestTemperatures();
    // Температура в градусах Цельсия
    temperatureString = String(sensors.getTempCByIndex(0));
    // Раскомментируйте следующую строку для температуры в градусах Фаренгейта
    //temperatureString = String(sensors.getTempFByIndex(0));
    // Публикация значений температуры
    client.publish("esp8266/temperature", temperatureString.c_str());
    Serial.println("Temperature published");

    // Публикация значений LDR
    client.publish("esp8266/ldr", String(analogRead(ldr)).c_str());
    Serial.println("LDR values published");
  }
  // После 10 секунд с момента обнаружения движения публикуется сообщение "No motion"
  if ((now - previousTime > 10000) && startTimer) {
    client.publish("esp8266/motion", "No motion");
    Serial.println("Motion stopped");
    startTimer = false;
  }
}

Просмотреть исходный код

Этот код довольно длинный для объяснения, поэтому вы можете просто заменить следующие три переменные своими данными, и код сразу заработает.

const char* ssid = "";
const char* password = "";
const char* mqtt_server = "";

Если вы хотите узнать, как работает этот код, продолжайте чтение.

callback()

В функции callback(), когда новое сообщение получено в топике esp8266/output, вы проверяете, является ли сообщение on или off, чтобы включить или выключить выход соответственно.

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

Публикация показаний температуры и LDR

Этот раздел кода публикует новые показания температуры и LDR каждые 30 секунд. Показания температуры публикуются в топике esp8266/temperature. Показания освещённости публикуются в топике esp8266/ldr.

if (now - lastMeasure > 30000) {
  lastMeasure = now;
  sensors.requestTemperatures();
  // Temperature in Celsius degrees
  temperatureString = String(sensors.getTempCByIndex(0));
  // Uncomment the next line for temperature in Fahrenheit degrees
  //temperatureString = String(sensors.getTempFByIndex(0));
  // Publishes Temperature values
  client.publish("esp8266/temperature", temperatureString.c_str());
  Serial.println("Temperature published");

  // Publishes LDR values
  client.publish("esp8266/ldr", String(analogRead(ldr)).c_str());
  Serial.println("LDR values published");
}

Примечание: температура публикуется в градусах Цельсия, но вы можете раскомментировать следующую строку для температуры в градусах Фаренгейта:

temperatureString = String(sensors.getTempFByIndex(0));

Обнаружение движения

При обнаружении движения вызывается функция detectsMovement(), публикуется сообщение «MOTION DETECTED!» в топике esp8266/motion и запускается таймер:

void detectsMovement() {
  Serial.println("MOTION DETECTED!");
  client.publish("esp8266/motion", "MOTION DETECTED!");
  previousTime = millis();
  startTimer = true;
}

Если движение не обнаружено в течение более 10 секунд, в топике esp8266/motion публикуется новое сообщение с текстом «No motion»:

// After 10 seconds have passed since motion was detected, publishes a "No motion" message
if ((now - previousTime > 10000) && startTimer) {
  client.publish("esp8266/motion", "No motion");
  Serial.println("Motion stopped");
  startTimer = false;
}

Это основные разделы кода, на которые вам нужно обратить внимание. Вы можете изменять сообщения, подписываться на дополнительные топики для управления дополнительными выходами или публиковать показания других датчиков.

Тестирование подключения

Загрузите код на свою плату. После загрузки, при работающем приложении Node-RED и брокере Mosquitto на Raspberry Pi, откройте монитор последовательного порта Arduino IDE со скоростью 115200 бод и наблюдайте за происходящим в реальном времени.

Монитор последовательного порта Arduino IDE -- Node-RED ESP8266 MQTT

Это полезно для проверки того, что ESP8266 успешно установил соединение с вашим роутером и с брокером Mosquitto.

Создание потока Node-RED

Перед созданием потока на вашем Raspberry Pi должны быть установлены:

Импорт потока Node-RED

Чтобы импортировать предоставленный поток Node-RED, перейдите в репозиторий GitHub или нажмите на изображение ниже, чтобы увидеть исходный файл, и скопируйте предоставленный код.

Скачивание исходного файла потока Node-RED с GitHub

Далее, в окне Node-RED, в правом верхнем углу, выберите меню и перейдите в Import > Clipboard.

Импорт узлов в Node-RED

Затем вставьте предоставленный код и нажмите Import.

Импорт потока в Node-RED

Вот импортированный поток, который управляет ESP8266 и отображает опубликованные показания датчиков.

Поток Node-RED для мультисенсорного шилда ESP8266

Интерфейс Node-RED

После внесения всех необходимых изменений нажмите кнопку Deploy, чтобы сохранить все изменения.

Кнопка Deploy в Node-RED

Теперь ваше приложение Node-RED готово. Чтобы получить доступ к интерфейсу Node-RED и увидеть, как выглядит ваше приложение, откройте любой браузер в вашей локальной сети и введите:

http://IP_адрес_вашего_RPi:1880/ui

Ваше приложение должно выглядеть так, как показано на следующем изображении.

Интерфейс Node-RED для мультисенсорного шилда ESP8266

Когда движение обнаружено, в поле PIR Status выводится сообщение «MOTION DETECTED!»:

Интерфейс Node-RED -- обнаружено движение

Подведение итогов

На этом проект завершён. Мы надеемся, что вы нашли этот проект полезным и сможете интегрировать мультисенсорный шилд в свою собственную систему домашней автоматизации с помощью Node-RED.

Если вам понравился этот проект, вам также могут понравиться другие наши проекты:

Спасибо за чтение.