enumで状態に名前を付ける
CoddyのArduinoジャーニー「delayを使わないタイミング制御」セクションの一部。レッスン 9/18。
0、1、2と番号を付けたモードでも動作しますが、if (mode == 2)では2が何を意味するのか分かりません。enumを使うと、それぞれの数値に名前を付けられます。
enum State { READY, RUNNING, DONE };
State state = READY;1行目では、新しい型Stateを作成します。この型が取りうる値はREADY、RUNNING、DONEだけです。内部では引き続き0、1、2ですが、名前を見るとそれぞれが何を意味するか分かります。2行目では、その型の変数を作成します。
enumとswitchは相性がよく、各状態に1つずつcaseを用意します。
switch (state) {
case READY:
// READYが行うことと、次の状態に移るタイミング
break;
case RUNNING:
// ...
break;
}新しい状態に移るには、stateを設定し、その状態が始まった時刻を記録します。state = DONE; stateStart = millis();。その後、各状態はmillis() - stateStartを使って、それぞれの経過時間を計ります。このようなスケッチの書き方をステートマシンと呼びます。
チャレンジ
中級マシンには3つの状態があります。READYは用意されています。緑色のLEDが点灯し、ボタンを押すとマシンが起動します。残りの2つのケースを追加してください。
RUNNING:黄色のLEDが点灯します。2000 ms後に消灯し、DONEに移行します。DONE:赤色のLEDが点灯します。1000 ms後に消灯し、READYに戻ります。
状態が変わるたびにstateStartを保存してください。Runを押し、ボタンを押してから、Checkを押してください。
自分で試してみよう
const int buttonPin = 2;
const int greenLed = 10;
const int yellowLed = 11;
const int redLed = 12;
enum State { READY, RUNNING, DONE };
State state = READY;
unsigned long stateStart = 0; // 現在の状態が始まった時刻
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(greenLed, OUTPUT);
pinMode(yellowLed, OUTPUT);
pinMode(redLed, OUTPUT);
}
void loop() {
unsigned long now = millis();
switch (state) {
case READY:
digitalWrite(greenLed, HIGH);
if (digitalRead(buttonPin) == LOW) {
digitalWrite(greenLed, LOW);
state = RUNNING;
stateStart = now;
}
break;
// case RUNNING を追加:黄色のLEDを点灯し、2000 ms 後に消灯して DONE に移る
// case DONE を追加:赤色のLEDを点灯し、1000 ms 後に消灯して READY に戻る
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
delayを使わないタイミング制御のすべてのレッスン
自分で練習してみよう: Arduinoプレイグラウンド