// Định nghĩa mã ID, tên, mã Token để sử dụng Blynk
#define BLYNK_TEMPLATE_ID "TMPL6WsAQrsk3"
#define BLYNK_TEMPLATE_NAME "Traffic light Tan"
#define BLYNK_AUTH_TOKEN "GfC44MrzPuoYH4bGk-XYn1KME1eobVcc"
//Định nghĩa in ra thông tin debug của Blynk qua cổng Serial.
#define BLYNK_PRINT Serial
// Khai báo thư viện cần thiết cho việc kết nối Wifi và Blynk
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <Ticker.h>
//Lưu trữ tên mật khẩu Wifi
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
//Khởi tạo một đối tượng BlynkTimer để quản lý bộ hẹn giờ trong chương trình.
// BlynkTimer timer;
//Định nghĩa chân LED
#define RED 14 //Led đỏ đang kết nối với chân 14
#define YELLOW 13 //Led vàng đang kết nối với chân 13
#define GREEN 12 //Led xanh đang kết nối với chân 12
int RED_VALUE = 0; //Khai báo biến RED_VALUE kiểu số nguyên và gán giá trị ban đầu là 0. Biến này sẽ lưu trữ trạng thái của công tắc ảo (Virtual Pin) cho đèn đỏ trên ứng dụng Blynk.
int YELLOW_VALUE = 0; //Khai báo biến YELLOW_VALUE kiểu số nguyên và gán giá trị ban đầu là 0. Biến này sẽ lưu trữ trạng thái của công tắc ảo (Virtual Pin) cho đèn vàng trên ứng dụng Blynk.
int GREEN_VALUE = 0; //Khai báo biến GREEN_VALUE kiểu số nguyên và gán giá trị ban đầu là 0. Biến này sẽ lưu trữ trạng thái của công tắc ảo (Virtual Pin) cho đèn xanh trên ứng dụng Blynk.
int atu = 0;
int atu1 = 0;
//int timer = 0;
// Hàm này được gọi mỗi khi trạng thái Virtual Pin 0 thay đổi
BLYNK_WRITE(V0)
{
int RED_VALUE = param.asInt();
//Nếu RED_VALUE có giá trị 1, tức là công tắc ảo được bật, thì đèn đỏ sẽ được bật và các đèn khác sẽ tắt.
//Nếu RED_VALUE có giá trị khác 1, tức là công tắc ảo được tắt
if (RED_VALUE == 1) {
digitalWrite(RED, HIGH);
digitalWrite(YELLOW, LOW);
digitalWrite(GREEN, LOW);
}else{
digitalWrite(RED, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(GREEN, LOW);
}
// Cập nhật trạng thái của công tắc ảo lên ứng dụng Blynk bằng cách sử dụng hàm virtualWrite().
Blynk.virtualWrite(V0, RED_VALUE);
Blynk.virtualWrite(V1, YELLOW_VALUE);
Blynk.virtualWrite(V2, GREEN_VALUE);
}
BLYNK_WRITE(V1)
{
int YELLOW_VALUE = param.asInt();
if (YELLOW_VALUE == 1) {
digitalWrite(RED, LOW);
digitalWrite(YELLOW, HIGH);
digitalWrite(GREEN, LOW);
}else{
digitalWrite(RED, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(GREEN, LOW);
}
// Update state
Blynk.virtualWrite(V0, RED_VALUE);
Blynk.virtualWrite(V1, YELLOW_VALUE);
Blynk.virtualWrite(V2, GREEN_VALUE);
}
BLYNK_WRITE(V2)
{
int GREEN_VALUE = param.asInt();
if (GREEN_VALUE == 1) {
digitalWrite(RED, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(GREEN, HIGH);
}else{
digitalWrite(RED, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(GREEN, LOW);
}
// Update state
Blynk.virtualWrite(V0, RED_VALUE);
Blynk.virtualWrite(V1, YELLOW_VALUE);
Blynk.virtualWrite(V2, GREEN_VALUE);
}
Ticker trafficLightTimer;
// Định nghĩa trạng thái của đèn
#define GREEN_STATE 0
#define YELLOW_STATE 1
#define RED_STATE 2
// Biến lưu trữ trạng thái hiện tại
int currentState = GREEN_STATE;
// Hàm chuyển trạng thái đèn
void changeLightState() {
// Tắt tất cả các đèn
digitalWrite(GREEN, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(RED, LOW);
// Chuyển trạng thái đèn
switch (currentState) {
case GREEN_STATE:
currentState = YELLOW_STATE;
digitalWrite(YELLOW, HIGH);
// Kích hoạt timer để chuyển trạng thái sau 4 giây
trafficLightTimer.attach(4, changeLightState);
break;
case YELLOW_STATE:
currentState = RED_STATE;
digitalWrite(RED, HIGH);
// Kích hoạt timer để chuyển trạng thái sau 3 giây
trafficLightTimer.attach(3, changeLightState);
break;
case RED_STATE:
currentState = GREEN_STATE;
digitalWrite(GREEN, HIGH);
// Kích hoạt timer để chuyển trạng thái sau 5 giây
trafficLightTimer.attach(5, changeLightState);
break;
}
}
BLYNK_WRITE(V3)
{
int atu = param.asInt();
// Nếu công tắc ảo được bật, kích hoạt timer chuyển trạng thái đèn
if (atu == 1 && !trafficLightTimer.active()) {
changeLightState(); // Chuyển trạng thái đèn ngay lập tức
// Kích hoạt timer để chuyển trạng thái sau 1 giây
trafficLightTimer.attach(1, changeLightState);
} else if (atu == 0) {
// Nếu công tắc ảo được tắt, tắt tất cả các đèn và ngưng timer
digitalWrite(GREEN, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(RED, LOW);
trafficLightTimer.detach();
}
// Update state
Blynk.virtualWrite(V3, atu);
Blynk.virtualWrite(V0, RED_VALUE);
Blynk.virtualWrite(V1, YELLOW_VALUE);
Blynk.virtualWrite(V2, GREEN_VALUE);
Blynk.virtualWrite(V4, atu1);
}
Ticker timer1;
// Biến lưu trữ trạng thái của đèn xanh
int lightState = LOW;
// Hàm nhấp nháy đèn xanh
void blinkYELLOW() {
lightState = !lightState; // Đảo trạng thái của đèn xanh
digitalWrite(YELLOW, lightState);
}
BLYNK_WRITE(V4)
{
int atu1 = param.asInt();
// Nếu có giá trị 1 và timer chưa được kích hoạt, bắt đầu nhấp nháy
if (atu1 == 1 && !timer1.active()) {
// Kích hoạt timer để gọi hàm blinkGreen mỗi 500ms
timer1.attach(0.5, blinkYELLOW);
} else if (atu1 == 0) {
// Nếu có giá trị khác 1, tắt đèn xanh và ngưng timer
digitalWrite(YELLOW, LOW);
timer1.detach();
}
// Update state
Blynk.virtualWrite(V0, RED_VALUE);
Blynk.virtualWrite(V1, YELLOW_VALUE);
Blynk.virtualWrite(V2, GREEN_VALUE);
Blynk.virtualWrite(V3, atu);
Blynk.virtualWrite(V4, atu1);
}
void setup()
{
pinMode(RED, OUTPUT); //Thiết lập chân GPIO được định nghĩa là RED là chế độ OUTPUT
pinMode(YELLOW, OUTPUT); //Thiết lập chân GPIO được định nghĩa là YELLOW là chế độ OUTPUT
pinMode(GREEN, OUTPUT); //Thiết lập chân GPIO được định nghĩa là GREEN là chế độ OUTPUT
Serial.begin(9600); //Khởi động giao tiếp Serial với tốc độ baud rate là 9600. Điều này cho phép dữ liệu được gửi và nhận thông qua cổng Serial.
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass); //Khởi động kết nối với ứng dụng Blynk
}
//duy trì kết nối với ứng dụng Blynk và xử lý các sự kiện
void loop()
{
Blynk.run();
//timer.run();
}