ボタンでモードを切り替える
CoddyのArduinoジャーニー「delayを使わないタイミング制御」セクションの一部。レッスン 11/18。
多くのガジェットには、押すたびにモードが切り替わるボタンが1つあります。自転車のライトなら、消灯、点灯、点滅、高速点滅、そして再び消灯と切り替わります。これは、時計ではなくボタンを押すことで次の状態に移る状態機械です。
切り替え処理を独立した関数にします。現在のモードに対するswitchで次のモードを設定し、最後のモードから最初のモードに戻します。
void nextMode() {
switch (mode) {
case OFF:
mode = ON;
Serial.println("ON");
break;
// ... 以下同様に続き、FAST から OFF に戻るまで
}
}スケッチはボタンを押すたびにnextMode()を1回呼び出します。ボタンのチャタリング除去は、Inputsセクションで学んだ方法で行います。読み取り値が変化したら処理し、その後、接点が安定するまで20 ms待ちます。modeに対する2つ目のswitchでLEDを設定します。
チャレンジ
中級ボタンとLEDのコードは用意されています。ボタンを押すたびに次のモードに切り替わり、その名前を出力するようにnextMode()を作成してください。順番はOFF、ON、BLINK、FASTで、その後は再びOFFになります。
Runを押し、ボタンを数回押してから、Checkを押してください。
自分で試してみよう
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() {
// 各モードに1つのcaseを設ける:次のモードを設定し、名前を出力して、breakする
}
// interval msごとに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プレイグラウンド