#include <WiFi.h> // Бібліотека для роботи з Wi-Fi.
#include <PubSubClient.h> // Бібліотека для роботи з протоколом MQTT (публікація та підписка).
#define LIGHT_PIN 16 // Пін для керування світлодіодом.
#define PIR_PIN 19 // Пін для датчика руху (PIR).
#define ECHO_PIN 17 // Пін для приймача ультразвукового датчика.
#define TRIG_PIN 18 // Пін для передавача ультразвукового датчика.
#define WIFI_SSID "Wokwi-GUEST" // Назва мережі Wi-Fi.
#define WIFI_PW "" // Пароль до Wi-Fi (порожній у цьому прикладі).
#define MQTT_BROKER "broker.mqtt-dashboard.com" // Адреса MQTT брокера.
#define MQTT_PORT 1883 // Порт MQTT брокера.
int val = 0; // Змінна для збереження відстані, виміряної ультразвуковим датчиком.
bool pir = false; // Флаг для стану датчика руху.
bool LED = false; // Стан світлодіода (ввімкнено/вимкнено).
unsigned long lastTime1 = 0; // Час останньої взаємодії ультразвукового датчика.
unsigned long lastTime2 = 0; // Час останнього виявлення руху PIR-датчиком.
int on_Off = 0; // Стан ввімкнення/вимкнення через MQTT.
int time_ = 10000; // Таймер у мілісекундах для автоматичного вимкнення світлодіода.
WiFiClient espClient; // Об'єкт для роботи з Wi-Fi клієнтом.
PubSubClient client(espClient); // Об'єкт для роботи з MQTT клієнтом.
void setup() {
Serial.begin(9600); // Ініціалізація серійного зв'язку на швидкості 9600 біт/с.
pinMode(LIGHT_PIN, OUTPUT); // Налаштування піна для світлодіода як вихідного.
pinMode(PIR_PIN, INPUT); // Налаштування піна для датчика руху як вхідного.
pinMode(TRIG_PIN, OUTPUT); // Налаштування TRIG піна ультразвукового датчика як вихідного.
pinMode(ECHO_PIN, INPUT); // Налаштування ECHO піна ультразвукового датчика як вхідного.
WiFi.begin(WIFI_SSID, WIFI_PW); // Початок підключення до Wi-Fi.
while (WiFi.status() != WL_CONNECTED) { // Чекати, поки пристрій не підключиться до Wi-Fi.
delay(250); // Затримка для перевірки підключення.
Serial.print("."); // Виведення прогресу підключення.
}
Serial.println("\nConnected to hotspot:"); // Підтвердження підключення.
Serial.println(WIFI_SSID); // Виведення імені Wi-Fi.
Serial.print("IP address is: ");
Serial.println(WiFi.localIP()); // Виведення IP-адреси пристрою.
Serial.println("###");
client.setServer(MQTT_BROKER, MQTT_PORT); // Налаштування сервера MQTT брокера.
client.setCallback(callback); // Вказання функції зворотного виклику для обробки повідомлень.
while (!client.connected()) { // Чекати підключення до MQTT брокера.
Serial.println("Connecting to MQTT...");
if (client.connect("espGood", "Qwerty12", "Qwerty12")) {
Serial.println("Connected to broker"); // Успішне підключення.
client.subscribe("On_Off"); // Підписка на топік для керування вмиканням/вимиканням.
client.subscribe("Time"); // Підписка на топік для зміни часу автоматичного вимкнення.
} else {
Serial.print("Failed with state ");
Serial.println(client.state()); // Виведення помилки підключення.
delay(2000); // Затримка перед повторною спробою.
}
}
}
void loop() {
val = readDistanceCm(); // Зчитування відстані з ультразвукового датчика.
if ((val < 10 && (millis() - lastTime1) > 2000) || (on_Off == 1)) {
// Якщо відстань менше 10 см або отримано команду ввімкнення через MQTT.
on_Off = 0; // Скидання флагу команди.
LED = !LED; // Зміна стану світлодіода.
lastTime1 = millis(); // Оновлення часу взаємодії.
if (LED) {
client.publish("LIGHT_", "1"); // Надсилання повідомлення про ввімкнення.
} else {
client.publish("LIGHT_", "0"); // Надсилання повідомлення про вимкнення.
}
digitalWrite(LIGHT_PIN, LED); // Зміна стану світлодіода.
}
pir = digitalRead(PIR_PIN); // Зчитування стану PIR-датчика.
if (pir) {
lastTime2 = millis(); // Оновлення часу останнього руху.
}
if (((millis() - lastTime2) > time_) && LED == true) {
// Якщо перевищено час автоматичного вимкнення та світлодіод ввімкнено.
LED = false; // Вимикання світлодіода.
client.publish("LIGHT_", "0"); // Надсилання повідомлення про вимкнення.
digitalWrite(LIGHT_PIN, LED); // Фізичне вимкнення світлодіода.
}
client.loop(); // Обробка MQTT-з'єднання.
}
int readDistanceCm() {
digitalWrite(TRIG_PIN, LOW); // Встановлення TRIG в низький стан.
delayMicroseconds(2); // Затримка 2 мкс.
digitalWrite(TRIG_PIN, HIGH); // Встановлення TRIG у високий стан.
delayMicroseconds(10); // Затримка 10 мкс для запуску імпульсу.
digitalWrite(TRIG_PIN, LOW); // Встановлення TRIG назад у низький стан.
int duration = pulseIn(ECHO_PIN, HIGH); // Вимірювання часу затримки відбитого сигналу.
return duration * 0.034 / 2; // Розрахунок відстані у см.
}
void callback(char* topic, byte* payload, unsigned int length) {
// Обробка повідомлень з топіків MQTT.
String valueString = ""; // Рядок для збереження отриманого повідомлення.
Serial.print("Message arrived in topic: ");
Serial.println(topic); // Виведення топіка.
Serial.print("Message: ");
for (int i = 0; i < length; i++) {
valueString += (char)payload[i]; // Конвертація повідомлення з байтів у текст.
}
Serial.println(valueString);
if (String(topic) == "On_Off") {
if (valueString == "1") {
on_Off = 1; // Увімкнення через MQTT.
}
}
if (String(topic) == "Time") {
time_ = valueString.toInt(); // Зміна таймера автоматичного вимкнення.
if (time_ < 0) {
time_ = 10000; // Перевірка на коректність, встановлення значення за замовчуванням.
}
}
delay(3000); // Затримка обробки (рекомендовано уникати таких затримок у callback).
}