Làm mô hình đèn giao thông thông minh với Arduino và nút bấm cho người đi bộ

Mô hình sẽ hoạt động như thế nào?

Ở trạng thái bình thường, đèn xe màu xanh và đèn người đi bộ màu đỏ sáng. Khi có người nhấn nút, Arduino chuyển đèn xe sang vàng, rồi đỏ. Sau một khoảng chờ ngắn, đèn người đi bộ mới chuyển xanh. Hết thời gian qua đường, đèn người đi bộ trở lại đỏ trước khi đèn xe chuyển xanh.

Đây là mô hình học tập để tìm hiểu đầu vào, đầu ra và trình tự điều khiển bằng Arduino; không dùng để điều khiển giao thông thực tế.

Chuẩn bị linh kiện

Bạn cần một Arduino Uno hoặc bo tương thích, breadboard, dây nối, nút nhấn, cáp USB và 5 LED: đỏ, vàng, xanh cho xe; đỏ, xanh cho người đi bộ. Chuẩn bị thêm 5 điện trở hạn dòng, mỗi điện trở khoảng 220–330 Ω, để mắc nối tiếp với từng LED.

Ngắt kết nối USB trước khi thay đổi dây trên breadboard. Mỗi LED cần điện trở riêng; không nối LED trực tiếp giữa chân tín hiệu và GND.

Nối mạch theo từng nhóm tín hiệu

Nối chân GND của Arduino với thanh GND trên breadboard. Với mỗi LED, nối chân Arduino đến điện trở, từ điện trở đến chân dài của LED; nối chân ngắn của LED về GND. Dùng D8 cho đèn xe đỏ, D9 cho đèn xe vàng, D10 cho đèn xe xanh, D11 cho đèn người đi bộ đỏ và D12 cho đèn người đi bộ xanh.

Nối một phía của nút nhấn vào D2, phía đối diện vào GND. Chương trình dùng INPUT_PULLUP: nút chưa nhấn được đọc là HIGH, nút nhấn được đọc là LOW. Nếu dùng nút bốn chân, hãy đặt nút vắt qua rãnh giữa breadboard để hai phía không bị nối sẵn với nhau.

Xác định trình tự và thời gian

Sau khi nút được nhấn, chương trình giữ đèn xe xanh thêm ít nhất 2 giây, bật đèn vàng trong 2 giây, rồi bật đèn xe đỏ. Cả hai hướng đều đỏ trong 1 giây trước khi đèn người đi bộ xanh sáng trong 5 giây.

Khi hết 5 giây, đèn người đi bộ chuyển đỏ. Chương trình tiếp tục giữ đèn xe đỏ thêm 1 giây rồi mới bật đèn xe xanh. Hai khoảng chờ khi cả hai hướng đều đỏ giúp học sinh thấy rõ rằng hai đèn xanh không được sáng cùng lúc.

Nạp chương trình Arduino

Mở Arduino IDE, chọn đúng loại bo và cổng kết nối, rồi tạo sketch mới. Chép chương trình dưới đây và nạp vào bo. Hàm denXe và denDiBo gom các thao tác bật, tắt LED; biến sanSang ngăn việc giữ nút liên tục tạo ra nhiều yêu cầu qua đường.

const byte NUT = 2;
const byte XE_DO = 8;
const byte XE_VANG = 9;
const byte XE_XANH = 10;
const byte BO_DO = 11;
const byte BO_XANH = 12;
bool sanSang = true;

void denXe(bool doBat, bool vangBat, bool xanhBat) {
digitalWrite(XE_DO, doBat);
digitalWrite(XE_VANG, vangBat);
digitalWrite(XE_XANH, xanhBat);
}

void denDiBo(bool doBat, bool xanhBat) {
digitalWrite(BO_DO, doBat);
digitalWrite(BO_XANH, xanhBat);
}

void setup() {
pinMode(NUT, INPUT_PULLUP);
pinMode(XE_DO, OUTPUT);
pinMode(XE_VANG, OUTPUT);
pinMode(XE_XANH, OUTPUT);
pinMode(BO_DO, OUTPUT);
pinMode(BO_XANH, OUTPUT);
denDiBo(true, false);
denXe(false, false, true);
}

void loop() {
if (digitalRead(NUT) == HIGH) sanSang = true;

if (sanSang && digitalRead(NUT) == LOW) {
delay(30); // Kiểm tra lại để giảm tác động của nút dội
if (digitalRead(NUT) != LOW) return;
sanSang = false;

delay(2000);
denXe(false, true, false);
delay(2000);
denXe(true, false, false);
delay(1000);
denDiBo(false, true);
delay(5000);
denDiBo(true, false);
delay(1000);
denXe(false, false, true);
}
}

Kiểm tra và xử lý lỗi thường gặp

Sau khi nạp, quan sát trạng thái ban đầu: xe xanh, người đi bộ đỏ. Nhấn rồi thả nút một lần và theo dõi toàn bộ trình tự. Kiểm tra riêng thời điểm chuyển hướng: đèn xe xanh và đèn người đi bộ xanh không được sáng đồng thời.

Nếu LED không sáng, ngắt USB rồi kiểm tra chiều LED, điện trở, dây GND và số chân trong chương trình. Nếu nhấn nút không có tác dụng, kiểm tra hai dây nút có nằm ở hai phía đối diện của nút hay không. Chương trình dùng delay nên không nhận thêm yêu cầu trong lúc đang chạy một chu kỳ; đây là giới hạn có chủ ý của phiên bản cơ bản.

Thử mở rộng bài học

Cho học sinh vẽ sơ đồ trạng thái gồm: xe xanh, xe vàng, tất cả đỏ, người đi bộ xanh và trở về ban đầu. Từ đó, thử thay đổi thời gian trong chương trình và dự đoán điều gì sẽ xảy ra trước khi nạp lại.

Một thử thách tiếp theo là thay delay bằng millis để Arduino vẫn có thể đọc nút trong khi đèn đang hoạt động. Khi mở rộng, hãy xác định rõ yêu cầu nhấn thêm sẽ được bỏ qua hay lưu lại cho chu kỳ kế tiếp.