同時に複数のパターンを処理することは、Arduinoのようなプラットフォームで確かに可能であり、それに対処する方法はいくつかあります。
私が検討する1つの方法は、各パターンを数学的に効果的に表す関数を記述することです。これまでにプログラムで経過した合計時間を渡すだけで、その特定の瞬間に適切なアクションを実行します。その後すぐに戻ります(遅延などはありません)。
そのためには、最初にパターンの1サイクルがどれだけ続くかを知る必要があります。次に、モジュロ演算子を使用して、現在のサイクルをどれだけ進んでいるかを把握できます。そこから、あなたがしなければならないことはif
、いつでも何をすべきかを決定するためのいくつかの条件を持つことです。
「5秒オン、5秒オフ」のパターンは次のようになります。
function pattern5on5off(unsigned long totalTime)
{
// Calculate how far through the current cycle we are
const unsigned long cycleTime = totalTime % 10000;
// If we're in the first 5 seconds of the cycle then turn the light on.
// Otherwise, turn it off.
if (cycleTime < 5000)
digitalWrite(3, HIGH);
else
digitalWrite(3, LOW);
}
確かに、digitalWrite()
技術的に必要がないときに絶えず電話をかけることは、あまり効率的ではありません。ただし、問題が発生することはなく、必要に応じて最適化するのもかなり簡単です。
上記の例をスケッチで使用するには、それをで呼び出しloop()
、取得した数値を渡すだけですmillis()
。例えば:
void loop()
{
const unsigned long totalTime = millis();
pattern5on5off(totalTime);
// call other patterns here...
}
他のパターンはより複雑になりますが、同じ原理に従います。適切なif
ステートメントを使用してロジックを表現するだけです。
覚えておくべき重要なことは、関数が特定の瞬間を表すということです。プログラムを一時停止したり遅延させたりしてはなりません。そうしないと、他のパターンの実行が妨げられます。
編集:最初のサイクルのタイミング
jfpoilpretがコメントに記載されているように、最初のサイクルはランダムなポイントから始まります。これは、最初にを呼び出しmillis()
たときにloop()
、0からは開始されないためです(デバイスは、loop()
呼び出される前にすでに短時間実行されています)。ただし、必要に応じて簡単に解決できます。
これtotalTime
は、最初に取得した任意の値で値をオフセットすることによって行いますloop()
。例えば:
unsigned long g_startTime = 0;
void loop()
{
unsigned long totalTime = 0;
if (g_startTime == 0) {
// This is the first cycle.
// Store the start time so we can compensate later.
g_startTime = millis();
} else {
// This is not the first cycle.
// Compensate for the start time.
totalTime = millis() - g_startTime;
}
pattern5on5off(totalTime);
// etc..
}