Menu
CoddyTech

ループでは見逃すボタン押下

CoddyのArduinoジャーニー「delayを使わないタイミング制御」セクションの一部。レッスン 12/18。

スケッチは、時間のかかる処理や長いdelay()の実行中に、ほかの処理ができないことがあります。処理の合間にだけボタンを読み取るループでは、その間に始まって終わった押下を見逃します。

割り込みを使えば解決できます。ピンの状態が変化すると、ボードはいま行っている処理を中断し、指定した関数を実行してから処理を再開します。チップはdelay()の実行中も、ピンの状態を自ら監視します。

void onPress() {
  digitalWrite(ledPin, HIGH);
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), onPress, FALLING);
}

attachInterrupt()には3つのものを渡します。ピンに対応する割り込み(digitalPinToInterrupt(buttonPin)で取得します)、実行する関数、そして実行するタイミングです。FALLINGはピンがHIGHからLOWになる瞬間です。プルアップを使っている場合、ボタンを押した瞬間にあたります。

この関数は割り込みサービスルーチン(ISR)と呼ばれます。短く保ちましょう。delay()もSerialも使わないでください。

challenge icon

チャレンジ

簡単

このアラームは2秒ごとに一度しかボタンを確認しないため、素早く押すと見逃してしまいます。ボタンを押したらすぐにLEDが点灯するようにしてください。

  • LEDを点灯させるISR onPress() を作成します
  • setup() で、FALLING を使ってボタンのピンに割り込みを設定します

時間のかかる処理は loop() に残します。アラームのように、ボタンを押した後もLEDは点灯したままです。Run を押し、ボタンをタップしてから、Check を押してください。

自分で試してみよう

const int ledPin = 13;
const int buttonPin = 2;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
  // ここで割り込みを設定する
}

void loop() {
  // 時間のかかる処理:そのままにしておく
  Serial.println("working");
  delay(2000);

  // これではボタンを2秒に1回しか確認しないため、
  // 短く押すと検出されない
  if (digitalRead(buttonPin) == LOW) {
    digitalWrite(ledPin, HIGH);
  }
}
quiz icon腕試し

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

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

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