遅延なしで点滅
CoddyのArduinoジャーニー「delayを使わないタイミング制御」セクションの一部。レッスン 3/18。
delay()はスケッチ全体を停止します。点滅のために500 ms待っている間、loop()内のほかの処理は何も実行されません。その間にボタンが押されても、待ち時間が終わるまで検知されません。
解決策は、決して待たないことです。loop()を何度も非常に速く実行し、そのたびに現在時刻とLEDが最後に切り替わった時刻を比較します。500 msが経過するまでは何もしません。その後、LEDを切り替えて新しい時刻を保存します:
const unsigned long interval = 500;
unsigned long previousMillis = 0; // LEDが最後に切り替わったとき
void loop() {
unsigned long now = millis();
if (now - previousMillis >= interval) {
previousMillis = now; // この時点を記録する
// ここでLEDを切り替える
}
// ここに書いたほかの処理は1秒間に数千回実行される
}now - previousMillisは、最後に切り替わってからの経過時間です。LEDを切り替えるには、状態をint redState = LOW;のように変数に保持し、if/elseで反転させて、digitalWrite(redLed, redState);で書き込みます。
previousMillisの更新を忘れると、最初の500 msが経過した後も条件がtrueのままになり、LEDはループのたびに切り替わって、半分点灯しているように見えます。
チャレンジ
中級黄色の LED はボタンに連動するはずですが、赤色 LED の delay() 呼び出しによってループが停止するため、反応が遅れます。millis() を使って赤色 LED の点滅を書き換えましょう。
- ボタンの部分はそのままにする
- 500 ms ごとに、13 番ピンの赤色 LED のオン/オフを切り替える
delay()はどこにも使わない
Run を押し、ボタンを押したまま両方の LED を確認してから、Check を押してください。
自分で試してみよう
const int redLed = 13;
const int yellowLed = 12;
const int buttonPin = 2;
void setup() {
pinMode(redLed, OUTPUT);
pinMode(yellowLed, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
}
void loop() {
// 黄色のLEDはボタンの状態に連動します。この部分は残してください。
if (digitalRead(buttonPin) == LOW) {
digitalWrite(yellowLed, HIGH);
} else {
digitalWrite(yellowLed, LOW);
}
// 赤色のLEDは点滅しますが、各delay()によって上の行の処理が
// 0.5秒間止まります。この部分をmillis()を使って書き直してください。
digitalWrite(redLed, HIGH);
delay(500);
digitalWrite(redLed, LOW);
delay(500);
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
delayを使わないタイミング制御のすべてのレッスン
自分で練習してみよう: Arduinoプレイグラウンド