Độ trễ rất dài () có thể?


9

Tôi đang cố gắng để mở và đóng một cánh cửa nhỏ nên mở hoặc đóng cứ sau 12 giờ. Tôi đã tự hỏi nếu tôi chỉ có thể tạo một kịch bản lặp nhỏ với độ trễ () trong 12 giờ, độ trễ (43 200 000 000); Tôi đoán? Tuy nhiên, tôi không biết nếu điều đó có thể và / hoặc được khuyến nghị. Một số phản hồi / lựa chọn thay thế (nếu cần) sẽ tốt đẹp :)


ok, tôi nghĩ độ trễ có tối đa 65535 lượt, nhưng bây giờ tôi cần một giải pháp thay thế ...
Fred Pannekoek

4
Thời gian trong các hệ thống MCU đơn thuần hơn thường được thực hiện bằng cách lập trình kênh hẹn giờ phần cứng của MCU để thực hiện ngắt theo định kỳ, sau đó đếm chúng - cho phép bộ xử lý thực hiện những việc khác trong thời gian đó và chính xác như chính xác đồng hồ pha lê.
Chris Stratton

3
Sử dụng độ trễ sẽ phóng to một lỗi quá nhỏ. Nó là tốt hơn để sử dụng một ngắt để thời gian một thời gian tốt được biết đến và sau đó đếm từ đó. Dưới đây là một bằng chứng về khái niệm trên trang web cá nhân của tôi: blog.linformatronics.nl/213/electronics/iêu
jippie

1
Nếu không nhất thiết phải đúng giờ, bạn có thể sử dụng những thứ độc đáo, như cảm biến ánh sáng để cảm nhận buổi sáng và buổi tối.
Chàng trai với chiếc mũ

vâng, tôi đã nghĩ về điều đó, tuy nhiên tôi chỉ có một bộ phận phát hiện ánh sáng nhỏ và tôi không chắc làm thế nào để bảo vệ nó khỏi thời tiết (cánh cửa nhỏ ở bên ngoài)
Fred Pannekoek

Câu trả lời:


10

Phương pháp đồng hồ thời gian thực là cách chính xác nhất nhưng sử dụng khác millis

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

Điều này sẽ trì hoãn đến khoảng. 4294967295ms (2 ^ 32-1) hoặc 49 ngày, sau đó bộ hẹn giờ sẽ bắt kịp giá trị củastartMillis


1
Có gì sai khi chỉ sử dụng delay(LONG_DELAY_MS)? Việc thực hiện arduino chấp nhận dài không dấu. Tôi cũng không hoàn toàn chắc chắn rằng mã của bạn hoạt động chính xác khi millis()kết thúc tốt hơn và nhỏ hơnstartMillis
Gerben

Độ trễ làm cho arduino của bạn hoàn toàn không hoạt động trong khi chờ đợi nếu tôi đúng. Tôi không biết điều này sẽ hoạt động như thế nào khi millis trở về 0.
Fred Pannekoek

@Gerben thứ tốt, đặt nó như một câu trả lời!
geometrikal

2
@FredPannekoek tràn sẽ hoạt động tốt, miễn là sử dụng lâu dài không dấu .
geometrikal

1
@ 23ars Lý do chính khiến Arduino thành công là thư viện trừu tượng hóa phần cứng dễ sử dụng, nếu bạn chống lại các chức năng từ các thư viện, bạn sẽ tự giới hạn mình phần nào. Dù sao, chức năng của ý kiến ​​là cải thiện câu trả lời, nếu bạn có giải pháp tốt hơn, hãy viết câu trả lời của riêng bạn. ;)
geometrikal

7

delay()có công dụng của nó, nhưng đối với sự chậm trễ lâu thì không tốt. Nó chỉ đơn giản là bảo vi điều khiển không làm gì cho xchu kỳ xung nhịp. Trong thời gian đó, Arduino của bạn không thể làm gì khác.

Đặt cược tốt nhất của bạn sẽ là sử dụng một thứ gọi là Đồng hồ thời gian thực (RTC). Những con chip này được chế tạo đặc biệt để theo dõi thời gian và bạn có thể kết nối chúng với Arduino của mình một cách dễ dàng. Đây là một ví dụ về cách bạn có thể làm điều đó.


+1 - Giải pháp RTC đặc biệt tốt nếu bạn muốn độ chính xác cao hơn MCU có thể cung cấp cho bạn.
Ricardo

1
@Ricardo - RTC dường như không chính xác hơn MCU với tinh thể đồng hồ sử dụng một trong các bộ định thời phần cứng của nó để tạo ra một ngắt định kỳ; những gì nó thường làm cho bạn đang theo dõi trong tình trạng mất điện và có lẽ một số kiến ​​thức về các kế hoạch lịch.
Chris Stratton

1
Afaik uno không sử dụng bit thạch anh một bộ cộng hưởng gốm cho đồng hồ của nó, do đó với độ chính xác thấp hơn nhiều so với rtc.
jfpoilpret

@ChrisStratton - Phải. Điểm lấy. RTC sẽ là lựa chọn tốt hơn nhiều nếu OP phải mở hoặc đóng cửa vào một thời điểm nhất định trong ngày.
Ricardo

7

Bạn có thể sử dụng ngắt cơ quan giám sát và để MCU ngủ trong khi chờ đợi và tiết kiệm điện.

Nhưng lưu ý rằng bạn sẽ chỉ tiết kiệm điện nếu bảng của bạn cũng lưu nó. Điều đó có nghĩa là bạn phải có một bộ điều chỉnh điện áp thấp thay vì các bộ điều chỉnh thông thường trang bị cho các bo mạch Arduino phổ biến nhất, chẳng hạn như Uno. Mặt khác, MCU của bạn có tiết kiệm năng lượng hay không nếu bảng của bạn không.

Đây là mã (chưa được kiểm tra):

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

Mã tôi đã sao chép là từ trang này: Arduino công suất thấp sử dụng Timer Watchdog .


1

Bạn có sẵn một giấc ngủ (không dấu int giây) không?

Nếu không, điều này sẽ cho phép bạn trì hoãn () một thời gian rất dài:

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

Tôi có thể thử điều này nếu tôi không quản lý để có được một rtc như Tom nói. Cảm ơn đã giúp đỡ!
Fred Pannekoek

1

Điều này sẽ làm việc:

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

        delay(1000);
        p++;

}

4
không phải là giải pháp tốt nhất và OP yêu cầu trong 12 giờ chứ không phải 2 phút.
Madivad

1

Tôi chỉ sử dụng cho các vòng lặp khi tôi không muốn làm công cụ ở giữa:

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
Giải thích làm thế nào điều này là tốt hơn so với đơn giản delay(43200000).

1
Vâng, để bắt đầu, sẽ dễ dàng hơn để sửa đổi bao lâu bạn muốn chờ đợi. Chỉ cần thay đổi số cho mỗi giờ, phút và giây mà không cần phải chuyển đổi thành milisecond.
GeneCode
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.