交通灯状态机
本课属于 Coddy Arduino 学习旅程的“无需 delay 的计时”单元。第 10 课,共 18 课。
交通信号灯是一种状态机:它始终处于一种状态(绿色、黄色或红色),每种状态持续一段固定时间,并且每种状态都知道接下来会进入哪种状态:
- GREEN:绿灯亮;2 s 后,切换到 YELLOW
- YELLOW:黄灯亮;1 s 后,切换到 RED
- RED:红灯亮;2 s 后,切换到 GREEN
每一行对应一个 case:
case GREEN:
setLights(HIGH, LOW, LOW);
if (now - lightStart >= 2000) {
light = YELLOW;
lightStart = now;
}
break;使用 delay(2000),信号灯也能正常工作,但其他任务都无法运行。使用 millis() 时,每次执行 loop() 只需几微秒,因此电路板有时间处理其他任务:这里的其他任务是让状态 LED 一直闪烁,以显示控制器正在运行。
挑战
中等引脚 13 上的状态 LED 已经在闪烁,enum 和 lightStart 也已准备好。使用 switch (light) 编写交通灯逻辑,每种灯对应一个 case:
- 绿灯 2 s,黄灯 1 s,红灯 2 s,然后再次亮起绿灯
- 每次只亮一盏 LED,使用
setLights() - 不要使用
delay(),这样状态 LED 就能继续闪烁
点击 运行,然后点击 检查。
亲手试试
const int greenLed = 10;
const int yellowLed = 11;
const int redLed = 12;
const int statusLed = 13; // 开发板自带的 LED
enum Light { GREEN, YELLOW, RED };
Light light = GREEN;
unsigned long lightStart = 0; // 当前灯亮起的时间
unsigned long statusPrevious = 0;
int statusState = LOW;
void setup() {
pinMode(greenLed, OUTPUT);
pinMode(yellowLed, OUTPUT);
pinMode(redLed, OUTPUT);
pinMode(statusLed, OUTPUT);
}
void setLights(int green, int yellow, int red) {
digitalWrite(greenLed, green);
digitalWrite(yellowLed, yellow);
digitalWrite(redLed, red);
}
void loop() {
unsigned long now = millis();
// 状态 LED 每隔 250 ms 切换一次,表示控制器正在运行
if (now - statusPrevious >= 250) {
statusPrevious = now;
if (statusState == LOW) {
statusState = HIGH;
} else {
statusState = LOW;
}
digitalWrite(statusLed, statusState);
}
// 交通信号灯:用 switch(light)为每种灯设置一个 case
// 绿灯亮 2 s,黄灯亮 1 s,红灯亮 2 s,然后再次亮绿灯
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
无需 delay 的计时中的所有课
自己练习: Arduino 在线编辑器