매우 긴 지연 ()이 가능합니까?


9

나는 12 시간마다 열거 나 닫히는 작은 문을 열고 닫으려고합니다. 12 시간 동안 delay (), delay (43 200 000 000)로 작은 루핑 스크립트를 만들 수 있는지 궁금합니다. 내 생각 엔? 그러나 그것이 가능하고 / 혹은 추천 가능한지 모르겠습니다. 일부 피드백 / 대안 (필요한 경우)이 좋을 것입니다 :)


좋아, 지연이 최대 65535 µs라고 생각하지만 지금은 대안이 필요하다 ...
Fred Pannekoek

4
보다 성숙한 MCU 독립 시스템의 타이밍은 일반적으로 인터럽트를 주기적으로 발생하도록 MCU의 하드웨어 타이머 채널을 프로그래밍 한 다음이를 계산하여 수행됩니다. 즉, 프로세서가 그 동안 다른 작업을 수행 할 수 있도록하며 시계 크리스탈.
Chris Stratton

3
지연을 사용하면 약간의 오버 헤드 오류가 확대됩니다. 인터럽트를 사용하여 알려진 양호한 시간을 기록한 다음 계산하는 것이 좋습니다. 내 개인 웹 사이트의 개념 증명은 다음과 같습니다. blog.linformatronics.nl/213/electronics/…
jippie

1
완벽하게 시간을 정할 필요가 없다면 아침과 저녁을 감지하기 위해 빛 센서와 같은 비 전통적인 것을 사용할 수 있습니다.
모자와 사람

그렇습니다, 나는 그것에 대해 생각했습니다. 그러나 나는 작은 빛 탐지기 부분 만 가지고 있으며 날씨로부터 그것을 보호하는 방법을 잘 모릅니다 (작은 문은 바깥에 있습니다)
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)되었습니까? 아두 이노 구현은 서명되지 않은 갈망을 받아들입니다. 또한 millis()startMillis
랩할

지연하면 내가 올바른지 기다리는 동안 arduino가 완전히 비활성화됩니다. millis가 0으로 돌아 왔을 때 이것이 어떻게 작동하는지 모르겠습니다.
Fred Pannekoek

@ Gerben 좋은 물건, 답변으로 넣어!
geometrikal

2
부호없는 long을 사용하는 한 @FredPannekoek overflow가 정상적으로 작동합니다 .
geometrikal

1
@ 23ars Arduino가 성공한 주된 이유는 사용하기 쉬운 하드웨어 추상화 라이브러리입니다. 라이브러리의 함수에 반대하는 경우 다소 제한적입니다. 어쨌든, 의견의 기능은 답변을 향상시키는 것입니다. 더 나은 해결책이 있다면 자신의 답변을 작성하십시오. ;)
geometrikal

7

delay()그 용도가 있지만 오래 지연되면 좋지 않습니다. 단순히 마이크로 컨트롤러에게 x클럭 사이클에 대해 아무 것도하지 말라고 지시합니다 . 그 시간 동안 Arduino는 다른 작업을 수행 할 수 없습니다.

최선의 방법은 RTC (Real Time Clock)라는 것을 사용하는 것입니다. 이 칩은 특별히 시간을 추적하기 위해 만들어졌으며 Arduino에 쉽게 연결할 수 있습니다. 다음은 그 방법에 대한 예입니다.


+1-RTC 솔루션은 MCU가 제공 할 수있는 것보다 더 높은 정확도를 원할 때 특히 좋습니다.
Ricardo

1
@Ricardo-RTC는 하드웨어 타이머 중 하나를 사용하여 주기적 인터럽트를 발생시키는 클록 크리스탈이있는 MCU보다 더 정확하지는 않습니다. 일반적으로 전력 손실을 추적하고 일정 계획에 대한 지식이 필요합니다.
Chris Stratton

1
Afaik uno는 클럭에 쿼츠 비트 세라믹 공진기를 사용하지 않으므로 rtc보다 정확도가 떨어집니다.
jfpoilpret

@ChrisStratton-맞습니다. 요점을 알았어. OP가 주어진 시간에 문을 열거 나 닫아야하는 경우 RTC가 훨씬 더 나은 옵션입니다.
Ricardo

7

대기하고 전력을 절약하면서 워치 독 인터럽트를 사용하고 MCU를 절전 상태로 유지할 수 있습니다.

그러나 보드가 절약 할 경우에만 전력을 절약 할 수 있습니다. 즉, Uno와 같이 가장 일반적인 Arduino 보드를 장착하는 일반적인 레귤레이터 대신 낮은 대기 전압 레귤레이터를 사용해야합니다. 그렇지 않으면 보드가 그렇지 않은 경우 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

사용할 수있는 수면 (서명없는 초)이 있습니까?

그렇지 않으면 매우 오래 지연시킬 수 있습니다.

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이 말한 것처럼 rtc를 얻지 못하면 이것을 시도 할 수 있습니다. 도움을 주셔서 감사합니다!
Fred Pannekoek

1

이것은 작동합니다 :

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

        delay(1000);
        p++;

}

4
최상의 솔루션이 아니었고 OP는 2 분이 아닌 12 시간 동안 요청했습니다.
Madivad

1

나는 중간에 물건을하고 싶지 않을 때 for 루프를 사용합니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.