Arduino交通灯代码循环一次后不同步,如何实现无限循环?
Arduino交通灯代码同步问题修复
问题根源
你的代码使用多个独立的时间追踪变量(start、start_middle等),每个状态条件独立判断,没有状态流转逻辑。第一次循环后,各变量累加值相互偏移,导致多个状态被同时触发,出现灯效不同步的问题。
修复方案:状态机实现
改用状态机模式,通过单个时间变量跟踪状态切换节点,按顺序流转各个灯效状态,确保无限循环时的同步性:
int RED = 13; int YELLOW = 12; int GREEN = 11; // 定义每个状态的持续时间(毫秒) const unsigned long RED_DURATION = 5000; const unsigned long RED_YELLOW_DURATION = 2000; const unsigned long GREEN_DURATION = 10000; const unsigned long YELLOW_DURATION = 2000; // 定义交通灯状态枚举 enum TrafficLightState { STATE_RED, STATE_RED_YELLOW, STATE_GREEN, STATE_YELLOW }; TrafficLightState currentState = STATE_RED; unsigned long previousMillis = 0; void print_time(unsigned long time_millis); void setup() { Serial.begin(9600); pinMode(RED, OUTPUT); pinMode(YELLOW, OUTPUT); pinMode(GREEN, OUTPUT); // 初始状态设为红灯 digitalWrite(RED, HIGH); digitalWrite(YELLOW, LOW); digitalWrite(GREEN, LOW); } void loop() { unsigned long currentMillis = millis(); switch(currentState) { case STATE_RED: if (currentMillis - previousMillis >= RED_DURATION) { // 切换到红黄灯状态 previousMillis = currentMillis; currentState = STATE_RED_YELLOW; digitalWrite(RED, HIGH); digitalWrite(YELLOW, HIGH); digitalWrite(GREEN, LOW); print_time(RED_DURATION); Serial.println("Get Ready!!"); } break; case STATE_RED_YELLOW: if (currentMillis - previousMillis >= RED_YELLOW_DURATION) { // 切换到绿灯状态 previousMillis = currentMillis; currentState = STATE_GREEN; digitalWrite(RED, LOW); digitalWrite(YELLOW, LOW); digitalWrite(GREEN, HIGH); print_time(RED_YELLOW_DURATION); Serial.println("START!!"); } break; case STATE_GREEN: if (currentMillis - previousMillis >= GREEN_DURATION) { // 切换到黄灯状态 previousMillis = currentMillis; currentState = STATE_YELLOW; digitalWrite(RED, LOW); digitalWrite(YELLOW, HIGH); digitalWrite(GREEN, LOW); print_time(GREEN_DURATION); Serial.println("END OF LINE!!"); } break; case STATE_YELLOW: if (currentMillis - previousMillis >= YELLOW_DURATION) { // 切换回红灯状态,完成循环 previousMillis = currentMillis; currentState = STATE_RED; digitalWrite(RED, HIGH); digitalWrite(YELLOW, LOW); digitalWrite(GREEN, LOW); print_time(YELLOW_DURATION); Serial.println("STOP!"); } break; } } void print_time(unsigned long time_millis){ Serial.print("Time: "); Serial.print(time_millis/1000); Serial.print("s - "); }
关键改动说明
- 用
TrafficLightState枚举明确区分每个灯效阶段,避免逻辑混乱 - 单个
previousMillis变量统一记录状态切换的时间点,确保各状态时间基准一致 - 状态按
红灯→红黄灯→绿灯→黄灯→红灯的顺序循环流转,保证同步性 - 移除了
exit(0)终止语句,程序会无限循环执行正确的灯效逻辑 - 重新计算了每个状态的实际持续时间(原代码中的
dley变量是累计时间,这里改为单个状态的持续时长,更符合逻辑)
内容的提问来源于stack exchange,提问作者Teriell
相关产品推荐
相关产品推荐

