Çok uzun gecikme () mümkün mü?


9

12 saatte bir açılıp kapanması gereken küçük bir kapı açmaya çalışıyorum. Ben sadece 12 saat, gecikme (43 200 000 000) için bir delay () ile küçük bir döngü script yapabilir miyim merak ediyordum; Sanırım? Ancak bunun mümkün ve / veya tavsiye edilip edilmediğine dair hiçbir fikrim yok. Bazı geribildirim / alternatifler (gerekirse) iyi olurdu :)


Tamam, gecikmenin maksimum 65535 µs olduğunu düşünüyorum, ama şimdi bir alternatife ihtiyacım var ...
Fred Pannekoek

4
Daha olgun, MCU'lu sistemlerde zamanlama genellikle, MCU'nun bir donanım zamanlayıcı kanalını periyodik olarak bir kesmeyi tetikleyecek şekilde programlayarak ve daha sonra bunları sayarak - işlemcinin bu arada başka şeyler yapmasına izin verir ve kümülatif olarak saat kristali.
Chris Stratton

3
Gecikmenin kullanılması, çok hafif bir havai hatayı büyütecektir. Bilinen iyi bir dönemi zamanlamak için bir kesme kullanmak ve oradan saymak daha iyidir. İşte kişisel web sitemde bir kavram kanıtı: blog.linformatronics.nl/213/electronics/…
jippie

1
Mükemmel bir şekilde zamanlanması gerekmiyorsa, sabah ve akşamları algılamak için bir ışık sensörü gibi geleneksel olmayan şeyleri kullanabilirsiniz.
Şapkalı Adam

evet, bunu düşündüm, ancak sadece küçük bir ışık dedektörü parçam var ve hava koşullarından nasıl koruyacağından emin değilim (küçük kapı dışarıda)
Fred Pannekoek

Yanıtlar:


10

Gerçek zamanlı saat yöntemi en doğru yoldur, ancak başka şekilde kullanın millis

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

Bu, yakl. 4294967295ms (2 ^ 32-1) veya 49 gün, bundan sonra zamanlayıcı,startMillis


1
Sadece kullanmanın nesi yanlış delay(LONG_DELAY_MS)? Arduino uygulama imzasız uzun ürünler kabul eder. Ben de tamamen millis()sarar zaman kodu doğru çalıştığından emin değilim ve daha küçükstartMillis
Gerben

Gecikme, arduino'nuzu doğru olup olmadığımı beklerken tamamen pasif hale getirir. Milis 0'a döndüğünde bunun nasıl hareket edeceğini bilmiyorum
Fred Pannekoek

@ Gerben iyi şeyler, bir cevap olarak koy!
geometrikal

2
@FredPannekoek taşması imzasız uzun kullanıldığı sürece iyi çalışır .
geometrikal

1
@ 23ars Arduino'nun bu kadar başarılı olmasının ana nedeni, kullanımı kolay donanım soyutlama kütüphanesidir, eğer kütüphanelerden gelen fonksiyonlara karşıysanız, kendinizi biraz kısıtlıyorsunuz. Her neyse, yorumların işlevi cevabı geliştirmektir, daha iyi bir çözümünüz varsa, kendi cevabınızı yazın. ;)
geometrikal

7

delay()kullanımları vardır, ancak uzun gecikmeler için iyi değildir. Sadece mikrodenetleyiciye xsaat çevrimleri için hiçbir şey yapmamasını söyler . Bu süre zarfında, Arduino'nuz başka bir şey yapamaz.

En iyi seçeneğiniz Gerçek Zamanlı Saat (RTC) adı verilen bir şey kullanmak olacaktır. Bu yongalar özellikle zamanı takip etmek için yapılır ve bunları Arduino'nuza kolaylıkla bağlayabilirsiniz. İşte bunu nasıl yapabileceğinize bir örnek.


+1 - MCU'nun size verebileceğinden daha fazla doğruluk istiyorsanız, RTC çözümü özellikle iyidir.
Ricardo

1
@Ricardo - bir RTC'nin, periyodik bir kesmeyi ateşlemek için donanım zamanlayıcılarından birini kullanan bir saat kristaline sahip bir MCU'dan daha doğru olması muhtemel değildir; genellikle size sağladığı şey, güç kaybını ve belki de bazı takvim şemaları bilgisini takip etmektir.
Chris Stratton

1
Afaik uno, saati için kuvars biti bir seramik rezonatör kullanmaz, bu nedenle bir rtc'den çok daha az doğrulukla.
jfpoilpret

@ChrisStratton - Doğru. Alınan nokta. OP günün belirli bir saatinde kapıyı açması veya kapatması gerekiyorsa RTC çok daha iyi bir seçenek olacaktır.
Ricardo

7

Bekçi beklemesini kullanabilir ve MCU'nuzu beklerken uykuya alabilirsiniz ve güç tasarrufu yapabilirsiniz.

Ancak, yalnızca kartınız da kaydederse güç tasarrufu yapacağınızı unutmayın. Bu, Uno gibi en yaygın Arduino kartlarını donatan normal regülatörler yerine düşük bir sessiz voltaj regülatörünüz olması gerektiği anlamına gelir. Aksi takdirde, kartınız değilse MCU'nuzun enerji tasarrufu sağlayıp sağlamadığı önemli değildir.

İşte kod (denenmemiş):

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

Kopyaladığım kod bu sayfadan: Düşük Güçlü Arduino Bekçi Zamanlayıcısını Kullanarak .


1

Uykunuz var mı (imzalanmamış int saniye)?

Değilse, bu çok uzun bir süre geciktirmenize () izin verir:

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

Tom'un dediği gibi bir rtc almayı başaramazsam bunu deneyebilirim. Yardım için teşekkürler!
Fred Pannekoek

1

Bu çalışacak:

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

        delay(1000);
        p++;

}

4
en iyi çözüm değil ve OP 2 saat değil 12 saat istedi.
Madivad

1

Aralarında bir şeyler yapmak istemediğimde döngüler için kullanıyorum:

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
Bunun bir basitten daha iyi olduğunu açıklamak delay(43200000).

1
Başlangıç ​​için ne kadar beklemek istediğinizi değiştirmek daha kolay olacaktır. Milisaniyeye dönüştürmeye gerek kalmadan her saat, dakika ve saniye sayısını değiştirin.
GeneCode
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.