Arduino, ESP8266, MQTT, DHT22, Бутони и Волтметър управление на релета и мониторинг на сензори

Arduino, ESP8266, MQTT, DHT22, Бутони и Волтметър управление на релета и мониторинг на сензори

Въведение

Този проект демонстрира как да използвате ESP8266 с Arduino за създаване на система за управление на четири релета и мониторинг на сензори чрез MQTT протокол. Системата включва DHT22 сензор за температура и влажност, бутони за ръчно управление на релетата и волтметър за измерване на напрежение. Проектът е идеален за домашна автоматизация, IoT приложения и образователни цели. Този проект сме го използвали за да демонстрираме как за едио хардуерно изделие можем да напишем код за управлението му на различни с различни протоколи. Може да разгледате другите ни статии:

Хардуер

За реализацията на проекта са използвани следните компоненти:

Arduino, ESP8266, MQTT, DHT22, Бутони и Волтметър управление на релета и мониторинг на сензори Устройство
  1. ESP8266 – Микроконтролер с WiFi възможности, използван за управление на релетата и сензорите.
  2. Релета – Четири релета, управлявани чрез цифрови изходи на ESP8266.
  3. Бутони – Четири бутона за ръчно управление на релетата.
  4. DHT22 сензор – Сензор за температура и влажност.
  5. Волтметър – Използва се аналогов вход за измерване на напрежение чрез делител на напрежение.
  6. Делител на напрежение – Състоящ се от два резистора (R1 = 120kΩ, R2 = 15.5kΩ) за измерване на напрежение.

Използвани библиотеки

ESP8266WiFi – Библиотека за управление на WiFi връзката на ESP8266. Включена е в стандартната инсталация на Arduino IDE за ESP8266. Ако все още не сте добавили този процесор във вашето Arduino IDE може да прочетете как става това в статията ни: Добавяне на ESP8266 в Arduino IDE: Стъпка по стъпка

MQTT PubSubClient Arduino IDE Library Manager

PubSubClient – Библиотека за работа с MQTT протокол. Може да бъде намерена в GitHub, или да я свалите директно с Arduino IDE Library Manager както е показано на картинката отляво. В краен случай може да я свалите от тук.

Ако не знаете как да инсталирате и настройте свой собствен MQTT брокер, може да прочетете как става това в страниците ни:

DHT – Библиотека за работа с DHT сензорите. Може да бъде намерена в GitHub или отново да я свалите директно с Arduino IDE Library Manager. Също така може да я свалите от тук.

ESP8266 Arduino IDE Library Manager DHT Library

Код за управление на релета и мониторинг на сензори написан на Arduino IDE, и ESP8266 през MQTT

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

// Настройка на пиновете за релета
#define RELAY1_PIN D0  // GPIO16
#define RELAY2_PIN D6  // GPIO12
#define RELAY3_PIN D7  // GPIO13
#define RELAY4_PIN D8  // GPIO15

// Настройка на пиновете за бутони
#define BUTTON1_PIN D3  // GPIO0
#define BUTTON2_PIN D4  // GPIO2
#define BUTTON3_PIN D2  // GPIO4
#define BUTTON4_PIN D1  // GPIO5

// Аналогов вход
#define ANALOG_INPUT A0

// DHT22 сензор
#define DHTPIN D5  // GPIO14
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

// Настройки за WiFi и MQTT
const char* ssid = "XXXXXXXX"; // Заменете с вашето WiFi SSID
const char* password = "XXXXXXXX"; // Заместете с вашата WiFi парола
const char* mqtt_server = "192.168.1.80"; // Заместете с IP на вашия MQTT сървър
const int mqtt_port = 1883; // Заменете с вашия порт на MQTT сървъра
const char* mqtt_user = "XXXXXXXX"; // Заместете с username на вашия MQTT сървър
const char* mqtt_password = "XXXXXXXX"; // Заместете с вашата MQTT парола
const char* mqtt_client_id = "ESP8266_proto_1";

// MQTT топици
const char* mqtt_topic_command = "esp8266/relays";
const char* mqtt_topic_dht_temp = "esp8266/DHTtemp";
const char* mqtt_topic_dht_hum = "esp8266/DHThum";
const char* mqtt_topic_analog_in = "esp8266/AnalogIN";
const char* mqtt_topic_relay1_state = "esp8266/relay1/state";
const char* mqtt_topic_relay2_state = "esp8266/relay2/state";
const char* mqtt_topic_relay3_state = "esp8266/relay3/state";
const char* mqtt_topic_relay4_state = "esp8266/relay4/state";
const char* mqtt_topic_status = "esp8266/status";

// MQTT клиент
WiFiClient espClient;
PubSubClient client(espClient);

// Делител на напрежение
const float R1 = 120000.0;
const float R2 = 15500.0;

// Променливи за състоянието на релетата
bool relay1_state = false;
bool relay2_state = false;
bool relay3_state = false;
bool relay4_state = false;

// Функция за свързване към WiFi
void connectToWiFi() {
  Serial.println("Connecting to WiFi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected to WiFi");
}

// Функция за свързване към MQTT сървър
void connectToMQTT() {
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect(mqtt_client_id, mqtt_user, mqtt_password)) {
      Serial.println("Connected to MQTT server");
      client.subscribe(mqtt_topic_command);
      client.publish(mqtt_topic_status, "online", true);
    } else {
      Serial.print("Failed to connect to MQTT, retrying in 5 seconds...");
      delay(5000);
    }
  }
}

// Функция за обработка на MQTT съобщения
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }

  Serial.print("Message received on topic: ");
  Serial.print(topic);
  Serial.print(" - ");
  Serial.println(message);

  if (String(topic) == mqtt_topic_command) {
    if (message == "R1on") {
      digitalWrite(RELAY1_PIN, HIGH);
      relay1_state = true;
      publishRelayState(1);
    } else if (message == "R1off") {
      digitalWrite(RELAY1_PIN, LOW);
      relay1_state = false;
      publishRelayState(1);
    } else if (message == "R2on") {
      digitalWrite(RELAY2_PIN, HIGH);
      relay2_state = true;
      publishRelayState(2);
    } else if (message == "R2off") {
      digitalWrite(RELAY2_PIN, LOW);
      relay2_state = false;
      publishRelayState(2);
    } else if (message == "R3on") {
      digitalWrite(RELAY3_PIN, HIGH);
      relay3_state = true;
      publishRelayState(3);
    } else if (message == "R3off") {
      digitalWrite(RELAY3_PIN, LOW);
      relay3_state = false;
      publishRelayState(3);
    } else if (message == "R4on") {
      digitalWrite(RELAY4_PIN, HIGH);
      relay4_state = true;
      publishRelayState(4);
    } else if (message == "R4off") {
      digitalWrite(RELAY4_PIN, LOW);
      relay4_state = false;
      publishRelayState(4);
    }
  }
}

// Функция за публикуване на състоянието на релетата
void publishRelayState(int relay_number) {
  String topic;
  String state;

  switch (relay_number) {
    case 1:
      topic = mqtt_topic_relay1_state;
      state = relay1_state ? "ON" : "OFF";
      break;
    case 2:
      topic = mqtt_topic_relay2_state;
      state = relay2_state ? "ON" : "OFF";
      break;
    case 3:
      topic = mqtt_topic_relay3_state;
      state = relay3_state ? "ON" : "OFF";
      break;
    case 4:
      topic = mqtt_topic_relay4_state;
      state = relay4_state ? "ON" : "OFF";
      break;
  }

  client.publish(topic.c_str(), state.c_str(), true);
}

// Функция за четене на DHT сензора
void readDHT() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  if (!isnan(temperature) && !isnan(humidity)) {
    client.publish(mqtt_topic_dht_temp, String(temperature).c_str(), true);
    client.publish(mqtt_topic_dht_hum, String(humidity).c_str(), true);
  } else {
    Serial.println("Failed to read DHT sensor");
  }
}

// Функция за четене на аналоговия вход
void readAnalogInput() {
  int analog_value = analogRead(ANALOG_INPUT);
  float voltage_in = analog_value * (3.3 / 1024.0) * 10.0;
  float volt = (voltage_in * (R1 / (R1 + R2))) - 0.14;

  // Ако volt е по-малко от 0, задайте го на 0
  if (volt < 0) {
    volt = 0;
  }

  volt = round(volt * 100) / 100;  // Закръгляне до 2 знака след десетичната запетая

  client.publish(mqtt_topic_analog_in, String(volt).c_str(), true);
}

// Функция за обработка на бутоните
void handleButtons() {
  if (digitalRead(BUTTON1_PIN) == LOW) {
    relay1_state = !relay1_state;
    digitalWrite(RELAY1_PIN, relay1_state ? HIGH : LOW);
    publishRelayState(1);
    delay(200);  // Anti-bounce
  }
  if (digitalRead(BUTTON2_PIN) == LOW) {
    relay2_state = !relay2_state;
    digitalWrite(RELAY2_PIN, relay2_state ? HIGH : LOW);
    publishRelayState(2);
    delay(200);
  }
  if (digitalRead(BUTTON3_PIN) == LOW) {
    relay3_state = !relay3_state;
    digitalWrite(RELAY3_PIN, relay3_state ? HIGH : LOW);
    publishRelayState(3);
    delay(200);
  }
  if (digitalRead(BUTTON4_PIN) == LOW) {
    relay4_state = !relay4_state;
    digitalWrite(RELAY4_PIN, relay4_state ? HIGH : LOW);
    publishRelayState(4);
    delay(200);
  }
}

// Настройка
void setup() {
  Serial.begin(115200);

  // Инициализация на пиновете
  pinMode(RELAY1_PIN, OUTPUT);
  pinMode(RELAY2_PIN, OUTPUT);
  pinMode(RELAY3_PIN, OUTPUT);
  pinMode(RELAY4_PIN, OUTPUT);
  pinMode(BUTTON1_PIN, INPUT_PULLUP);
  pinMode(BUTTON2_PIN, INPUT_PULLUP);
  pinMode(BUTTON3_PIN, INPUT_PULLUP);
  pinMode(BUTTON4_PIN, INPUT_PULLUP);

  // Инициализация на DHT сензора
  dht.begin();

  // Свързване към WiFi
  connectToWiFi();

  // Настройка на MQTT клиента
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(mqttCallback);
}

// Главен цикъл
void loop() {
  if (!client.connected()) {
    connectToMQTT();
  }
  client.loop();

  // Четене и публикуване на данни от сензорите
  readDHT();
  readAnalogInput();

  // Обработка на бутоните
  handleButtons();

  delay(1000);  // Изчакване преди следващия цикъл
}

Пълно описание на кода

Инициализация на пинове и библиотеки

В началото на кода се инициализират пиновете за релетата, бутоните, аналоговия вход и DHT сензора. Също така се включват необходимите библиотеки.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

// Настройка на пиновете за релета
#define RELAY1_PIN D0  // GPIO16
#define RELAY2_PIN D6  // GPIO12
#define RELAY3_PIN D7  // GPIO13
#define RELAY4_PIN D8  // GPIO15

// Настройка на пиновете за бутони
#define BUTTON1_PIN D3  // GPIO0
#define BUTTON2_PIN D4  // GPIO2
#define BUTTON3_PIN D2  // GPIO4
#define BUTTON4_PIN D1  // GPIO5

// Аналогов вход
#define ANALOG_INPUT A0

// DHT22 сензор
#define DHTPIN D5  // GPIO14
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

Настройка на WiFi и MQTT

След инициализацията на пиновете, се задават настройките за WiFi и MQTT сървъра. Функциите connectToWiFi() и connectToMQTT() се използват за свързване към WiFi и MQTT сървъра.

// Настройки за WiFi и MQTT
const char* ssid = "XXXXXXXXX"; // Заменете с вашето WiFi SSID
const char* password = "XXXXXXXXX"; // Заместете с вашата WiFi парола
const char* mqtt_server = "192.168.1.80"; // Заместете с IP на вашия MQTT сървър
const int mqtt_port = 1883; // Заменете с вашия порт на MQTT сървъра
const char* mqtt_user = "XXXXXXXXX"; // Заместете с username на вашия MQTT сървър
const char* mqtt_password = "XXXXXXXXX"; // Заместете с вашата MQTT парола
const char* mqtt_client_id = "ESP8266_proto_1";

// MQTT топици
const char* mqtt_topic_command = "esp8266/relays";
const char* mqtt_topic_dht_temp = "esp8266/DHTtemp";
const char* mqtt_topic_dht_hum = "esp8266/DHThum";
const char* mqtt_topic_analog_in = "esp8266/AnalogIN";
const char* mqtt_topic_relay1_state = "esp8266/relay1/state";
const char* mqtt_topic_relay2_state = "esp8266/relay2/state";
const char* mqtt_topic_relay3_state = "esp8266/relay3/state";
const char* mqtt_topic_relay4_state = "esp8266/relay4/state";
const char* mqtt_topic_status = "esp8266/status";

// MQTT клиент
WiFiClient espClient;
PubSubClient client(espClient);

Функции за управление на релетата

Функцията mqttCallback() се използва за обработка на MQTT съобщенията. Тя проверява командите и управлява релетата според получените команди.

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }

  if (String(topic) == mqtt_topic_command) {
    if (message == "R1on") {
      digitalWrite(RELAY1_PIN, HIGH);
      relay1_state = true;
      publishRelayState(1);
    } else if (message == "R1off") {
      digitalWrite(RELAY1_PIN, LOW);
      relay1_state = false;
      publishRelayState(1);
    }
    // Аналогично за R2, R3, R4
  }
}

Функции за четене на сензорите

Функциите readDHT() и readAnalogInput() се използват за четене на данните от DHT сензора и аналоговия вход, и публикуването им в MQTT топици.

void readDHT() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  if (!isnan(temperature) && !isnan(humidity)) {
    client.publish(mqtt_topic_dht_temp, String(temperature).c_str(), true);
    client.publish(mqtt_topic_dht_hum, String(humidity).c_str(), true);
  } else {
    Serial.println("Failed to read DHT sensor");
  }
}

void readAnalogInput() {
  int analog_value = analogRead(ANALOG_INPUT);
  float voltage_in = analog_value * (3.3 / 1024.0) * 10.0;
  float volt = (voltage_in * (R1 / (R1 + R2))) - 0.14;

  if (volt < 0) {
    volt = 0;
  }

  volt = round(volt * 100) / 100;  // Закръгляне до 2 знака след десетичната запетая

  client.publish(mqtt_topic_analog_in, String(volt).c_str(), true);
}

Обработка на бутоните

Функцията handleButtons() се използва за ръчно управление на релетата чрез бутоните.

void handleButtons() {
  if (digitalRead(BUTTON1_PIN) == LOW) {
    relay1_state = !relay1_state;
    digitalWrite(RELAY1_PIN, relay1_state ? HIGH : LOW);
    publishRelayState(1);
    delay(200);  // Anti-bounce
  }
  // Аналогично за BUTTON2_PIN, BUTTON3_PIN, BUTTON4_PIN
}

Топици и настройка на MQTT панел

MQTT топиците са основен елемент за комуникация между ESP8266 и MQTT сървъра. Те действат като канали, през които устройствата обменят информация. В този проект са дефинирани няколко ключови топика, които позволяват управление на релетата, мониторинг на сензорите и проследяване на състоянието на системата.

  • esp8266/relays: Този топик се използва за изпращане на команди към релетата. Например, съобщения като “R1on” или “R1off” включват или изключват първото реле.
  • esp8266/DHTtemp: Тук се публикуват данните за температурата, получени от DHT22 сензора.
  • esp8266/DHThum: Този топик съдържа информация за влажността, измерена от DHT22.
  • esp8266/AnalogIN: Чрез този топик се изпращат данните от волтметъра, който измерва напрежението на аналоговия вход.
  • esp8266/relay1/stateesp8266/relay2/stateesp8266/relay3/stateesp8266/relay4/state: Тези топици съдържат текущото състояние на всяко реле (ON или OFF).
  • esp8266/status: Този топик се използва за индикация на статуса на устройството, като “online” или “offline“.

Настройката на MQTT панела включва конфигуриране на сървъра, клиентски идентификатор и потребителски данни. Всички топици се абонират и публикуват автоматично, когато устройството се свърже към MQTT сървъра. Това позволява лесно интегриране на системата в съществуващи IoT платформи или мобилни приложения за управление.

Виде презентация на проекта

Arduino, ESP8266, MQTT, DHT22, Бутони и Волтметър Видео на проекта

Заключение

Този проект демонстрира как може да се използва Arduino и ESP8266 за управление на релета и мониторинг на сензори чрез MQTT протокол. Системата включва DHT22 сензор за температура и влажност, бутони за ръчно управление и волтметър за измерване на напрежение. С правилната настройка на MQTT сървъра и клиенти, системата може да бъде интегрирана в по-големи проекти за управление на умни домове и индустриални системи.

Translate »