Ritardo molto lungo () possibile?


9

Sto cercando di aprire e chiudere una piccola porta che dovrebbe aprirsi o chiudersi ogni 12 ore. Mi chiedevo se potevo semplicemente creare un piccolo script in loop con un ritardo () per 12 ore, ritardo (43 200 000 000); Suppongo? Tuttavia, non ho idea se sia possibile e / o raccomandabile. Qualche feedback / alternativa (se necessario) sarebbe bello :)


ok, penso che il ritardo abbia un massimo di 65535 µs, ma ora ho bisogno di un'alternativa ...
Fred Pannekoek,

4
Il cronometraggio in sistemi più maturi, solo MCU, viene solitamente programmato programmando un canale timer hardware dell'MCU per generare periodicamente un interrupt e quindi contando questi - che consente al processore di fare altre cose nel frattempo, ed è cumulativamente accurato come il cristallo dell'orologio.
Chris Stratton,

3
L'uso del ritardo amplifica un errore ambientale sempre così lieve. È meglio usare un interrupt per cronometrare un periodo buono noto e poi contare da lì. Ecco una prova di concetto sul mio sito personale: blog.linformatronics.nl/213/electronics/…
jippie

1
Se non deve essere perfettamente cronometrato, puoi usare cose non convenzionali, come un sensore di luce per rilevare mattina e sera.
The Guy with The Hat,

sì, ci ho pensato, tuttavia ho solo una piccola parte del rivelatore di luce e non sono sicuro di come proteggerlo dalle intemperie (la porticina è fuori)
Fred Pannekoek,

Risposte:


10

Il metodo dell'orologio in tempo reale è il modo più preciso ma altrimenti utilizza millis

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

Ciò ritarderà fino a ca. 4294967295 ms (2 ^ 32-1) o 49 giorni, dopodiché il timer raggiungerà il valore distartMillis


1
Cosa c'è di sbagliato nel solo utilizzo delay(LONG_DELAY_MS)? L' implementazione di arduino accetta long senza segno. Inoltre, non sono del tutto sicuro che il codice funzioni correttamente quando si millis()avvolge ed è più piccolo distartMillis
Gerben

Il ritardo rende il tuo arduino completamente inattivo durante l'attesa se ho ragione. Non so come funzionerà quando i millis sono tornati a 0.
Fred Pannekoek,

@Gerben roba buona, mettilo come una risposta!
geometrikal,

2
L'overflow di @FredPannekoek funzionerà correttamente, purché venga utilizzato il tempo non firmato .
geometrikal,

1
@ 23ars Il motivo principale per cui Arduino ha così tanto successo è la sua libreria di astrazione hardware facile da usare, se sei contrario alle funzioni delle librerie ti stai limitando un po '. Comunque, la funzione dei commenti è di migliorare la risposta, se hai una soluzione migliore, scrivi la tua risposta. ;)
geometrikal,

7

delay()ha i suoi usi, ma per lunghi ritardi non va bene. Dice semplicemente al microcontrollore di non fare nulla per i xcicli di clock. Durante quel periodo, il tuo Arduino non può fare nient'altro.

La tua scommessa migliore sarebbe quella di usare una cosa chiamata Real Time Clock (RTC). Questi chip sono realizzati appositamente per tenere traccia del tempo e puoi collegarli facilmente al tuo Arduino. Ecco un esempio di come potresti farlo.


+1: la soluzione RTC è particolarmente utile se si desidera una maggiore precisione di quella che la MCU può offrire.
Ricardo,

1
@Ricardo - è improbabile che un RTC sia più preciso di un MCU con un cristallo di orologio che utilizza uno dei suoi timer hardware per attivare un interrupt periodico; ciò che di solito ti dà è il monitoraggio della perdita di potenza e forse una certa conoscenza degli schemi del calendario.
Chris Stratton,

1
Afaik Uno non usa un bit di quarzo un risuonatore ceramico per il suo orologio, quindi con molta meno precisione di un RTC.
jfpoilpret,

@ChrisStratton - Giusto. Punto preso. L'RTC sarà un'opzione molto migliore se l'OP deve aprire o chiudere la porta a una determinata ora del giorno.
Ricardo,

7

È possibile utilizzare l'interruzione del watchdog e far dormire l'MCU in attesa e risparmiare energia.

Ma nota che risparmierai energia solo se la tua scheda la salva. Ciò significa che devi avere un regolatore di tensione a bassa quiescenza invece dei soliti regolatori che equipaggiano le schede Arduino più comuni, come Uno. Altrimenti, non importa se la tua MCU risparmia energia se la tua scheda no.

Ecco il codice (non testato):

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

Il codice che ho copiato proviene da questa pagina: Arduino a basso consumo utilizzando il timer di watchdog .


1

Hai un sonno (secondi int non firmati) disponibile?

In caso contrario, ciò consentirebbe di ritardare () molto a lungo:

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

Potrei provare questo se non riesco a ottenere un RTC come ha detto Tom. Grazie dell'aiuto!
Fred Pannekoek,

1

Questo funzionerà:

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

        delay(1000);
        p++;

}

4
non è la soluzione migliore e l'OP ha richiesto 12 ore, non 2 minuti.
Madivad,

1

Uso solo per i loop quando non voglio fare cose tra:

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
Spiegare come sia meglio di un semplice delay(43200000).

1
Bene, per cominciare sarebbe più facile modificare il tempo che vuoi aspettare. Basta cambiare il numero per ogni ora, minuti e secondi senza la necessità di convertire in millisecondi.
GeneCode
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.