Возможна очень большая задержка ()?

9

Я пытаюсь открыть и закрыть маленькую дверь, которая должна открываться или закрываться каждые 12 часов. Мне было интересно, смогу ли я просто сделать небольшой зацикленный скрипт с задержкой () на 12 часов, задержкой (43 200 000 000); Я полагаю? Тем не менее, я понятия не имею, если это возможно и / или рекомендуется. Некоторые отзывы / альтернативы (при необходимости) были бы хороши :)

Фред Паннекук
источник
хорошо, я думаю, что задержка составляет максимум 65535 мкс, но теперь мне нужна альтернатива ...
Фред Паннекук
4
Синхронизация в более зрелых, автономных системах MCU обычно выполняется путем программирования канала аппаратного таймера MCU на периодическое срабатывание прерывания, а затем подсчитывает их - это позволяет процессору делать другие вещи в то же время и кумулятивно настолько же точно, как и часы кристалл.
Крис Страттон
3
Использование задержки увеличит очень незначительную ошибку заголовка. Лучше использовать прерывание для определения времени известного хорошего периода, а затем отсчитывать оттуда. Вот подтверждение концепции на моем личном веб-сайте: blog.linformatronics.nl/213/electronics/…
jippie
1
Если это не должно быть точно рассчитано по времени, вы можете использовать нетрадиционные вещи, такие как датчик света, чтобы чувствовать утро и вечер.
Парень со шляпой
да, я думал об этом, однако у меня есть только небольшая часть детектора света, и я не уверен, как защитить его от непогоды (маленькая дверь снаружи)
Фред Паннекук

Ответы:

10

Метод часов реального времени является наиболее точным, но в противном случае используется millis

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

Это задержит до прибл. 4294967295 мс (2 ^ 32-1) или 49 дней, после чего таймер догонит значениеstartMillis

geometrikal
источник
1
Что не так просто с использованием delay(LONG_DELAY_MS)? Реализация arduino принимает беззнаковые long. Я также не совсем уверен, что ваш код работает правильно, когда millis()оборачивается, и меньше, чемstartMillis
Gerben
Задержка делает ваше Arduino полностью неактивным во время ожидания, если я прав. Я не знаю, как это будет действовать, когда Миллис вернется к 0.
Фред Паннекук
@ Гербен хороший материал, поставь это как ответ!
геометрикал
2
Переполнение @FredPannekoek будет работать нормально, если используется unsigned long.
геометрикал
1
@ 23ars Основная причина успеха Arduino - это простая в использовании библиотека аппаратных абстракций. Если вы против функций из библиотек, вы несколько ограничиваете себя. В любом случае, функция комментариев - улучшить ответ, если у вас есть лучшее решение, напишите свой ответ. ;)
геометрикал
7

delay()имеет свое применение, но для длительных задержек это бесполезно. Он просто говорит микроконтроллеру ничего не делать для xтактов. В течение этого времени ваш Arduino не может больше ничего делать.

Лучше всего использовать часы реального времени (RTC). Эти чипы специально созданы для отслеживания времени, и вы можете легко подключить их к Arduino. Вот пример того, как вы могли бы сделать это.

Том
источник
+1 - решение RTC особенно хорошо, если вы хотите большей точности, чем может дать MCU.
Рикардо
1
@Ricardo - RTC вряд ли будет более точным, чем MCU с тактовым кристаллом, использующим один из своих аппаратных таймеров для срабатывания периодического прерывания; то, что он обычно получает, отслеживает потерю мощности и, возможно, некоторые знания о календарных схемах.
Крис Страттон
1
Afaik Uno не использует кварцевый бит керамический резонатор для своих часов, таким образом, с гораздо меньшей точностью, чем RTC.
jfpoilpret
@ChrisStratton - Верно. Дело принято. RTC будет намного лучшим вариантом, если OP должен открыть или закрыть дверь в определенное время суток.
Рикардо
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);
      }
   }
}
TDHofstetter
источник
Я мог бы попробовать это, если бы мне не удалось получить RC, как сказал Том. Спасибо за помощь!
Фред Паннекук
1

Это будет работать:

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

        delay(1000);
        p++;

}
Фрэнк С
источник
4
не лучшее решение и ОП попросили 12 часов, а не 2 минуты.
Мадивад
1

Я просто использую для циклов, когда я не хочу делать вещи между:

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