非常に長いdelay()が可能ですか?


9

12時間ごとに開閉する小さなドアを開閉しようとしています。12時間delay()、delay(43 200 000 000)で小さなループスクリプトを作成できるかどうか疑問に思いました。私は推測する?しかし、それが可能であるか、推奨できるか、あるいはその両方であるかどうかはわかりません。いくつかのフィードバック/代替案(必要な場合)がいいでしょう:)


はい、遅延の最大値は65535 µsだと思いますが、今は別の方法が必要です...
Fred Pannekoek 2014

4
より成熟したMCU単体のシステムでのタイミングは、通常、MCUのハードウェアタイマーチャネルをプログラミングして割り込みを定期的に発生させ、それをカウントすることで行われます。時計クリスタル。
Chris Stratton

3
遅延を使用すると、これまでにないわずかなオーバーヘッドエラーが拡大します。割り込みを使用して既知の良好な期間を計時し、そこからカウントすることをお勧めします。ここでは私の個人的なウェブサイト上の概念の証明がある:blog.linformatronics.nl/213/electronics/...
jippie

1
完全にタイミングを合わせる必要がない場合は、朝と夕方を感知する光センサーなど、型破りなものを使用できます。
帽子をかぶった男

はい、私はそれについて考えました、しかし、私は小さな光検出器部分しか持っておらず、それを天候から保護する方法がわかりません(小さなドアは外にあります)
Fred Pannekoek 2014

回答:


10

リアルタイムクロック方式が最も正確な方法ですが、それ以外の場合は millis

unsigned long startMillis = millis();
while (millis() - startMillis < LONG_DELAY_MS);

これは最大約遅延します。4294967295ms(2 ^ 32-1)または49日後、タイマーは次の値に追いつきますstartMillis


1
ただ使用することの何が問題になっていdelay(LONG_DELAY_MS)ますか?arduinoの実装では、符号なしlong型を受け入れます。また、私は完全に必ず時にコードが正しく機能していないよmillis()ラップアラウンド、およびよりも小さいstartMillis
Gerben

遅延は、私が正しいかどうかを待っている間、arduinoを完全に非アクティブにします。ミリが0に戻ったときに、これがどのように機能するかわかりません。–
Fred Pannekoek

@Gerben良いもの、答えにしてください!
geometrikal

2
@FredPannekoekオーバーフローは、unsigned longが使用されている限り、正常に機能します。
geometrikal

1
@ 23ars Arduinoが非常に成功している主な理由は、使いやすいハードウェア抽象化ライブラリーです。ライブラリーの関数に反対する場合は、ある程度制限します。とにかく、コメントの機能は答えを改善することです。より良い解決策がある場合は、独自の答えを書いてください。;)
geometrikal

7

delay()その用途はありますが、長い遅延のため、それは良くありません。それは単にxクロックサイクルに対して何もしないようにマイクロコントローラーに伝えます。その間、Arduinoは他に何もできません。

あなたの最善の策は、リアルタイムクロック(RTC)と呼ばれるものを使用することです。これらのチップは、時間を追跡するために特別に作成されており、Arduinoに簡単に接続できます。これを行う方法の例を次に示します。


+1-RTCソリューションは、MCUが提供できるよりも高い精度が必要な場合に特に適しています。
Ricardo

1
@Ricardo-RTCは、ハードウェアタイマーの1つを使用して定期的な割り込みを起動するクロッククリスタルを備えたMCUよりも正確ではありません。それによって通常得られるのは、停電を追跡することであり、おそらくカレンダースキームの知識もあるでしょう。
Chris Stratton

1
Afaik unoは、クロックにクオーツビットセラミック共振子を使用しないため、RTCよりもはるかに精度が低くなります。
jfpoilpret 14

@ChrisStratton-そうです。ポイントを取る。OPが特定の時間にドアを開閉する必要がある場合は、RTCの方がはるかに優れています。
Ricardo

7

ウォッチドッグ割り込みを使用して、待機中にMCUをスリープさせ、電力を節約できます。

ただし、ボードもそれを節約する場合にのみ、電力を節約することに注意してください。つまり、Unoなどの最も一般的なArduinoボードを装備する通常のレギュレーターの代わりに、低静止電圧レギュレーターが必要です。それ以外の場合は、ボードが省エネルギーしない場合にMCUがエネルギーを節約するかどうかは問題ではありません。

ここにコードがあります(テストされていません):

#include <avr/sleep.h>
// This variable is made volatile because it is changed inside an interrupt function
volatile int sleep_count = 0; // Keep track of how many sleep cycles have been completed.
const int interval = 720; // Interval in minutes between waking and doing tasks.
const int sleep_total = (interval*60)/8; // Approximate number of sleep cycles 
// needed before the interval defined above elapses. Not that this does integer math.

void setup(void) {
    watchdogOn(); // Turn on the watch dog timer.
    // Disable the ADC by setting the ADEN bit (bit 7) to zero.
    ADCSRA = ADCSRA & B01111111;
    // Disable the analog comparator by setting the ACD bit (bit 7) to one.
    ACSR = B10000000;
    // Disable digital input buffers on all analog input pins by setting bits 0-5 to one.
    DIDR0 = DIDR0 | B00111111;
}

void loop(void) {
    goToSleep(); // ATmega328 goes to sleep for about 8 seconds
    // and continues to execute code when it wakes up
    if (sleep_count == sleep_total) {
        // CODE TO BE EXECUTED PERIODICALLY
    }
}

void goToSleep() {
    set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode.
    sleep_enable(); // Enable sleep mode.
    sleep_mode(); // Enter sleep mode.
    // After waking from watchdog interrupt the code continues
    // to execute from this point.
    sleep_disable(); // Disable sleep mode after waking.
}

void watchdogOn() {
    // Clear the reset flag, the WDRF bit (bit 3) of MCUSR.
    MCUSR = MCUSR & B11110111;
    // Set the WDCE bit (bit 4) and the WDE bit (bit 3) of WDTCSR. 
    WDTCSR = WDTCSR | B00011000; 
    // Set the watchdog timeout prescaler value to 1024 K 
    // which will yeild a time-out interval of about 8.0 s.
    WDTCSR = B00100001;
    // Enable the watchdog timer interupt.
    WDTCSR = WDTCSR | B01000000;
    MCUSR = MCUSR & B11110111;
}

ISR(WDT_vect) 
{
    sleep_count ++; // keep track of how many sleep cycles have been completed.
}

私がコピーしたコードはこのページからです:ウォッチドッグタイマーを使用した低電力Arduino


1

スリープ(符号なし整数秒)はありますか?

そうでない場合は、これにより非常に長い間delay()を実行できます。

for (unsigned int bigloop=0; bigloop<65535; bigloop++)
{
   for (unsigned int smallloop=0; smallloop<65535; smallloop++)
   {
      for (unsigned int tinyloop=0; tinyloop<65535; tinyloop++)
      {
         delay(65535);
      }
   }
}

トムが言ったようなRTCを取得できなかった場合は、これを試すことができます。助けてくれてありがとう!
Fred Pannekoek 14

1

これは動作します:

longDelayInSeconds = 120; //two minutes;   
while (p < longDelayInSeconds) {

        delay(1000);
        p++;

}

4
最適なソリューションではなく、OPは2分ではなく12時間を要求しました。
Madivad

1

間に何かしたくない場合は、forループを使用します。

for (int Hours = 0; Hours < 12; Hours++) {            //Creates 12 hours
  for (int Minutes = 0; Minutes < 60; Minutes++) {    //Creates 1 hour
    for (int Seconds = 0; Seconds < 60; Seconds++) {  //Creates 1 minute
      delay(1000);                                    //Creates 1 second
    }
  }
}

4
これが単純なものよりも優れていることを説明しますdelay(43200000)

1
まず、待機時間を変更する方が簡単です。ミリ秒に変換する必要なく、時間、分、秒ごとに数値を変更するだけです。
GeneCode
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.