Можлива дуже довга затримка ()?


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);

Це затримається до приблизно. 4294967295ms (2 ^ 32-1) або 49 днів, після чого таймер наздожене значенняstartMillis


1
Що не в тому, щоб просто використовувати delay(LONG_DELAY_MS)? Реалізація arduino приймає неподписані довги . Я також не зовсім впевнений, що код працює правильно під час millis()обгортання, і він менший ніжstartMillis
Гербен

Затримка робить ваш ардуїно абсолютно неактивним під час очікування, якщо я маю рацію. Я не знаю, як це буде діяти, коли міліс повернеться до 0.
Фред Паннекок

@Gerben гарний матеріал, поставте це як відповідь!
geometrikal

2
Переповнення @FredPannekoek буде працювати нормально, так довго , як непідписані давно використовується.
geometrikal

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.
}

Код, який я скопіював, з цієї сторінки: Ардуїно малої потужності за допомогою таймера сторожового дога .


1

Чи є у вас сон (непідписаний int секунд)?

Якщо ні, це дозволить вам затримати () дуже довгий час:

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, як сказав Том. Дякуємо за допомогу!
Фред Паннекек

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.