หน่วงเวลานานมาก () เป็นไปได้หรือไม่


9

ฉันกำลังพยายามเปิดและปิดประตูเล็ก ๆ ที่ควรเปิดหรือปิดทุก ๆ 12 ชั่วโมง ฉันสงสัยว่าฉันสามารถสร้างสคริปต์ลูปขนาดเล็กที่มีการหน่วงเวลา () เป็นเวลา 12 ชั่วโมงล่าช้า (43 200,000 ล้าน); ฉันคิดว่า? อย่างไรก็ตามฉันไม่รู้ว่ามันเป็นไปได้และ / หรือแนะนำได้ ข้อเสนอแนะ / ทางเลือก (ถ้าจำเป็น) จะดี :)


ตกลงฉันคิดว่าความล่าช้ามีมากถึง 65535 µs แต่ตอนนี้ฉันต้องการทางเลือก ...
Fred Pannekoek

4
การกำหนดเวลาในระบบที่มีความเป็นผู้ใหญ่มากขึ้นโดยปกติแล้วระบบ MCU จะทำโดยการตั้งโปรแกรมแชนเนลตัวจับเวลาฮาร์ดแวร์ของ MCU เพื่อดับการขัดจังหวะเป็นระยะจากนั้นนับจำนวนเหล่านี้ - ซึ่งทำให้โปรเซสเซอร์ทำสิ่งอื่น ๆ ในเวลาเดียวกัน นาฬิกาคริสตัล
Chris Stratton

3
การใช้การหน่วงเวลาจะขยายข้อผิดพลาดค่าโสหุ้ยเล็กน้อย จะเป็นการดีกว่าถ้าคุณใช้อินเทอร์รัปต์เพื่อทราบช่วงเวลาที่ดีและนับจากนั้น นี่คือหลักฐานของแนวคิดในเว็บไซต์ส่วนตัวของฉัน: blog.linformatronics.nl/213/electronics/…
jippie

1
หากไม่ต้องตั้งเวลาอย่างสมบูรณ์แบบคุณสามารถใช้สิ่งแปลกใหม่เช่นเซ็นเซอร์ตรวจจับแสงเพื่อรับรู้ตอนเช้าและเย็น
The Guy with The Hat

ใช่ฉันคิดเกี่ยวกับเรื่องนี้ แต่ฉันมีเพียงส่วนตรวจจับแสงน้อยและฉันไม่แน่ใจว่าจะปกป้องมันจากสภาพอากาศ (ประตูเล็ก ๆ ด้านนอก)
Fred Pannekoek

คำตอบ:


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

ความล่าช้าทำให้ arduino ของคุณไม่ทำงานอย่างสมบูรณ์ในขณะที่รอถ้าฉันถูกต้อง ฉันไม่รู้ว่าจะทำอย่างไรเมื่อมิลลิวินาทีกลับมาเป็น 0
Fred Pannekoek

@ Gerben สิ่งที่ดีวางไว้เป็นคำตอบ!
geometrikal

2
@FredPannekoek โอเวอร์โฟลว์จะทำงานได้ดีตราบใดที่มีการใช้งานแบบไม่ลงนามนานเกินไป
geometrikal

1
@ 23ars เหตุผลหลักที่ทำให้ Arduino ประสบความสำเร็จก็คือห้องสมุดนามธรรมที่ใช้งานง่ายถ้าคุณใช้ฟังก์ชั่นจากห้องสมุดคุณ จำกัด ตัวเองอยู่บ้าง อย่างไรก็ตามฟังก์ชั่นของความคิดเห็นคือการปรับปรุงคำตอบหากคุณมีทางออกที่ดีกว่าให้เขียนคำตอบของคุณเอง ;)
geometrikal

7

delay()มีประโยชน์ แต่สำหรับความล่าช้านานมันไม่ดี เพียงแค่บอกให้ไมโครคอนโทรลเลอร์ไม่ทำอะไรเลยกับxวงจรนาฬิกา ในช่วงเวลานั้น Arduino ของคุณไม่สามารถทำอะไรได้อีก

ทางออกที่ดีที่สุดของคุณคือใช้สิ่งที่เรียกว่านาฬิกาเรียลไทม์ (RTC) ชิปเหล่านี้ออกแบบมาโดยเฉพาะเพื่อติดตามเวลาและคุณสามารถเชื่อมต่อกับ Arduino ได้อย่างง่ายดาย นี่คือตัวอย่างของวิธีที่คุณสามารถทำได้


+1 - โซลูชัน RTC นั้นดีเป็นพิเศษหากคุณต้องการความแม่นยำมากกว่า MCU ที่สามารถให้คุณได้
Ricardo

1
@Ricardo - RTC ไม่น่าจะมีความแม่นยำมากกว่า MCU ที่มีนาฬิกาคริสตัลโดยใช้ตัวจับเวลาฮาร์ดแวร์ตัวใดตัวหนึ่งเพื่อเริ่มการขัดจังหวะเป็นระยะ สิ่งที่มักทำให้คุณได้รับคือการติดตามการสูญเสียพลังงานและอาจมีความรู้บางอย่างเกี่ยวกับแผนการปฏิทิน
Chris Stratton

1
Afaik uno ไม่ได้ใช้ resonator เซรามิกบิตของนาฬิกาควอทซ์ดังนั้นจึงมีความแม่นยำน้อยกว่า rtc มาก
jfpoilpret

@ChrisStratton - ถูกต้อง จุดที่ถ่าย RTC จะเป็นตัวเลือกที่ดีกว่าถ้า OP ต้องเปิดหรือปิดประตูในเวลาที่กำหนดของวัน
Ricardo

7

คุณสามารถใช้ watchdog อินเตอร์รัปต์และทำให้ 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

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
explaing delay(43200000)วิธีนี้จะดีกว่าที่เรียบง่าย

1
สำหรับผู้เริ่มต้นมันจะง่ายขึ้นในการปรับเปลี่ยนว่าคุณต้องการรอนานแค่ไหน เพียงแค่เปลี่ยนจำนวนสำหรับแต่ละชั่วโมงนาทีและวินาทีโดยไม่จำเป็นต้องแปลงเป็นมิลลิวินาที
GeneCode
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.