Penundaan yang sangat lama () mungkin?

9

Saya mencoba membuat pintu kecil yang membuka dan menutup setiap 12 jam. Saya bertanya-tanya apakah saya bisa membuat skrip pengulangan kecil dengan jeda () selama 12 jam, jeda (43 200 000 000); Saya tebak? Namun, saya tidak tahu apakah itu mungkin dan / atau direkomendasikan. Beberapa umpan balik / alternatif (jika perlu) akan menyenangkan :)

Fred Pannekoek
sumber
ok, saya pikir delay memiliki maks 65535 μs, tapi sekarang saya butuh alternatif ...
Fred Pannekoek
4
Pengaturan waktu yang lebih matang, sistem MCU-alone biasanya dilakukan dengan memprogram saluran timer perangkat keras MCU untuk menyalakan interupsi secara berkala, dan kemudian menghitungnya - yang memungkinkan prosesor melakukan hal-hal lain sementara itu, dan secara kumulatif seakurat kristal jam.
Chris Stratton
3
Menggunakan penundaan akan memperbesar kesalahan overhead yang sangat kecil. Lebih baik menggunakan interupsi ke waktu periode yang dikenal baik dan kemudian dihitung dari sana. Ini adalah bukti konsep di situs web pribadi saya: blog.linformatronics.nl/213/electronics/…
jippie
1
Jika tidak harus tepat waktunya, Anda dapat menggunakan hal-hal yang tidak konvensional, seperti sensor cahaya untuk merasakan pagi dan sore hari.
The Guy with The Hat
ya, saya berpikir tentang itu, namun saya hanya memiliki bagian detektor cahaya kecil dan saya tidak yakin bagaimana melindunginya dari cuaca (pintu kecil ada di luar)
Fred Pannekoek

Jawaban:

10

Metode jam waktu nyata adalah cara yang paling akurat tetapi sebaliknya digunakan millis

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

Ini akan menunda hingga sekitar. 4294967295ms (2 ^ 32-1) atau 49 hari, setelah itu timer akan mengejar nilaistartMillis

geometrikal
sumber
1
Apa yang salah dengan hanya menggunakan delay(LONG_DELAY_MS)? The pelaksanaan Arduino menerima rindu unsigned. Saya juga tidak sepenuhnya yakin kode Anda berfungsi dengan benar ketika millis()membungkusnya, dan lebih kecil daristartMillis
Gerben
Keterlambatan membuat Arduino Anda benar-benar tidak aktif sambil menunggu jika saya benar. Saya tidak tahu bagaimana ini akan bertindak ketika milis kembali ke 0.
Fred Pannekoek
@Gerben barang bagus, letakkan sebagai jawaban!
geometrikal
2
@FredPannekoek overflow akan berfungsi dengan baik, asalkan lama yang tidak ditandai digunakan.
geometrikal
1
@ 23ars Alasan utama Arduino begitu sukses adalah pustaka abstraksi perangkat keras yang mudah digunakan, jika Anda menentang fungsi-fungsi dari pustaka, Anda agak membatasi diri. Bagaimanapun, fungsi komentar adalah untuk meningkatkan jawaban, jika Anda memiliki solusi yang lebih baik, tulis jawaban Anda sendiri. ;)
geometrikal
7

delay()memiliki kegunaannya, tetapi untuk penundaan yang lama itu tidak baik. Ini hanya memberitahu mikrokontroler untuk tidak melakukan apa pun untuk xsiklus jam. Selama waktu itu, Arduino Anda tidak dapat melakukan hal lain.

Taruhan terbaik Anda adalah menggunakan sesuatu yang disebut Real Time Clock (RTC). Chip ini khusus dibuat untuk melacak waktu, dan Anda dapat menghubungkannya ke Arduino Anda dengan mudah. Inilah contoh bagaimana Anda bisa melakukan itu.

Tom
sumber
+1 - Solusi RTC sangat bagus jika Anda ingin lebih akurat daripada yang bisa diberikan MCU.
Ricardo
1
@ Ricardo - sebuah RTC tidak mungkin lebih akurat daripada MCU dengan kristal jam menggunakan salah satu pengatur waktu perangkat kerasnya untuk menyalakan interupsi berkala; apa yang biasanya membuat Anda melacak kehilangan daya, dan mungkin beberapa pengetahuan tentang skema kalender.
Chris Stratton
1
Afaik uno tidak menggunakan kuarsa bit resonator keramik untuk jamnya, sehingga dengan akurasi jauh lebih sedikit daripada rtc.
jfpoilpret
@ ChrisStratton - Benar. Poin yang diambil. RTC akan menjadi opsi yang jauh lebih baik jika OP harus membuka atau menutup pintu pada waktu tertentu.
Ricardo
7

Anda dapat menggunakan pengawas interupsi dan membuat MCU Anda tidur sambil menunggu dan menghemat daya.

Tetapi perhatikan bahwa Anda hanya akan menghemat daya jika papan Anda juga menyimpannya. Itu berarti Anda harus memiliki regulator tegangan diam rendah daripada regulator biasa yang melengkapi papan Arduino yang paling umum, seperti Uno. Kalau tidak, tidak masalah apakah MCU Anda menghemat energi jika papan Anda tidak.

Berikut kodenya (belum diuji):

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

Kode yang saya salin dari halaman ini: Arduino Berdaya Rendah Menggunakan Watchdog Timer .

Ricardo
sumber
1

Apakah Anda memiliki sleep (unsigned int seconds) yang tersedia?

Jika tidak, ini akan memungkinkan Anda untuk menunda () waktu yang sangat lama:

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
sumber
Saya bisa mencoba ini jika saya tidak berhasil mendapatkan rtc seperti kata Tom. Terima kasih telah membantu!
Fred Pannekoek
1

Ini akan berhasil:

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

        delay(1000);
        p++;

}
Frank C
sumber
4
bukan solusi terbaik dan OP meminta 12 jam, bukan 2 menit.
Madivad
1

Saya hanya menggunakan untuk loop ketika saya tidak ingin melakukan hal-hal di antaranya:

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
    }
  }
}
Lohan
sumber
4
Jelaskan bagaimana ini lebih baik daripada yang sederhana delay(43200000).
1
Nah untuk pemula akan lebih mudah untuk memodifikasi berapa lama Anda ingin menunggu. Ubah saja angka untuk setiap jam, menit, dan detik tanpa perlu mengonversikannya menjadi milidetik.
GeneCode