// 🚦 ATmega2560 交通號誌 + 七段顯示器倒數顯示// 修正版:修復自動模式卡住不循環的問題
// ---- LED 腳位設定 ----int TG1 = 24, TY1 = 23, TR1 = 22;int TG2 = 27, TY2 = 26, TR2 = 25;
// ---- 按鈕 ----int sw1 = 30, sw2 = 31, sw3 = 32, sw4 = 33;
// ---- 七段顯示器腳位(A~G)----int segPins[7] = {38, 39, 40, 41, 42, 43, 44};
// 七段顯示數字對應表 (共陰)byte numbers[10][7] = { {0,0,0,0,0,0,1}, //0 {1,0,0,1,1,1,1}, //1 {0,0,1,0,0,1,0}, //2 {0,0,0,0,1,1,0}, //3 {1,0,0,1,1,0,0}, //4 {0,1,0,0,1,0,0}, //5 {0,1,0,0,0,0,0}, //6 {0,0,0,1,1,1,1}, //7 {0,0,0,0,0,0,0}, //8 {0,0,0,0,1,0,0} //9};
// ---- 系統控制變數 ----unsigned long previousMillis = 0;unsigned long displayMillis = 0;int mode = 1; // 預設自動模式int state = 0; // 自動循環階段int subState = -1; // 協助每個 state 初始化使用int countdown = 0; // 倒數秒數bool blinkState = false;
// ---- 時間設定 ----int greenTime = 6; // 綠燈秒數int yellowTime = 2; // 黃燈秒數
void setup() { // 設定輸出腳 pinMode(TG1, OUTPUT); pinMode(TY1, OUTPUT); pinMode(TR1, OUTPUT); pinMode(TG2, OUTPUT); pinMode(TY2, OUTPUT); pinMode(TR2, OUTPUT);
for (int i = 0; i < 7; i++) pinMode(segPins[i], OUTPUT);
// 設定輸入腳(含上拉) pinMode(sw1, INPUT_PULLUP); pinMode(sw2, INPUT_PULLUP); pinMode(sw3, INPUT_PULLUP); pinMode(sw4, INPUT_PULLUP);
allOff(); showNumber(0);}
void loop() { // 按鈕控制模式(不含防彈跳,建議日後加入) if (digitalRead(sw1) == HIGH) mode = 1; if (digitalRead(sw2) == HIGH) mode = 2; if (digitalRead(sw3) == HIGH) mode = 3; if (digitalRead(sw4) == HIGH) mode = 4;
switch (mode) { case 1: autoCycle(); break; case 2: blinkMode(); break; case 3: manualMode(); break; case 4: allOff(); showNumber(0); break; }}
// 🟢 模式 1:自動循環 + 倒數顯示void autoCycle() { unsigned long currentMillis = millis();
// 每秒更新倒數顯示 if (currentMillis - displayMillis >= 1000) { displayMillis = currentMillis; if (countdown > 0) countdown--; showNumber(countdown); }
switch (state) { case 0: // 方向1綠燈 + 方向2紅燈 if (subState != 0) { allOff(); digitalWrite(TG1, HIGH); digitalWrite(TR2, HIGH); countdown = greenTime; previousMillis = currentMillis; subState = 0; } if (currentMillis - previousMillis >= greenTime * 1000UL) { digitalWrite(TG1, LOW); digitalWrite(TY1, HIGH); countdown = yellowTime; previousMillis = currentMillis; state = 1; subState = -1; } break;
case 1: // 方向1黃燈 if (currentMillis - previousMillis >= yellowTime * 1000UL) { digitalWrite(TY1, LOW); digitalWrite(TR2, LOW); digitalWrite(TR1, HIGH); digitalWrite(TG2, HIGH); countdown = greenTime; previousMillis = currentMillis; state = 2; subState = -1; } break;
case 2: // 方向2綠燈 + 方向1紅燈 if (subState != 2) { countdown = greenTime; previousMillis = currentMillis; subState = 2; } if (currentMillis - previousMillis >= greenTime * 1000UL) { digitalWrite(TG2, LOW); digitalWrite(TY2, HIGH); countdown = yellowTime; previousMillis = currentMillis; state = 3; subState = -1; } break;
case 3: // 方向2黃燈 if (currentMillis - previousMillis >= yellowTime * 1000UL) { digitalWrite(TY2, LOW); digitalWrite(TR1, LOW); state = 0; subState = -1; } break; }}
// ⚠️ 模式 2:閃燈警示void blinkMode() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= 500) { previousMillis = currentMillis; blinkState = !blinkState; digitalWrite(TY1, blinkState); digitalWrite(TY2, !blinkState); } showNumber(0);}
// 🚗 模式 3:手動放行void manualMode() { allOff(); digitalWrite(TR1, HIGH); digitalWrite(TG2, HIGH); showNumber(0);}
// 🛑 模式 4:全部熄滅void allOff() { digitalWrite(TG1, LOW); digitalWrite(TY1, LOW); digitalWrite(TR1, LOW); digitalWrite(TG2, LOW); digitalWrite(TY2, LOW); digitalWrite(TR2, LOW);}
// 🧮 顯示數字到七段顯示器void showNumber(int num) { if (num < 0 || num > 9) num = 0; for (int i = 0; i < 7; i++) { digitalWrite(segPins[i], numbers[num][i] ? HIGH : LOW); }}