信号機の状態機械
CoddyのArduinoジャーニー「delayを使わないタイミング制御」セクションの一部。レッスン 10/18。
信号機は状態機械です。常に1つの状態(緑、黄、または赤)にあり、各状態は決まった時間続き、次にどの状態へ進むかが決まっています。
- GREEN:緑色を点灯。2 s後にYELLOWへ進む
- YELLOW:黄色を点灯。1 s後にREDへ進む
- RED:赤色を点灯。2 s後にGREENへ進む
各行は1つの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も準備できています。信号機を、ライトごとに1つのcaseを持つswitch (light)として書いてください。
- 緑は2秒、黄色は1秒、赤は2秒、その後また緑
setLights()を使って、一度に点灯するLEDは1つだけdelay()は使わず、ステータスLEDの点滅を続ける
Runを押してから、Checkを押してください。
自分で試してみよう
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);
}
// 信号機:各ライトに1つずつcaseを持つswitch (light)
// 緑が2 s、黄が1 s、赤が2 s点灯し、再び緑に戻る
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
delayを使わないタイミング制御のすべてのレッスン
自分で練習してみよう: Arduinoプレイグラウンド