このチュートリアルでは、delay()
関数を適切に使用して、Arduinoプログラムの2つのアクションの間に遅延を追加する方法を学びます。 次に、プログラムを拡張したいときにdelay()
を使用することがしばしば良い考えではない理由と、それを修正する方法を発見します。
よし、始めよう!
目次
Arduinoプログラムに遅延が必要なのはなぜですか?
まあ、Arduinoプログラムは外部入力/出力に大きく依存して動作します。
簡単な例を取ると、プッシュボタンの状態を毎秒100回監視したり、0.5秒ごとにLEDを点滅させたりすることができます。
さて、どうすればそれを達成できますか? Arduinoプログラムは次のように動作します:
- まず、
setup()
関数が一度実行されます。 - その後、Arduinoの電源を切るまで、
loop()
関数が何度も何度も実行されます。
あなたが書いたプログラムはすべてフルスピードで実行されます。 したがって、コードでLEDを点滅させている場合、LEDが非常に高い速度で点滅することが起こります(少なくとも1秒あたり数千回)。
あなた自身のプロジェクトを構築するためにArduinoを使用する方法を学んでいますか?
初心者のためのArduinoをチェックして、ステップバイステップを学びます。
時間を制御したい場合、つまり、LEDが0.5秒ごとに点滅し、フルスピードではないことを確認してください–コードに遅延を追加する必要があります。
あなたのコードにArduinoの遅延を実装
Arduinoの遅延()関数
ここでは、LEDを点滅させるコードです(ここでは内蔵LEDを選択し、外部LEDを追加する必要はありません)0.5秒ごとに-これはArduinoで始める場合に表示される最も一般的な例の一つです。
#define LED_PIN 13void setup() { pinMode(LED_PIN, OUTPUT);}void loop() { digitalWrite(LED_PIN, HIGH); delay(500); digitalWrite(LED_PIN, LOW); delay(500);}
だから、このコードはどのように動作しますか?
最初に”define”を使用するので、コード内で数”13″を複数回ハードコードする必要がなく、プログラムを読みやすくします。
pinMode()
機能で出力する端子のモードを設定します。
次に、loop()
関数では、次のようになります。:
- LEDの電源を入れる
-
delay(500)
を使用して500ミリ秒、または0.5秒間スリープ状態にする - LEDの電源をオフにする
-
delay(500)
を使用して0.5秒間スリープ状態にする -
loop()
関数が何度も実行され続けるため、ステップ1に戻ります。
delay()
関数は、スリープに秒ではなくミリ秒の数を与えることを期待しています。 だから、あなたが数秒で考えるならば、その数に1000を掛けて、あなたはあなたが必要とする価値を持っています。
Arduinoを1分間遅延させる
Arduinoを1分間、または複数分間スリープさせたい場合は、非常に簡単です。
分数を取り、60を掛けて秒数を取得し、1000を掛けてミリ秒数を取得します。
Ex:delay(3 * 60 * 1000);
はプログラムを3分間スリープさせます。
Arduino delayMicroseconds()関数
より正確にする必要がある場合は、delayMicroseconds()
関数を使用する必要があります。 delayMicroseconds()
を使用すると、スリープにマイクロ秒の数を提供することができます。 delay()
の最小持続時間は1ミリ秒なので、400マイクロ秒だけスリープする必要がある場合は、ここで新しい解決策があります。
この関数は、いくつかのハードウェアコンポーネントと通信するときに非常に便利です。 たとえば、Arduinoはコンポーネントにデータを送信してから、応答を読み取る必要があります。 コンポーネントが要求を処理し、正確なデータを提供するために6マイクロ秒が必要とするとします。
次に、あなたのプログラムでは、次のようなものがあるかもしれません:
...void loop() { // send data to component delayMicroseconds(6); // reach out to component again to read data}
非ブロッキング遅延–delay()
を使用しない理由arduinoの遅延とは何か、delay()
とdelayMicroseconds()
で実装する方法を理解したので、遅延機能を使用する方法を見てみましょう。
なぜ?
delay()
を使用すると、プログラムの実行が停止し、遅延が終了した後にのみ再開されます。
これは、実行するアクションが1つだけの場合は問題ありません–例: 単一のLEDを点滅させる-しかし、あなたは、複数のハードウェアコンポーネントの世話をするか、そのようなArduinoのボードや自分のコンピュータなどの他のデバ
前の例を使用して、1つのLEDを0.5秒ごとに点滅させ、別のLEDを0.8秒ごとに点滅させるにはどうすればよいですか?
その場合、あなたは非常に迅速に立ち往生します。 それでもdelay()
を使用したい場合は、複数のアクションの間でより短い遅延を使用する解決策を見つけることができますが、これにより、新しいアクショその解決策は、単純にdelay()
関数を使用せずに時間を監視し、基本的にはdelay()
の動作を使用せずに再現する方法を見つけることです。
コード例–arduino delay without delay()
delay()
を使用せずにblink LEDの例を書き直しましょう。
#define LED_PIN 13unsigned int lastTimeLedBlinked = millis();unsigned int delayBetweenBlink = 500;byte ledState = LOW;void setup() { pinMode(LED_PIN, OUTPUT);}void loop() { unsigned int timeNow = millis(); if (timeNow - lastTimeLedBlinked > delayBetweenBlink) { if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } digitalWrite(LED_PIN, ledState); lastTimeLedBlinked = timeNow; }}
このコードを行ごとに分析してみましょう。
初期化
#define LED_PIN 13unsigned int lastTimeLedBlinked = millis();unsigned int delayBetweenBlink = 500;byte ledState = LOW;
まず、グローバルスコープ内の3つの変数を初期化します:
- lastTimeLedBlinked:この変数は、LEDが最後に点滅した時間を格納するために使用されます。 基本的に、LEDを点滅させるたびに、millis()関数を使用して、この変数を現在の時刻で更新します。
- delayBetweenBlink:これは2つのアクションの間で待機したい時間です。
- ledState:現在のLEDの状態(HIGHまたはLOW)を保存して、前の状態が何であったかを知ることができ、それに応じてアクションを実行する必要があります。
なぜグローバルスコープにあるのですか? さて、私たちがやろうとしているのは、loop()
関数でこれらの変数を更新し、次にloop()
内に入るときにそれらに再度アクセスすることです。 loop()
内に変数を作成すると、変数はローカル変数になるため、loop()
関数を終了すると破棄されます。 したがって、次回loop()
が再び呼び出されると、すべての値が失われ、以前の値が含まれていない変数が再び作成されます。 ここでは、関数の外側に変数を作成することで、loop()
を入力するたびに変数を「生き残る」ようにし、その値を保持できます。
ループ関数でのArduinoの遅延機能の実装
さて、loop()
関数で何が起こるかを見てみましょう。
void loop() { unsigned int timeNow = millis();
まず、millis()
関数で現在の時刻を読み取ります。
if (timeNow - lastTimeLedBlinked > delayBetweenBlink) {
そして今、あなたは今読んだ現在の時刻を、前回のLEDが点滅した時刻と比較します。 十分な時間が経過した場合(delayBetweenBlinkに格納されている値よりも多い場合)、if()
を入力できることを意味します。
このコード構造–時間を読み取り、それを前回のアクションを実行した時間と比較する–は、delay()
関数をどのように置き換えるかです。 基本的には、ここで期間を計算しています。 そして、あなたが見ることができるように、それはあなたのプログラムが単純なアプリケーションのためのより多くの行を含むことを意味しますが、
だから、何が起こるのだろうか? まあ、loop()
はフルスピードで実行され続けます。 毎回、プログラムは十分な時間が経過したかどうかをチェックします。 そうでない場合、loop()
はif構造体に入らないため、ここで終了します。
そして、ちょうど十分な時間が経過したとき、我々はif()
を入力します。
アクションを実行する
if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } digitalWrite(LED_PIN, ledState);
OK、あなたはちょうどif()
を入力しました、そしてこれはあなたがする必要があるどんなアクションをするでしょう。
ここではLEDを点滅させます。 また、LEDの以前の状態が何であったかを直接知ることができないため(loop()
を何度も入力し、内部で作成されたすべてのローカル変数を失ったため)、その状
このグローバル変数を使って行うことは簡単です:低ければHIGHに設定し、高ければLOWに設定します。 そして、もちろん、それに応じて物理的なLEDの状態をdigitalWrite()
で更新します。最後に、これは非常に重要ですが、現在の時刻を最後にLEDを点滅させた時刻として保存します。 そうしないと、if()
内の条件は常にtrueになるため、プログラムはLEDをフルスピードで点滅させます。
前回の時刻を現在の時刻に設定することで、”タイマーをリセット”します。
したがって、この例では、if()
は500ミリ秒ごと、つまり0.5秒ごとにのみ入力されます。
そして今、あなたのプログラムが停止しないので、これは素晴らしいことですので、LEDを点滅させるのを”待っている”間に、さまざまな独立したアクショ
2つのアクション”同時に”
例えば、0ごとにLEDを点滅させたいとしましょう。5秒、および別のものは0.8秒毎に。
#define LED_1_PIN 13#define LED_2_PIN 10unsigned int lastTimeLed1Blinked = millis();unsigned int delayBetweenBlink1 = 500;byte led1State = LOW;unsigned int lastTimeLed2Blinked = millis();unsigned int delayBetweenBlink2 = 800;byte led2State = LOW;void setup() { pinMode(LED_1_PIN, OUTPUT); pinMode(LED_2_PIN, OUTPUT);}void loop() { unsigned int timeNow = millis(); // Action 1 - Blink LED 1 if (timeNow - lastTimeLed1Blinked > delayBetweenBlink1) { if (led1State == LOW) { led1State = HIGH; } else { led1State = LOW; } digitalWrite(LED_1_PIN, led1State); lastTimeLed1Blinked = timeNow; } // Action 2 - Blink LED 2 if (timeNow - lastTimeLed2Blinked > delayBetweenBlink2) { if (led2State == LOW) { led2State = HIGH; } else { led2State = LOW; } digitalWrite(LED_2_PIN, led2State); lastTimeLed2Blinked = timeNow; }}
ご覧のように、追加した2番目のアクションのコード構造を繰り返します。 そして、両方のアクションはお互いを邪魔しません!
要約
あなたは使用せずにArduinoの遅延を作りたい場合delay()
:
- 最後に特定のアクションを実行した時間を格納するグローバル変数を作成します。
- 2つのアクションの間に必要な期間を格納する別のグローバル変数を作成します。
-
loop()
関数では、millis()
で現在の時刻を読み取ります。 - その直後にif構造体を使用し、条件
(timeNow - lastTimeActionWasExecuted > delayBetweenActions)
を使用します。 -
if()
を入力したら、アクションを実行します。 - そしてまだ
if()
には、現在の時刻を前の時刻として保存します。
Arduinoの遅延が必要なすべてのアクションに対して、これらの手順を繰り返すことができます。Delay()とdelayMicroseconds()を使用しても問題ない場合
コードでdelay()
を使用しても問題ない場合は、特定の機会があります。
そのうちの2つは:
- プログラムのセットアップ中にコンポーネントを初期化する必要があり、このコンポーネントは初期化するのに時間がかかります–たとえば1.5秒。 この場合、
setup()
関数でdelay(1500)
を使用することは完全に問題ありません。 基本的には、Arduinoプログラムのsetup()
関数内のdelay()
は問題になりません。 -
delayMicroseconds()
の部分で説明されているように、数マイクロ秒(ミリ秒ではない)待つ必要があります。)外付け部品と通信する場合。 小さな数(たとえば10)でdelayMicroseconds()
を使用してもプログラムの残りの部分に支障がないことがわかった場合でも、あまり心配することなく使用できます。 しかし、それを一般的なルールではなく、例外とみなしてください。
結論–arduino delay()を慎重に使用する
Arduinoプログラムの性質上、コードに遅延を追加する必要があることが多いため、いくつかのアクションをいつ実行す
delay()
とdelayMicroseconds()
関数は非常にシンプルな関数であり、完全な初心者が簡単なものから始めることができるようにArduino言語に追加されました。
しかし、このチュートリアルで見たように、delay()
を使用すると、本当にすぐに立ち往生することができます。 したがって、最初に必要な理由、使用方法、およびArduinodelay()
関数を直接使用せずに同じ動作を取得する方法を理解することをお勧めします。
delay()
を取り除くためのコード構造を理解すると、Arduinoプログラムをたくさん改善することができ、マルチタスクは非常に簡単になります。