![Проект с ESP8266 D1 Mini Контрол на четири релета чрез бутони и WEB интерфейс и изчитане на сензори](http://ardudevelop.eu/wp-content/uploads/2024/09/Проект-с-ESP8266-D1-Mini-Контрол-на-четири-релета-чрез-бутони-и-WEB-интерфейс-и-изчитане-на-сензори.png)
В тази статия ще комбинираме всички научени умения от предишните ни проекти и ще ги приложим в създаването на пълноценен проект с ESP8266 D1 Mini. Ще изградим система за контрол на релета, управление чрез физически бутони и уеб интерфейс, както и четене на данни от сензори като DHT11 за температура и влажност. Също така а ще четем стойности от аналогов вход. Този проект ще послужи като основа за по-сложни IoT решения, които ще предложим в бъдещи статии.
Предишни статий които ще използваме за основа на този проект:
- Управление на 4 релета през WEB с ESP8266
- Изчитане на DHT11 и DHT22 с ESP8266
- Изчитане на бутон с ESP8266: Два примера с Arduino IDE
- Управление на LED с потенциометър и ESP8266 чрез PWM
Основната концепция на проекта
Проектът се състои от следните основни компоненти:
- Контрол на релета – ще управляваме четири релета, които могат да включват и изключват електрически устройства.
- Физически бутони – четири бутона ще бъдат използвани за управление на релетата. Те ще работят с дебаунс логика, за да предотвратим неправилни отчети при бързо натискане.
- Уеб интерфейс – ще създадем уеб сървър, чрез който ще можем да контролираме релетата дистанционно, да четем стойностите на бутоните и аналоговия вход, както и данни за температурата и влажността от сензора DHT11.
- DHT11 сензор – ще четем данни за температурата и влажността от този сензор, което ще ни даде възможност да следим околната среда. Може да свалите библиотеката от тук.
DHT11 диаграма на пиновете (pinout)
![DHT11-пин-диаграма-pinout](http://ardudevelop.eu/wp-content/uploads/2024/09/DHT11-пин-диаграма-pinout-1.png)
DHT11 конфигурация на пиновете
Характеристики на ESP8266 D1 Mini
ESP8266 D1 Mini е малка и мощна платформа, подходяща за IoT проекти. Тя разполага с вградени Wi-Fi възможности, които ще използваме, за да създадем уеб сървър. С помощта на библиотеката ESP8266WebServer, ще създадем интерактивен уеб интерфейс за управление на системата.
Прочетете повече за тази платформа в ревюто ни за нея: ESP8266 D1 Mini – Малък, но Мощен Wi-Fi Микроконтролер
Код на проекта за контрол на четири релета чрез бутони и WEB интерфейс
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
// Пинове за релетата
#define RELAY_1 D0
#define RELAY_2 D6
#define RELAY_3 D7
#define RELAY_4 D8
// Пинове за бутоните
#define BUTTON_1 D4
#define BUTTON_2 D3
#define BUTTON_3 D2
#define BUTTON_4 D1
// Аналогов вход
#define ANALOG_IN A0
// Пин за DHT22
#define DHTPIN D5
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// Wi-Fi настройки
const char* ssid = "xxxxxxxx"; // заместете с името на вашата WiFi мрежа
const char* password = "xxxxxxxx"; // заместете с вашата WiFi парола
// Създаваме уеб сървър на порт 80
ESP8266WebServer server(80);
// Променливи за състоянията на релетата
bool relay1State = false;
bool relay2State = false;
bool relay3State = false;
bool relay4State = false;
// Променливи за състоянията на бутоните и броячи
int button1Counter = 0;
int button2Counter = 0;
int button3Counter = 0;
int button4Counter = 0;
// Променливи за време и дебаунс
unsigned long lastButtonPress1 = 0;
unsigned long lastButtonPress2 = 0;
unsigned long lastButtonPress3 = 0;
unsigned long lastButtonPress4 = 0;
const unsigned long debounceDelay = 250; // 250 ms debounce delay
void setup() {
Serial.begin(115200);
// Настройка на релетата като изходи и изключването им
pinMode(RELAY_1, OUTPUT);
pinMode(RELAY_2, OUTPUT);
pinMode(RELAY_3, OUTPUT);
pinMode(RELAY_4, OUTPUT);
// Настройваме релетата да са изключени по подразбиране при рестарт (LOW = изключено)
digitalWrite(RELAY_1, LOW); // По-ниско състояние = изключено
digitalWrite(RELAY_2, LOW);
digitalWrite(RELAY_3, LOW);
digitalWrite(RELAY_4, LOW);
// Настройка на бутоните като входове с активирани вътрешни pull-up резистори
pinMode(BUTTON_1, INPUT_PULLUP);
pinMode(BUTTON_2, INPUT_PULLUP);
pinMode(BUTTON_3, INPUT_PULLUP);
pinMode(BUTTON_4, INPUT_PULLUP);
// Инициализация на DHT
dht.begin();
// Свързване към Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
// Уеб интерфейс за управление
server.on("/", handleRoot);
server.on("/toggleRelay1", toggleRelay1);
server.on("/toggleRelay2", toggleRelay2);
server.on("/toggleRelay3", toggleRelay3);
server.on("/toggleRelay4", toggleRelay4);
// Пътища за външно четене на състояния
server.on("/readButtons", readButtons);
server.on("/readAnalog", readAnalog);
server.on("/readRelays", readRelays);
server.on("/readDHT", readDHT); // Четене на данни от DHT
server.begin();
}
void loop() {
// Проверка за натискане на бутоните с дебаунс
checkButton(BUTTON_1, button1Counter, lastButtonPress1, RELAY_1, relay1State);
checkButton(BUTTON_2, button2Counter, lastButtonPress2, RELAY_2, relay2State);
checkButton(BUTTON_3, button3Counter, lastButtonPress3, RELAY_3, relay3State);
checkButton(BUTTON_4, button4Counter, lastButtonPress4, RELAY_4, relay4State);
// Обработка на заявки от уеб сървъра
server.handleClient();
}
// Проверка на бутон с дебаунс логика
void checkButton(int buttonPin, int &counter, unsigned long &lastPress, int relayPin, bool &relayState) {
if (digitalRead(buttonPin) == LOW) {
if (millis() - lastPress > debounceDelay) {
counter++;
if (counter == 2) counter = 0; // Нулиране на брояча след две натискания
lastPress = millis();
relayState = (counter % 2 == 1); // Променяме състоянието на релето според брояча (вкл/изкл)
digitalWrite(relayPin, relayState ? HIGH : LOW); // LOW = изключено, HIGH = включено
}
}
}
// Главна страница с HTML интерфейс за управление на релетата и показване на състоянието на бутоните и аналоговия вход
void handleRoot() {
String html = "<!DOCTYPE html><html><head>";
html += "<style>";
html += "body { font-family: Arial; text-align: center; background-color: #f4f4f4; padding: 20px; }";
html += "table { margin: auto; border-collapse: collapse; width: 80%; }";
html += "table, th, td { border: 1px solid #ccc; padding: 10px; }";
html += "button { padding: 10px 20px; font-size: 16px; border: none; background-color: #007bff; color: white; border-radius: 5px; }";
html += "button:hover { background-color: #0056b3; }";
html += "</style>";
html += "</head><body>";
html += "<h1>ESP8266 Relay & WEB & Button Control + DHT & analogIN</h1>";
// Създаване на таблица с релета, бутони и сензори
html += "<table>";
html += "<tr><th>Component</th><th>Status</th><th>Action</th></tr>";
// Показване на състоянието на релетата
html += "<tr><td>Relay 1</td><td>" + String(relay1State ? "ON" : "OFF") + "</td>";
html += "<td><button id='relay1Btn' onclick=\"location.href='/toggleRelay1'\">Toggle</button></td></tr>";
html += "<tr><td>Relay 2</td><td>" + String(relay2State ? "ON" : "OFF") + "</td>";
html += "<td><button id='relay2Btn' onclick=\"location.href='/toggleRelay2'\">Toggle</button></td></tr>";
html += "<tr><td>Relay 3</td><td>" + String(relay3State ? "ON" : "OFF") + "</td>";
html += "<td><button id='relay3Btn' onclick=\"location.href='/toggleRelay3'\">Toggle</button></td></tr>";
html += "<tr><td>Relay 4</td><td>" + String(relay4State ? "ON" : "OFF") + "</td>";
html += "<td><button id='relay4Btn' onclick=\"location.href='/toggleRelay4'\">Toggle</button></td></tr>";
// Показване на броячите на бутоните
html += "<tr><td>Button 1</td><td>" + String(button1Counter) + "</td><td></td></tr>";
html += "<tr><td>Button 2</td><td>" + String(button2Counter) + "</td><td></td></tr>";
html += "<tr><td>Button 3</td><td>" + String(button3Counter) + "</td><td></td></tr>";
html += "<tr><td>Button 4</td><td>" + String(button4Counter) + "</td><td></td></tr>";
// Четене на аналогов вход
int analogValue = analogRead(ANALOG_IN);
html += "<tr><td>Analog Value</td><td>" + String(analogValue) + "</td><td></td></tr>";
// Показване на температурата и влажността от DHT
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
html += "<tr><td>Temperature</td><td>" + String(temperature) + " ℃</td><td></td></tr>";
html += "<tr><td>Humidity</td><td>" + String(humidity) + " %</td><td></td></tr>";
html += "</table>";
html += "</body></html>";
server.send(200, "text/html", html);
}
// Функции за управление на релетата от уеб интерфейса
void toggleRelay1() {
relay1State = !relay1State;
button1Counter = relay1State ? 1 : 0; // Актуализиране на брояча
digitalWrite(RELAY_1, relay1State ? HIGH : LOW);
handleRoot();
}
void toggleRelay2() {
relay2State = !relay2State;
button2Counter = relay2State ? 1 : 0;
digitalWrite(RELAY_2, relay2State ? HIGH : LOW);
handleRoot();
}
void toggleRelay3() {
relay3State = !relay3State;
button3Counter = relay3State ? 1 : 0;
digitalWrite(RELAY_3, relay3State ? HIGH : LOW);
handleRoot();
}
void toggleRelay4() {
relay4State = !relay4State;
button4Counter = relay4State ? 1 : 0;
digitalWrite(RELAY_4, relay4State ? HIGH : LOW);
handleRoot();
}
// Четене на състоянието на бутоните
void readButtons() {
String message = "";
message += "Button 1 Counter: " + String(button1Counter) + "\n";
message += "Button 2 Counter: " + String(button2Counter) + "\n";
message += "Button 3 Counter: " + String(button3Counter) + "\n";
message += "Button 4 Counter: " + String(button4Counter) + "\n";
server.send(200, "text/plain", message);
}
// Четене на аналоговия вход
void readAnalog() {
int analogValue = analogRead(ANALOG_IN);
server.send(200, "text/plain", String(analogValue));
}
// Четене на състоянието на релетата
void readRelays() {
String message = "";
message += "Relay 1: " + String(relay1State ? "ON" : "OFF") + "\n";
message += "Relay 2: " + String(relay2State ? "ON" : "OFF") + "\n";
message += "Relay 3: " + String(relay3State ? "ON" : "OFF") + "\n";
message += "Relay 4: " + String(relay4State ? "ON" : "OFF") + "\n";
server.send(200, "text/plain", message);
}
// Четене на температурата и влажността от DHT
void readDHT() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
String message = "Temperature: " + String(temperature) + " ℃\n";
message += "Humidity: " + String(humidity) + " %\n";
server.send(200, "text/plain", message);
}
WEB визуализация на кода:
![Проект с ESP8266 D1 Mini Контрол на четири релета чрез бутони и WEB интерфейс и изчитане на сензори Визуализация](http://ardudevelop.eu/wp-content/uploads/2024/09/Проект-с-ESP8266-D1-Mini-Контрол-на-четири-релета-чрез-бутони-и-WEB-интерфейс-и-изчитане-на-сензори-Визуализация-1024x518.png)
Обяснение на кода
Използвани и библиотеки
Първо включваме необходимите библиотеки:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
- ESP8266WiFi.h – Тази библиотека ни дава възможност да свързваме ESP8266 към Wi-Fi мрежа.
- ESP8266WebServer.h – Позволява ни да създадем уеб сървър и да обработваме HTTP заявки.
- DHT.h – Използваме тази библиотека за работа с DHT11 сензора за температура и влажност. Може да свалите тази библиотека от тук.
Пинове и хардуерни настройки
Дефинираме пиновете, към които са свързани релетата, бутоните и сензорите:
#define RELAY_1 D0
#define RELAY_2 D6
#define RELAY_3 D7
#define RELAY_4 D8
#define BUTTON_1 D4
#define BUTTON_2 D3
#define BUTTON_3 D2
#define BUTTON_4 D1
#define ANALOG_IN A0
#define DHTPIN D5
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
- Релета: Те се свързват към пиновете D0, D6, D7 и D8 и ще управляват включването и изключването на устройства.
- Бутони: Четирите бутона са свързани към пиновете D4, D3, D2 и D1 и ще контролират съответните релета.
- Аналогов вход: Аналоговият вход A0 ще чете стойности от аналогов датчик.
- DHT11 сензор: Свързан към D5, ще чете температура и влажност.
Wi-Fi свързване
В следващия блок код свързваме ESP8266 към Wi-Fi мрежата:
const char* ssid = "xxxxxxxx"; // заместете с името на вашата WiFi мрежа
const char* password = "xxxxxxxx"; // заместете с вашата WiFi парола
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
- WiFi.begin() – Започва връзката към мрежата, използвайки SSID и паролата.
- WL_CONNECTED – Докато устройството не се свърже с Wi-Fi мрежата, то продължава да се опитва.
Уеб сървър и HTTP пътища
Създаваме уеб сървър на порт 80 и дефинираме HTTP пътища за различни функционалности:
ESP8266WebServer server(80);
server.on("/", handleRoot);
server.on("/toggleRelay1", toggleRelay1);
server.on("/toggleRelay2", toggleRelay2);
server.on("/toggleRelay3", toggleRelay3);
server.on("/toggleRelay4", toggleRelay4);
server.on("/readButtons", readButtons);
server.on("/readAnalog", readAnalog);
server.on("/readRelays", readRelays);
server.on("/readDHT", readDHT);
server.begin();
- handleRoot() – Главната страница, която показва текущото състояние на релетата, бутоните и сензорите.
- toggleRelay1() до toggleRelay4() – Пътища за включване и изключване на съответните релета.
- readButtons(), readAnalog(), readRelays(), readDHT() – Пътища за четене на състоянията на бутоните, аналоговия вход, релетата и DHT11 сензора.
Физическо управление с бутони
Логиката за работа с бутоните включва дебаунс и поддържа броячи за натискания:
void checkButton(int buttonPin, int &counter, unsigned long &lastPress, int relayPin, bool &relayState) {
if (digitalRead(buttonPin) == LOW) {
if (millis() - lastPress > debounceDelay) {
counter++;
if (counter == 2) counter = 0;
lastPress = millis();
relayState = (counter % 2 == 1);
digitalWrite(relayPin, relayState ? HIGH : LOW);
}
}
}
- Debounce логика: За да се избегнат многократни отчети при еднократно натискане, използваме времева проверка (debouncing).
- Контрол на релетата: С всяко натискане на бутона броячът се увеличава и според стойността му релето се включва или изключва.
Четене на данни от DHT11
Четенето на данни от DHT11 сензора се извършва чрез библиотеката DHT.h:
void readDHT() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
String message = "Temperature: " + String(temperature) + " ℃\n";
message += "Humidity: " + String(humidity) + " %\n";
server.send(200, "text/plain", message);
}
- readTemperature() и readHumidity() – Извикваме тези функции, за да получим стойностите за температура и влажност.
Главната страница на уеб интерфейса
HTML страницата, показвана при посещение на уеб сървъра, дава информация за състоянието на всички компоненти:
void handleRoot() {
String html = "<html><head><title>ESP8266 Control</title></head><body>";
html += "<h1>ESP8266 Relay & Button Control</h1>";
html += "<p>Relay 1: " + String(relay1State ? "ON" : "OFF") + "</p>";
html += "<p>Button 1 Counter: " + String(button1Counter) + "</p>";
html += "<p>Temperature: " + String(dht.readTemperature()) + " ℃</p>";
html += "<p>Humidity: " + String(dht.readHumidity()) + " %</p>";
html += "</body></html>";
server.send(200, "text/html", html);
}
Заключение
Този проект комбинира няколко различни технологии и принципи, за да създаде интегрирана IoT система. В бъдещите ни статии ще предложим начини за разширяване на този проект, добавяйки нови функции и сензори.