可能有很长的delay()吗?


9

我正在尝试打开一个应该每12小时打开或关闭的小门。我想知道我是否可以制作一个带有delay()的小型循环脚本12个小时,delay(43 200 000 000); 我猜?但是,我不知道这是否可能和/或值得推荐。一些反馈/替代品(如果需要)将是不错的:)


好的,我认为延迟最大为65535 µs,但现在我需要一个替代方案...
Fred Pannekoek 2014年

4
在更成熟的,独立于MCU的系统中,计时通常是通过对MCU的硬件计时器通道进行编程以定期触发中断,然后对它们进行计数来进行的-这使处理器可以同时执行其他操作,并且累积精度与时钟晶体。
克里斯·斯特拉顿

3
使用延迟会放大一个如此微小的开销错误。最好使用中断为已知的良好时间计时,然后从那里开始计数。这里是概念在我的个人网站证明:blog.linformatronics.nl/213/electronics/...
jippie

1
如果不一定要定时,可以使用非常规的东西,例如光传感器来感应早晚。
戴帽子的家伙

是的,我考虑过这一点,但是我只有一个光探测器部分,并且我不确定如何保护它不受天气影响(小门在外面)
Fred Pannekoek 2014年

Answers:


10

实时时钟方法是最准确的方法,但可以使用其他方法 millis

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

这将最多延迟大约。4294967295ms(2 ^ 32-1)或49天,之后计时器将赶上startMillis


1
仅仅使用有什么问题delay(LONG_DELAY_MS)?在Arduino的实施接受无符号多头。我也不完全确定您的代码在millis()环绕时是否工作正确,并且小于startMillis
Gerben 2014年

如果我正确的话,延迟会使您的arduino完全不活动。我不知道这将如何当米利斯是回0行动
弗雷德潘涅库克

@Gerben好东西,把它作为答案!
geometrikal

2
只要使用unsigned long ,@ FredPannekoek溢出就可以正常工作。
geometrikal

1
@ 23ars Arduino如此成功的主要原因是其易于使用的硬件抽象库,如果您反对库中的函数,则会在某种程度上限制自己。无论如何,评论的功能是改善答案,如果您有更好的解决方案,请编写自己的答案。;)
geometrikal

7

delay()有其用途,但长时间拖延是没有用的。它只是告诉微控制器在x时钟周期内什么也不做。在这段时间内,您的Arduino无法执行其他任何操作。

最好的选择是使用一种称为实时时钟(RTC)的东西。这些芯片专门用于跟踪时间,您可以轻松地将它们连接到Arduino。这是一个如何做到这一点的例子。


+1-如果您想获得比MCU所能提供的精度更高的RTC解决方案,则特别好。
里卡多

1
@Ricardo-RTC可能不比带有时钟晶体的MCU使用其硬件计时器之一触发周期性中断的准确性高;它通常能使您跟踪功率损耗,以及日历计划的一些知识。
克里斯·斯特拉顿

1
Afaik uno的时钟没有使用石英位的陶瓷谐振器,因此精度比rtc小得多。
jfpoilpret 2014年

@ChrisStratton-对。点了。如果OP必须在一天的给定时间打开或关闭门,则RTC将是更好的选择。
里卡多

7

您可以使用看门狗中断,并在等待时让MCU休眠并节省功耗。

但是请注意,如果您的电路板也节省了电源,则只会节省电源。这意味着您必须具有低静态电压调节器,而不是配备最常见的Arduino板(例如Uno)的常规调节器。否则,如果您的主板不节能,您的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

您有睡眠时间(无符号整数秒)吗?

如果没有,这将使您可以延迟很长的时间:

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

1

这将起作用:

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

        delay(1000);
        p++;

}

4
不是最佳解决方案,OP要求12个小时而不是2分钟。
Madivad 2015年

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.