Menu
CoddyTech

信号機の状態機械

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を使います。

challenge icon

チャレンジ

中級

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点灯し、再び緑に戻る
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

delayを使わないタイミング制御のすべてのレッスン

自分で練習してみよう: Arduinoプレイグラウンド