#define BLYNK_TEMPLATE_ID "TMPL6LPfD1AES"
#define BLYNK_TEMPLATE_NAME "Lab2SmartSchool"
#define BLYNK_DEVICE_NAME "Lab2SmartSchool"
#define BLYNK_AUTH_TOKEN "ycpoCVUUrEMqukhnBg3YiHNfhBsWXv-1"
// Comment this out to disable prints and save space
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
// WiFi credentials
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Pin definitions
#define button1_pin 26 // Button for Room 1 (light)
#define button2_pin 25 // Button for Room 2 (light)
#define button3_pin 33 // Button for Room 1 Attendance
#define button4_pin 32 // Button for Room 2 Attendance
#define relay1_pin 13 // Relay for Room 1 (light)
#define relay2_pin 12 // Relay for Room 2 (light)
#define relay3_pin 15 // Relay for Water Pump
#define trigPin 5 // Trigger pin for HC-SR04
#define echoPin 18 // Echo pin for HC-SR04
#define pirLed_pin 4 // Đèn LED biểu thị cho PIR
#define pirPin 17 // Chân cảm biến PIR
// Virtual Pins for Blynk
#define button1_vpin V1
#define button2_vpin V2
#define button3_vpin V3
#define button4_vpin V4
#define waterLevel_vpin V0
// Water level thresholds
#define WATER_LOW_THRESHOLD 10
#define WATER_HIGH_THRESHOLD 50
// Global variables
int relay1_state = 0;
int relay2_state = 0;
int relay3_state = 0;
int attendanceRoom1 = 0;
int attendanceRoom2 = 0;
unsigned long lastDebounceTime1 = 0, lastDebounceTime2 = 0;
unsigned long lastDebounceTime3 = 0, lastDebounceTime4 = 0;
const unsigned long debounceDelay = 200;
BlynkTimer timer;
// Blynk sync on connection
BLYNK_CONNECTED() {
Blynk.syncVirtual(button1_vpin, button2_vpin, button3_vpin, button4_vpin, waterLevel_vpin);
}
// Control relay via Blynk
BLYNK_WRITE(button1_vpin) {
relay1_state = param.asInt();
digitalWrite(relay1_pin, relay1_state);
}
BLYNK_WRITE(button2_vpin) {
relay2_state = param.asInt();
digitalWrite(relay2_pin, relay2_state);
}
// Setup function
void setup() {
Serial.begin(115200);
pinMode(button1_pin, INPUT_PULLUP);
pinMode(button2_pin, INPUT_PULLUP);
pinMode(button3_pin, INPUT_PULLUP);
pinMode(button4_pin, INPUT_PULLUP);
pinMode(relay1_pin, OUTPUT);
pinMode(relay2_pin, OUTPUT);
pinMode(relay3_pin, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(pirPin, INPUT);
pinMode(pirLed_pin, OUTPUT);
digitalWrite(pirLed_pin, LOW); // Tắt đèn ban đầu
// Turn off all relays initially
digitalWrite(relay1_pin, LOW);
digitalWrite(relay2_pin, LOW);
digitalWrite(relay3_pin, LOW);
Blynk.begin(auth, ssid, pass);
}
// Main loop
void loop() {
Blynk.run();
timer.run();
listen_push_buttons();
listen_attendance_buttons();
checkWaterLevel();
listen_pir_sensor();
}
// Listen for physical button presses
void listen_push_buttons() {
if (digitalRead(button1_pin) == LOW && (millis() - lastDebounceTime1) > debounceDelay) {
lastDebounceTime1 = millis();
control_relay(1);
Blynk.virtualWrite(button1_vpin, relay1_state);
}
if (digitalRead(button2_pin) == LOW && (millis() - lastDebounceTime2) > debounceDelay) {
lastDebounceTime2 = millis();
control_relay(2);
Blynk.virtualWrite(button2_vpin, relay2_state);
}
}
// Listen for attendance button presses
void listen_attendance_buttons() {
if (digitalRead(button3_pin) == LOW && (millis() - lastDebounceTime3) > debounceDelay) {
lastDebounceTime3 = millis();
attendanceRoom1++;
Blynk.virtualWrite(button3_vpin, attendanceRoom1);
Serial.println("Room 1 Attendance Updated: " + String(attendanceRoom1));
}
if (digitalRead(button4_pin) == LOW && (millis() - lastDebounceTime4) > debounceDelay) {
lastDebounceTime4 = millis();
attendanceRoom2++;
Blynk.virtualWrite(button4_vpin, attendanceRoom2);
Serial.println("Room 2 Attendance Updated: " + String(attendanceRoom2));
}
}
// Toggle relay state
void control_relay(int relay) {
switch (relay) {
case 1:
relay1_state = !relay1_state;
digitalWrite(relay1_pin, relay1_state);
Serial.println("Relay 1 State: " + String(relay1_state));
break;
case 2:
relay2_state = !relay2_state;
digitalWrite(relay2_pin, relay2_state);
Serial.println("Relay 2 State: " + String(relay2_state));
break;
}
}
// Check water level
void checkWaterLevel() {
long duration, distance;
// Measure distance
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration / 2) * 0.0344;
// Send water level to Blynk
Blynk.virtualWrite(waterLevel_vpin, distance);
// Control water pump
if (distance < WATER_LOW_THRESHOLD && relay3_state == 1) {
relay3_state = 0;
digitalWrite(relay3_pin, LOW);
Serial.println("Water Pump OFF");
} else if (distance > WATER_HIGH_THRESHOLD && relay3_state == 0) {
relay3_state = 1;
digitalWrite(relay3_pin, HIGH);
Serial.println("Water Pump ON");
}
}
bool previousPirState = LOW; // Trạng thái trước của cảm biến PIR
void listen_pir_sensor() {
int pirState = digitalRead(pirPin); // Đọc trạng thái từ cảm biến PIR
if (pirState == HIGH && previousPirState == LOW) { // Phát hiện chuyển động
digitalWrite(pirLed_pin, HIGH); // Bật đèn báo hiệu PIR
Serial.println("Motion detected! PIR LED ON.");
} else if(pirState == LOW && previousPirState == HIGH)
{ // Không phát hiện chuyển động
digitalWrite(pirLed_pin, LOW); // Tắt đèn báo hiệu PIR
Serial.println("No motion. PIR LED OFF.");
}
previousPirState = pirState;
}