ループでは見逃すボタン押下
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も使わないでください。
チャレンジ
簡単このアラームは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);
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
delayを使わないタイミング制御のすべてのレッスン
自分で練習してみよう: Arduinoプレイグラウンド