You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 12:40:13