#define BLYNK_TEMPLATE_ID "TMPL4Uj-RXMOV" // Визначення ID шаблону для Blynk
#define BLYNK_TEMPLATE_NAME "ESP32 photoresistorLDRsensor" // Визначення імені пристрою для Blynk
#define BLYNK_AUTH_TOKEN "SNXUeUC4odR_QFQHbW7-02bfm8sBPHir" // Визначення токену аутентифікації для Blynk
#include <WiFi.h> // Підключення бібліотеки WiFi для ESP32
#include <WiFiClient.h> // Підключення бібліотеки WiFiClient
#include <BlynkSimpleEsp32.h> // Підключення бібліотеки Blynk для ESP32
#include <Wire.h> // Підключення бібліотеки Wire для роботи з I2C
#include <LiquidCrystal_I2C.h> // Підключення бібліотеки для роботи з LCD дисплеєм через I2C
char auth[] = BLYNK_AUTH_TOKEN; // Збереження токену аутентифікації у змінну
char ssid[] = "Wokwi-GUEST"; // Збереження SSID (назви Wi-Fi мережі) у змінну
char pass[] = ""; // Збереження пароля Wi-Fi у змінну
#define LDR_PIN 34 // Визначення піну для датчика освітленості
#define LED_PIN 2 // Визначення піну для світлодіода
#define BUTTON_PIN 0 // Визначення піну для кнопки
#define SDA_PIN 21 // Визначення піну SDA для I2C
#define SCL_PIN 22 // Визначення піну SCL для I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // Ініціалізація LCD дисплея (I2C адреса 0x27, розмір 16x2 символів)
volatile bool buttonPressed = false; // Визначення флагу для обробки переривання
bool manualMode = false; // Визначення змінної для режиму роботи (ручний або автоматичний)
bool ledState = false; // Визначення змінної для стану діода
unsigned long lastDebounceTime = 0; // Збереження часу останнього натискання кнопки
unsigned long debounceDelay = 50; // Затримка для усунення дрібезгу (50 мс)
int thresholdValue = 200; // Початкове значення порогу
BlynkTimer timer; // Ініціалізація таймера для Blynk
// Функція для перевірки значення датчика освітленості
void checkLDR() {
int ldrValue = analogRead(LDR_PIN); // Читання значення з датчика освітленості
Serial.print("LDR Value: ");
Serial.println(ldrValue);
lcd.setCursor(0, 0); // Встановлення курсору на початок першого рядка дисплея
lcd.print("LDR: ");
lcd.print(ldrValue); // Виведення значення датчика освітленості на дисплей
lcd.print(" "); // Очищення залишку рядка
if (!manualMode) { // Якщо автоматичний режим
if (ldrValue < thresholdValue) { // Якщо значення освітленості менше 200
digitalWrite(LED_PIN, HIGH); // Включити світлодіод
ledState = true; // Встановити стан світлодіода в "включений"
} else {
digitalWrite(LED_PIN, LOW); // Вимкнути світлодіод
ledState = false; // Встановити стан світлодіода в "вимкнений"
}
Blynk.virtualWrite(V1, ledState); // Відправити стан світлодіода на Blynk
}
Blynk.virtualWrite(V0, ldrValue);
lcd.setCursor(0, 1); // Встановити курсор на початок другого рядка дисплея
lcd.print("LED: ");
lcd.print(ledState ? "ON " : "OFF "); // Вивести стан світлодіода на дисплей
}
// Функція для обробки запису з віртуального піну V1
BLYNK_WRITE(V1) {
int pinValue = param.asInt(); // Отримати значення з Blynk
if (manualMode) { // Якщо ручний режим
if (pinValue == 1) { // Якщо значення 1 (включити)
digitalWrite(LED_PIN, HIGH); // Включити світлодіод
ledState = true; // Встановити стан світлодіода в "включений"
} else {
digitalWrite(LED_PIN, LOW); // Вимкнути світлодіод
ledState = false; // Встановити стан світлодіода в "вимкнений"
}
}
lcd.setCursor(0, 1); // Встановити курсор на початок другого рядка дисплея
lcd.print("LED: ");
lcd.print(ledState ? "ON " : "OFF "); // Вивести стан світлодіода на дисплей
}
BLYNK_WRITE(V3) {
thresholdValue = param.asInt(); // Оновлення порогового значення
Serial.print("New threshold value: ");
Serial.println(thresholdValue);
}
// Функція обробки переривання від кнопки
void IRAM_ATTR handleButtonPress() {
unsigned long currentTime = millis(); // Отримати поточний час
if ((currentTime - lastDebounceTime) > debounceDelay) { // Якщо пройшло більше часу, ніж затримка для debounce
buttonPressed = true; // Встановити флаг обробки переривання
lastDebounceTime = currentTime; // Оновити час останнього натискання кнопки
}
}
void setup() {
pinMode(LDR_PIN, INPUT); // Встановити пін LDR як вхідний
pinMode(LED_PIN, OUTPUT); // Встановити пін LED як вихідний
pinMode(BUTTON_PIN, INPUT_PULLUP); // Встановити пін кнопки як вхідний з підтягувачем
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleButtonPress, FALLING); // Прив'язати переривання до піну кнопки
Serial.begin(115200); // Ініціалізація серійного зв'язку
Wire.begin(SDA_PIN, SCL_PIN); // Ініціалізація I2C на визначених пінах
lcd.init(); // Ініціалізація дисплея
lcd.backlight(); // Включення підсвітки дисплея
lcd.clear(); // Очищення дисплея
lcd.setCursor(0, 0); // Встановлення курсору на початок першого рядка дисплея
lcd.print("Initializing..."); // Виведення повідомлення про ініціалізацію
Blynk.begin(auth, ssid, pass); // Підключення до Blynk
timer.setInterval(1000L, checkLDR); // Налаштування таймера для перевірки датчика освітленості кожну секунду
}
void loop() {
Blynk.run(); // Запуск Blynk
timer.run(); // Запуск таймера
if (buttonPressed) { // Якщо флаг переривання встановлено
manualMode = !manualMode; // Перемикання режиму (ручний/автоматичний)
Serial.print("Manual mode: ");
Serial.println(manualMode ? "ON" : "OFF"); // Виведення стану режиму в серійний порт
Blynk.virtualWrite(V2, manualMode ? "Manual" : "Automatic"); // Відправка стану режиму в Blynk
lcd.setCursor(0, 1); // Встановлення курсору на початок другого рядка дисплея
lcd.print("Mode: ");
lcd.print(manualMode ? "Manual " : "Auto "); // Виведення стану режиму на дисплей
if (!manualMode) {
checkLDR(); // Перевірка рівня освітленості при перемиканні на автоматичний режим
}
buttonPressed = false; // Скидання флагу переривання
}
}