/*Kịch bản:
* Mô phỏng nút bấm qua đường dành cho người đi bộ
* Ban đầu led đang xanh cho xe chạy, khi có tín hiệu nút bấm thì đếm ngược
* thời gian 9-0 để chuyển qua led vàng, đếm ngược 3-0 để chuyển qua led
* đỏ đồng thời bật led cho người đi bộ qua đường trong 10s (9-0)
*/
// Cấu hình chân của các led đơn
const int LED_WALK = 9; // Đèn cho người đi bộ
const int LED_RED = 10; // Đèn đỏ
const int LED_YELLOW = 11; // Đèn vàng
const int LED_GREEN = 12; // Đèn xanh cho xe chạy
// Cấu hình led 7 thanh từ chân 2-8
const int segPins[7] = {2, 3, 4, 5, 6, 7, 8};
// Nút bấm
const int BUTTON_PIN = 13;
// Mã hóa số cho led 7 thanh (Cathode chung)
const byte digitPatterns[10][7] = {
{1, 1, 1, 1, 1, 1, 0}, // 0
{0, 1, 1, 0, 0, 0, 0}, // 1
{1, 1, 0, 1, 1, 0, 1}, // 2
{1, 1, 1, 1, 0, 0, 1}, // 3
{0, 1, 1, 0, 0, 1, 1}, // 4
{1, 0, 1, 1, 0, 1, 1}, // 5
{1, 0, 1, 1, 1, 1, 1}, // 6
{1, 1, 1, 0, 0, 0, 0}, // 7
{1, 1, 1, 1, 1, 1, 1}, // 8
{1, 1, 1, 1, 0, 1, 1} // 9
};
// === CÁC TRẠNG THÁI HỆ THỐNG (STATE MACHINE) ===
enum TrafficState {
STATE_IDLE_GREEN, // Xe chạy, LED 7 thanh tắt (chờ bấm nút)
STATE_GREEN, // Xe chạy (Đèn xanh sáng)
STATE_YELLOW, // Xe chuẩn bị dừng (Đèn vàng sáng)
STATE_RED // Xe dừng - Người đi bộ sang đường (Đèn đỏ & Đèn đi bộ)
};
TrafficState currentState = STATE_IDLE_GREEN;
// Biến thời gian và
unsigned long previousMillis = 0;
const long ONE_SECOND = 1000; // 1000ms
int countdown = 0; // Thời gian đếm ngược (giây)
// Anti-debounce (Chống dội) nút bấm
unsigned long lastDebounceTime = 0;
const long debounceDelay = 50;
int lastButtonState = HIGH;
// === HÀM HIỂN THỊ LED 7 THANH ===
void displayDigit(int num) {
if (num < 0 || num > 9) return;
for (int i = 0; i < 7; i++) {
digitalWrite(segPins[i], digitPatterns[num][i]);
}
}
// Hàm tắt led 7 thanh
void clearDisplay() {
for (int i = 0; i < 7; i++) {
digitalWrite(segPins[i], LOW);
}
}
// === HÀM CHUYỂN ĐỔI TRẠNG THÁI VÀ BẬT/TẮT ĐÈN ===
void setTrafficState(TrafficState newState, int seconds) {
currentState = newState;
countdown = seconds;
// Tắt tất cả các LED đơn
digitalWrite(LED_RED, LOW);
digitalWrite(LED_YELLOW, LOW);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_WALK, LOW);
// Bật đèn tương ứng trạng thái
switch (currentState) {
case STATE_IDLE_GREEN:
digitalWrite(LED_GREEN, HIGH);
clearDisplay(); // Tắt LED 7 thanh khi đang chờ
break;
case STATE_GREEN_COUNTDOWN:
digitalWrite(LED_GREEN, HIGH);
clearDisplay(); // Tắt LED 7 thanh khi ở chế độ chờ
break;
case STATE_YELLOW:
digitalWrite(LED_YELLOW, HIGH);
displayDigit(countdown);
break;
case STATE_RED_WALK:
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_WALK, HIGH); // Bật đèn cho người đi bộ
displayDigit(countdown);
break;
}
}
}
// === HÀM THIẾT LẬP (SETUP) ===
void setup() {
// Cấu hình chân LED đơn
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_YELLOW, OUTPUT);
pinMode(LED_RED, OUTPUT);
pinMode(LED_WALK, OUTPUT);
// Cấu hình các chân LED 7 thanh (D2 -> D8)
for (int i = 0; i < 7; i++) {
pinMode(segPins[i], OUTPUT);
}
// Cấu hình nút bấm dùng trở kéo lên nội bù
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Khởi tạo trạng thái ban đầu: Đèn xanh sáng, đếm ngược từ 9
setTrafficState(STATE_IDLE_GREEN, 0);
}
// === VÒNG LẶP CHÍNH (LOOP) ===
void loop() {
unsigned long currentMillis = millis();
// 1. ĐỌC VÀ CHỐNG DỘI NÚT BẤM (DEBOUNCE)
if (currentState == STATE_IDLE_GREEN) {
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastDebounceTime = currentMillis;
}
if ((currentMillis - lastDebounceTime) > debounceDelay) {
// Khi nhấn nút (LOW) -> Bắt đầu kích hoạt chu kỳ giao thông
if (reading == LOW) {
previousMillis = currentMillis;
setTrafficState(STATE_GREEN_COUNTDOWN, 9); // Bắt đầu đếm ngược Đèn xanh từ 9s
}
}
lastButtonState = reading;
}
// 2. XỬ LÝ ĐẾM NGƯỢC THỜI GIAN REAL-TIME
if (currentState != STATE_IDLE_GREEN) {
if (currentMillis - previousMillis >= ONE_SECOND) {
previousMillis = currentMillis;
countdown--;
if (countdown >= 0) {
displayDigit(countdown);
} else {
// Khi đếm về 0 -> Chuyển pha giao thông tiếp theo
switch (currentState) {
case STATE_GREEN_COUNTDOWN:
setTrafficState(STATE_YELLOW, 3); // Chuyển sang Vàng (3 giây)
break;
case STATE_YELLOW:
setTrafficState(STATE_RED, 7); // Chuyển sang Đỏ & Đi bộ (7 giây)
break;
case STATE_RED_WALK:
walkRequested = false; // Reset cờ yêu cầu người đi bộ
setTrafficState(STATE_GREEN, 9); // Quay lại Xanh (9 giây)
break;
default:
break;
}
}
}
}
}