用按钮切换模式
本课属于 Coddy Arduino 学习旅程的“无需 delay 的计时”单元。第 11 课,共 18 课。
许多小设备只有一个按钮,用来依次切换模式:自行车灯依次熄灭、亮起、闪烁、快速闪烁,然后再次熄灭。这是一种状态机,按下按钮而不是等待时钟,就会切换到下一个状态。
把切换步骤放在单独的函数中。根据当前模式使用 switch 设置下一个模式,最后一个模式会回到第一个模式:
void nextMode() {
switch (mode) {
case OFF:
mode = ON;
Serial.println("ON");
break;
// ……以此类推,直到 FAST 重新切换为 OFF
}
}草图会在每次按下按钮时调用一次 nextMode()。按钮的消抖方式和你在“输入”单元中学的一样:读数变化时执行操作,然后等待 20 ms,让触点稳定下来。另一个针对 mode 的 switch 会设置 LED。
挑战
中等按钮和 LED 的代码已经为你写好。编写 nextMode(),让每次按下按钮都切换到下一个模式,并输出它的名称:OFF、ON、BLINK、FAST,然后再次回到 OFF。
按“运行”,按几次按钮,然后按“检查”。
亲手试试
const int ledPin = 13;
const int buttonPin = 2;
enum Mode { OFF, ON, BLINK, FAST };
Mode mode = OFF;
bool wasPressed = false;
unsigned long blinkPrevious = 0;
int ledState = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(9600);
}
// 切换到下一个模式并打印其名称。
void nextMode() {
// 每个模式对应一个 case:设置下一个模式,打印其名称,然后执行 break。
}
// 每隔 interval 毫秒切换一次 LED 状态。
void blinkEvery(unsigned long interval) {
unsigned long now = millis();
if (now - blinkPrevious >= interval) {
blinkPrevious = now;
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}
void loop() {
// 1. 按下按钮(消抖后)会调用 nextMode()
bool pressed = digitalRead(buttonPin) == LOW;
if (pressed != wasPressed) {
if (pressed) {
nextMode();
}
wasPressed = pressed;
delay(20); // 等待触点稳定
}
// 2. 模式决定 LED 的行为
switch (mode) {
case OFF:
digitalWrite(ledPin, LOW);
break;
case ON:
digitalWrite(ledPin, HIGH);
break;
case BLINK:
blinkEvery(500);
break;
case FAST:
blinkEvery(100);
break;
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
无需 delay 的计时中的所有课
自己练习: Arduino 在线编辑器