Въведение
ESP8266-01 е един от най-популярните Wi-Fi микроконтролери за „умни“ проекти. С негова помощ можем лесно да изградим домашна автоматизация, която да се управлява както локално през уеб интерфейс, така и дистанционно чрез MQTT сървър.
В тази статия ще разгледаме проект за двурелеен контролер с ESP8266-01, който поддържа:
- управление през MQTT брокер (например Mosquitto). За да разберете как да направите собствен MQTT сървър може да прочетете статията ни: Инсталиране на Mosquitto MQTT Broker на Raspberry Pi 4
- Вграден уеб интерфейс за директен контрол. За целта използваме платформата от пректа ни: ESP8266-01 двуканален WEB релеен борд
- fallback Access Point (AP) режим при липса на Wi-Fi връзка,
- възможност за OTA обновяване (Over-The-Air).
Проектът е подходящ за домашна автоматизация – например за управление на осветление, вентилатори или други уреди до 220V чрез реле.
Схематично решение на борда ESP8266-01 MQTT
Проектът използва ESP8266-01 (NodeMCU или Wemos D1 mini) и два релета. Релетата са свързани към GPIO0 и GPIO2 на микроконтролера. При подаване на команда, пиновете се активират логически HIGH и релеят включва товара.
Основна схема:
- GPIO0 → Relay 1
- GPIO2 → Relay 2
- VCC (5V или 3.3V според модула) → Реле борд
- GND → обща маса
⚠️ Внимание: При работа с 220V мрежа използвайте подходящи модули и изолация за безопасност.
Код на проекта ESP8266-01 и MQTT за управление на две релета
По-долу е целият код, който трябва да качите на ESP8266 чрез Arduino IDE.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#include <DNSServer.h>
// ================= Променливи за всеки борд ===============
const char* WiFi_ssid = "XXXXXXXX"; // Името на WiFi мрежата
const char* WiFi_password = "XXXXXXXX"; // Паролата на WiFi мрежата
const char* WiFi_ap_ssid = "ESP8266_Two_Relay_AP_3"; //AP WiFi-SSID
const char* WiFi_ap_pass = "12345678"; //AP WiFi-PASS
const char* MQTT_clientID = "esp8266_Two_Relay_Board_3"; // MQTT MQTT/ID
const char* MQTT_topicRelay1 = "board_3/relay_1"; // MQTT Topic Board/Relay
const char* MQTT_topicRelay2 = "board_3/relay_2"; // MQTT Topic Board/Relay
const char* OTA_setHostname("ESP8266_TwoRelay_board-3 "); // OTA name
const char* OTA_setPassword("XXXXXXXX"); // OTA password
// ======================= WiFi настройки =======================
const char* ssid = WiFi_ssid;
const char* password = WiFi_password;
// AP fallback настройки
const char* ap_ssid = WiFi_ap_ssid;
const char* ap_pass = WiFi_ap_pass;
// ======================= MQTT настройки =======================
const char* mqtt_server = "ххх.ххх.ххх.ххх"; // IP на MQTT сървъра
const char* mqtt_user = "ххххххххх"; // user за оторизация на MQTT
const char* mqtt_pass = "ххххххххх"; // pass за оторизация на MQTT
const char* clientID = MQTT_clientID;
const char* topicRelay1 = MQTT_topicRelay1;
const char* topicRelay2 = MQTT_topicRelay2;
// ======================= Пинове =======================
#define RELAY1 0 // GPIO0
#define RELAY2 2 // GPIO2
// Логика на релетата (активно HIGH)
#define RELAY_ON HIGH
#define RELAY_OFF LOW
// ======================= Обекти =======================
WiFiClient espClient;
PubSubClient client(espClient);
ESP8266WebServer server(80);
DNSServer dnsServer;
// ======================= Променливи =======================
bool relay1State = false;
bool relay2State = false;
bool wifiConnected = false;
const byte DNS_PORT = 53;
// ======================= MQTT Callback =======================
void callback(char* topic, byte* payload, unsigned int length) {
String msg;
for (unsigned int i = 0; i < length; i++) {
msg += (char)payload[i];
}
msg.trim();
if (String(topic) == topicRelay1) {
if (msg == "ON") {
digitalWrite(RELAY1, RELAY_ON);
relay1State = true;
} else if (msg == "OFF") {
digitalWrite(RELAY1, RELAY_OFF);
relay1State = false;
}
}
if (String(topic) == topicRelay2) {
if (msg == "ON") {
digitalWrite(RELAY2, RELAY_ON);
relay2State = true;
} else if (msg == "OFF") {
digitalWrite(RELAY2, RELAY_OFF);
relay2State = false;
}
}
}
// ======================= WiFi свързване =======================
void setup_wifi() {
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
unsigned long startAttemptTime = millis();
// чакаме до 10 секунди
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
delay(500);
}
if (WiFi.status() == WL_CONNECTED) {
wifiConnected = true;
} else {
// fallback AP + captive portal
WiFi.softAP(ap_ssid, ap_pass);
dnsServer.start(DNS_PORT, "*", WiFi.softAPIP());
wifiConnected = false;
}
}
// ======================= MQTT свързване =======================
void reconnect() {
while (wifiConnected && !client.connected()) {
if (client.connect(clientID, mqtt_user, mqtt_pass)) {
client.subscribe(topicRelay1);
client.subscribe(topicRelay2);
} else {
delay(5000);
}
}
}
// ======================= Web интерфейс =======================
void handleRoot() {
String html = "<!DOCTYPE html><html><head><meta charset='utf-8'>";
html += "<title>ESP8266 Two Relay</title>";
html += "<style>body{font-family:Arial;text-align:center;margin-top:50px;}";
html += "button{padding:15px 30px;margin:10px;font-size:18px;border:none;";
html += "border-radius:8px;cursor:pointer;}";
html += ".on{background:#4CAF50;color:white;}";
html += ".off{background:#f44336;color:white;}</style></head><body>";
html += "<h1>ESP8266 Relay Control</h1>";
html += "<p>Relay 1: ";
html += relay1State ? "ON" : "OFF";
html += "</p>";
html += "<a href='/relay1/on'><button class='on'>Relay 1 ON</button></a>";
html += "<a href='/relay1/off'><button class='off'>Relay 1 OFF</button></a><br>";
html += "<p>Relay 2: ";
html += relay2State ? "ON" : "OFF";
html += "</p>";
html += "<a href='/relay2/on'><button class='on'>Relay 2 ON</button></a>";
html += "<a href='/relay2/off'><button class='off'>Relay 2 OFF</button></a>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void handleRelay1On() { digitalWrite(RELAY1, RELAY_ON); relay1State = true; if (wifiConnected) client.publish(topicRelay1, "ON"); handleRoot(); }
void handleRelay1Off() { digitalWrite(RELAY1, RELAY_OFF); relay1State = false; if (wifiConnected) client.publish(topicRelay1, "OFF"); handleRoot(); }
void handleRelay2On() { digitalWrite(RELAY2, RELAY_ON); relay2State = true; if (wifiConnected) client.publish(topicRelay2, "ON"); handleRoot(); }
void handleRelay2Off() { digitalWrite(RELAY2, RELAY_OFF); relay2State = false; if (wifiConnected) client.publish(topicRelay2, "OFF"); handleRoot(); }
// ======================= Setup =======================
void setup() {
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
// При старт изключваме релетата
digitalWrite(RELAY1, RELAY_OFF);
digitalWrite(RELAY2, RELAY_OFF);
relay1State = false;
relay2State = false;
setup_wifi();
if (wifiConnected) {
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
server.on("/", handleRoot);
server.on("/relay1/on", handleRelay1On);
server.on("/relay1/off", handleRelay1Off);
server.on("/relay2/on", handleRelay2On);
server.on("/relay2/off", handleRelay2Off);
server.begin();
// OTA настройки (работи само при WiFi STA връзка)
if (wifiConnected) {
ArduinoOTA.setHostname(OTA_setHostname);
ArduinoOTA.setPassword(OTA_setPassword);
ArduinoOTA.begin();
}
}
// ======================= Loop =======================
void loop() {
if (wifiConnected) {
if (!client.connected()) {
reconnect();
}
client.loop();
ArduinoOTA.handle();
} else {
dnsServer.processNextRequest(); // captive portal DNS
}
server.handleClient();
}
Обяснение на кода
1. Импорт на библиотеки
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include <ArduinoOTA.h> #include <DNSServer.h>
- ESP8266WiFi.h – управление на Wi-Fi връзката.
- PubSubClient.h – MQTT клиент.
- ESP8266WebServer.h – мини HTTP сървър за уеб интерфейса.
- ESP8266mDNS.h – mDNS поддръжка (локално име на устройството).
- ArduinoOTA.h – OTA обновяване.
- DNSServer.h – DNS за captive portal (при fallback AP).
2. Настройки за Wi-Fi и MQTT
const char* WiFi_ssid = "хххххххх"; const char* WiFi_password = "хххххххх"; const char* mqtt_server = "ххх.ххх.ххх.ххх"; const char* mqtt_user = "хххххххх"; const char* mqtt_pass = "хххххххх";
- Устройството първо се опитва да се свърже към зададената Wi-Fi мрежа.
- Ако не успее, преминава в Access Point режим с SSID
ESP8266_Two_Relay_AP_3. - MQTT клиентът използва конкретен сървър, потребител и парола.
3. Пинове и логика
#define RELAY1 0 // GPIO0 #define RELAY2 2 // GPIO2 #define RELAY_ON HIGH #define RELAY_OFF LOW
- Определят се пиновете за релетата и логиката им (тук – активно HIGH).
4. MQTT Callback
void callback(char* topic, byte* payload, unsigned int length) {
// Проверява входящите съобщения
}
- При получаване на съобщение по topic (
board_3/relay_1илиboard_3/relay_2), се включва или изключва съответното реле. - Поддържаните команди са: ON и OFF.
5. Wi-Fi свързване
void setup_wifi() {
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
...
}
- Опит за свързване към домашната мрежа.
- Ако не успее до 10 секунди → активира се AP режим.
6. MQTT свързване
void reconnect() {
while (wifiConnected && !client.connected()) {
if (client.connect(clientID, mqtt_user, mqtt_pass)) {
client.subscribe(topicRelay1);
client.subscribe(topicRelay2);
}
}
}
- Автоматично възстановяване на връзката към брокера.
- Абониране за топиците на релетата.
7. Уеб интерфейс
void handleRoot() {
String html = "..."; // HTML с бутони за релета
server.send(200, "text/html", html);
}
- Устройството предоставя уеб страница с бутони за включване/изключване на двете релета.
- При промяна, състоянието се отразява и в MQTT топика.
8. OTA обновяване
ArduinoOTA.setHostname(OTA_setHostname); ArduinoOTA.setPassword(OTA_setPassword); ArduinoOTA.begin();
- Позволява ъпдейт на фърмуера през Wi-Fi, без нужда от кабелно качване.
MQTT топици и команди
Устройството използва два топика:
board_3/relay_1board_3/relay_2
Команди:
ON→ включва съответното реле.OFF→ изключва съответното реле.
Пример:
mosquitto_pub -h ххх.ххх.ххх.ххх -u хххххххх-P хххххххх -t board_3/relay_1 -m "ON"
Настройка на MQTT панел
Можете да използвате приложение като MQTT Dash (Android) или Node-RED Dashboard, за да управлявате релетата.
- Добавете два бутона – по един за всеки топик.
- Задайте стойности
ONиOFF. - Така получавате удобен мобилен интерфейс за контрол.
Обобщение
С помощта на ESP8266 и два релета създадохме универсален модул за домашна автоматизация. Той може да се управлява през:
- уеб браузър (вграден интерфейс),
- MQTT брокер (удобно за интеграция в Home Assistant, Node-RED и др.),
- OTA обновяване за лесна поддръжка.
Клип на аналогичен проект може да видите тук.
Заключение
Проектът показва как ESP8266 може да обедини няколко ключови технологии – Wi-Fi, MQTT, уеб интерфейс и OTA – в един практичен контролер. С малки промени кодът може да се адаптира за повече релета или различни приложения.
