Mục lục bài viết

1. Đèn tín hiệu giao thông có nút bấm

Ở các ngã tư, loại đèn có 3 màu thường được sử dụng để điều khiển giao thông. Loại này dành cho xe cộ với 3 màu: đỏ, xanh, vàng. Các màu này có ý nghĩa:

  • Đỏ: Không được phép qua đường.
  • Xanh: Được phép qua đường.
  • Vàng: Sắp hết thời gian được phép qua đường.
Đèn giao thông 3 màu: xanh, vàng, đỏ
Đèn giao thông 3 màu: xanh, vàng, đỏ

Loại đèn giao thông 3 màu có thể có thêm nút bấm. Cảnh sát giao thông dùng nút bấm này khi lưu lượng xe bất thường. Bấm nút là đổi đèn xanh, đỏ ngay lập tức để điều tiết giao thông.

2. Giả lập điều khiển đèn tín hiệu giao thông có nút bấm với Arduino

Sơ đồ mạch

Bên dưới là sơ đồ mạch điều khiển loại 3 đèn có nút bấm ở ngã tư với Arduino.

Sơ đồ mạch điều khiển đèn tín hiệu giao thông có nút bấm với Arduino
Sơ đồ mạch điều khiển đèn tín hiệu giao thông có nút bấm với Arduino

Ở ngã tư, người đi đường nhìn cụm đèn bên phải theo hướng đi của mình. Tuy là ngã tư nhưng thực chất chỉ cần xử lý đèn theo 2 hướng: chiều ngang và chiều dọc. Cụm đèn D1, D2, D3 sẽ tương tự cụm đèn D10, D11, D12. Cụm đèn D4, D5, D6 sẽ tương tự cụm đèn D7, D8, D9.

Nguyên lý hoạt động

Chúng ta xét cụm đèn D1, D2, D3 và cụm đèn D4, D5, D6. Chúng ta qui ước mặc định là đèn xanh D3 sẽ sáng trước. Lúc này, có 4 lượt đèn giao thông sáng và lặp đi lặp lại như sau:

Lượt 1 – Đèn đỏ D4 và đèn xanh D3 sáng, các đèn D1, D2, D5, D6 tắt.

Lượt 2 – Đèn đỏ D4 và đèn vàng D2 sáng, các đèn D1, D3, D5, D6 tắt.

Lượt 3 – Đèn đỏ D1 và đèn xanh D6 sáng, các đèn D2, D3, D4, D5 tắt.

Lượt 4 – Đèn đỏ D1 và đèn vàng D5 sáng, các đèn D2, D3, D4, D6 tắt.

Khi nhấn nút bấm lần 1 (lần lẻ), đèn xanh D6 sẽ sáng. Lúc này, có 4 lượt đèn giao thông sáng và lặp đi lặp lại như sau:

Lượt 1 – Đèn đỏ D1 và đèn xanh D6 sáng, các đèn D2, D3, D4, D5 tắt.

Lượt 2 – Đèn đỏ D1 và đèn vàng D5 sáng, các đèn D2, D3, D4, D6 tắt.

Lượt 3 – Đèn đỏ D4 và đèn xanh D3 sáng, các đèn D1, D2, D5, D6 tắt.

Lượt 4 – Đèn đỏ D4 và đèn vàng D2 sáng, các đèn D1, D3, D5, D6 tắt.

Trường hợp nhấn nút bấm lần 2 (lần chẵn) thì sẽ quay về lượt đèn xanh D3 sẽ sáng trước. Cứ như thế lặp lại với nhấn lần 3, lần 4,… của nút bấm.

Code Arduino

Dưới đây là code Arduino điều khiển đèn giao thông với sơ đồ mạch đã cho.

//led-red
int d1=7, d4=4, d7=10, d10=13;
//led-yellow
int d2=6, d5=3, d8=9, d11=12;
//led-green
int d3=5, d6=2, d9=8, d12=11;
//sử dụng hàm millis() thay delay()
unsigned long previousMillis = 0;
//button
int btn=1;
int preState=LOW;
int dem=0;
void setup() {
  for(int i=2;i<14;i++){
    pinMode(i, OUTPUT);
  }
  pinMode(btn, INPUT);
}

void loop() {
  int curState=digitalRead(btn);
  if(curState==HIGH && preState==LOW){
    dem++;
    if(dem==2){
      dem=0;
    }
    previousMillis = millis();
  }
  if(dem==1){
    denxanhD6sangtruoc();
  }else{
    denxanhD3sangtruoc();
  }
  preState=curState;
}

void denxanhD3sangtruoc(){
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis <= 12000) {
    /*----------Lượt đèn sáng 1----------*/
    //d4, d3 sáng; d1, d2 tắt; d5, d6 tắt
    digitalWrite(d4, HIGH);
    digitalWrite(d3, HIGH);
    digitalWrite(d1, LOW);
    digitalWrite(d2, LOW);
    digitalWrite(d5, LOW);
    digitalWrite(d6, LOW);
    //d7, d12 sáng; d10, d11 tắt; d8, d9 tắt
    digitalWrite(d7, HIGH);
    digitalWrite(d12, HIGH);
    digitalWrite(d10, LOW);
    digitalWrite(d11, LOW);
    digitalWrite(d8, LOW);
    digitalWrite(d9, LOW);
  }else if(currentMillis - previousMillis <= 15000){
    /*----------Lượt đèn sáng 2----------*/
    //d4, d2 sáng; d1, d3 tắt; d5, d6 tắt
    digitalWrite(d4, HIGH);
    digitalWrite(d2, HIGH);
    digitalWrite(d1, LOW);
    digitalWrite(d3, LOW);
    digitalWrite(d5, LOW);
    digitalWrite(d6, LOW);
    //d7, d11 sáng; d10, d12 tắt; d8, d9 tắt
    digitalWrite(d7, HIGH);
    digitalWrite(d11, HIGH);
    digitalWrite(d10, LOW);
    digitalWrite(d12, LOW);
    digitalWrite(d8, LOW);
    digitalWrite(d9, LOW);
  }else if(currentMillis - previousMillis <= 27000){
    /*----------Lượt đèn sáng 3----------*/
    //d1, d6 sáng; d2, d3 tắt; d4, d5 tắt
    digitalWrite(d1, HIGH);
    digitalWrite(d6, HIGH);
    digitalWrite(d2, LOW);
    digitalWrite(d3, LOW);
    digitalWrite(d4, LOW);
    digitalWrite(d5, LOW);
    //d10, d9 sáng; d11, d12 tắt; d7, d8 tắt
    digitalWrite(d10, HIGH);
    digitalWrite(d9, HIGH);
    digitalWrite(d11, LOW);
    digitalWrite(d12, LOW);
    digitalWrite(d7, LOW);
    digitalWrite(d8, LOW);
  }else if(currentMillis - previousMillis <= 30000){
    /*----------Lượt đèn sáng 4----------*/
    //d1, d5 sáng; d2, d3 tắt; d4, d6 tắt
    digitalWrite(d1, HIGH);
    digitalWrite(d5, HIGH);
    digitalWrite(d2, LOW);
    digitalWrite(d3, LOW);
    digitalWrite(d4, LOW);
    digitalWrite(d6, LOW);
    //d10, d8 sáng; d11, d12 tắt; d7, d9 tắt
    digitalWrite(d10, HIGH);
    digitalWrite(d8, HIGH);
    digitalWrite(d11, LOW);
    digitalWrite(d12, LOW);
    digitalWrite(d7, LOW);
    digitalWrite(d9, LOW);
  }else{
    previousMillis=currentMillis;
  }
}
void denxanhD6sangtruoc(){
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis <= 12000) {
    /*----------Lượt đèn sáng 1----------*/
    //d1, d6 sáng; d2, d3 tắt; d4, d5 tắt
    digitalWrite(d1, HIGH);
    digitalWrite(d6, HIGH);
    digitalWrite(d2, LOW);
    digitalWrite(d3, LOW);
    digitalWrite(d4, LOW);
    digitalWrite(d5, LOW);
    //d10, d9 sáng; d11, d12 tắt; d7, d8 tắt
    digitalWrite(d10, HIGH);
    digitalWrite(d9, HIGH);
    digitalWrite(d11, LOW);
    digitalWrite(d12, LOW);
    digitalWrite(d7, LOW);
    digitalWrite(d8, LOW);
  }else if(currentMillis - previousMillis <= 15000){
    /*----------Lượt đèn sáng 2----------*/
    //d5, d1 sáng; d2, d3 tắt; d4, d6 tắt
    digitalWrite(d5, HIGH);
    digitalWrite(d1, HIGH);
    digitalWrite(d2, LOW);
    digitalWrite(d3, LOW);
    digitalWrite(d4, LOW);
    digitalWrite(d6, LOW);
    //d8, d10 sáng; d11, d12 tắt; d7, d9 tắt
    digitalWrite(d8, HIGH);
    digitalWrite(d10, HIGH);
    digitalWrite(d11, LOW);
    digitalWrite(d12, LOW);
    digitalWrite(d7, LOW);
    digitalWrite(d9, LOW);
  }else if(currentMillis - previousMillis <= 27000){
    /*----------Lượt đèn sáng 3----------*/
    //d3, d4 sáng; d1, d2 tắt; d5, d6 tắt
    digitalWrite(d3, HIGH);
    digitalWrite(d4, HIGH);
    digitalWrite(d1, LOW);
    digitalWrite(d2, LOW);
    digitalWrite(d5, LOW);
    digitalWrite(d6, LOW);
    //d12, d7 sáng; d10, d11 tắt; d8, d9 tắt
    digitalWrite(d12, HIGH);
    digitalWrite(d7, HIGH);
    digitalWrite(d10, LOW);
    digitalWrite(d11, LOW);
    digitalWrite(d8, LOW);
    digitalWrite(d9, LOW);
  }else if(currentMillis - previousMillis <= 30000){
    /*----------Lượt đèn sáng 4----------*/
    //d4, d2 sáng; d1, d3 tắt; d5, d6 tắt
    digitalWrite(d4, HIGH);
    digitalWrite(d2, HIGH);
    digitalWrite(d1, LOW);
    digitalWrite(d3, LOW);
    digitalWrite(d5, LOW);
    digitalWrite(d6, LOW);
    //d7, d11 sáng; d10, d12 tắt; d8, d9 tắt
    digitalWrite(d7, HIGH);
    digitalWrite(d11, HIGH);
    digitalWrite(d10, LOW);
    digitalWrite(d12, LOW);
    digitalWrite(d8, LOW);
    digitalWrite(d9, LOW);
  }else{
    previousMillis=currentMillis;
  }
}

Chương trình dùng định thời với hàm millis() để bật, tắt đèn. Không dùng hàm delay() vì nó dừng cả chương trình, lúc đó bấm nút sẽ không có tác dụng.

Bên dưới là video demo điều khiển đèn giao thông với Arduino.

Tác giả

HV Lee

500+ bài viết về lập trình, phần cứng, mạng máy tính và công nghệ. Chia sẻ kiến thức từ những gì đã học, đã dạy và đã trải nghiệm — để người học CNTT hiểu sâu hơn và làm được nhiều hơn.

Gợi ý tiếp theo

Cài đặt Python và môi trường lập trình với Visual Studio Code

Học tiếp