Muy largo retraso () posible?


9

Estoy tratando de abrir y cerrar una pequeña puerta que debería abrirse o cerrarse cada 12 horas. Me preguntaba si podría hacer un pequeño script de bucle con un retraso () durante 12 horas, retraso (43 200 000 000); ¿Supongo? Sin embargo, no tengo idea si eso es posible y / o recomendable. Algunos comentarios / alternativas (si es necesario) serían buenos :)


ok, creo que el retraso tiene un máximo de 65535 µs, pero ahora necesito una alternativa ...
Fred Pannekoek

44
La sincronización en sistemas más maduros, solo MCU, generalmente se realiza mediante la programación de un canal de temporizador de hardware de la MCU para disparar una interrupción periódicamente, y luego contarlos, lo que permite que el procesador haga otras cosas mientras tanto, y es acumulativamente tan preciso como el Reloj de cristal.
Chris Stratton

3
El uso de la demora aumentará un error general muy leve. Es mejor usar una interrupción para cronometrar un período bueno conocido y luego contar desde allí. Aquí hay una prueba de concepto en mi sitio web personal: blog.linformatronics.nl/213/electronics/…
jippie

1
Si no tiene que estar perfectamente sincronizado, puede usar cosas poco convencionales, como un sensor de luz para detectar la mañana y la tarde.
el individuo con el sombrero

Sí, pensé en eso, sin embargo, solo tengo una pequeña parte del detector de luz y no estoy seguro de cómo protegerlo del clima (la pequeña puerta está afuera)
Fred Pannekoek

Respuestas:


10

El método de reloj en tiempo real es la forma más precisa, pero de lo contrario use millis

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

Esto retrasará hasta aprox. 4294967295 ms (2 ^ 32-1) o 49 días, después de los cuales el temporizador alcanzará el valor destartMillis


1
¿Qué hay de malo con solo usar delay(LONG_DELAY_MS)? La implementación de arduino acepta largos sin firmar. Tampoco estoy completamente seguro de que el código funcione correctamente cuando se millis()envuelve, y es más pequeño questartMillis
Gerben

El retraso hace que su arduino esté completamente inactivo mientras espera si estoy en lo correcto. No sé cómo actuará esto cuando Millis vuelva a 0.
Fred Pannekoek

@Gerben cosas buenas, ponlo como respuesta!
geometrikal

2
El desbordamiento de @FredPannekoek funcionará bien, siempre que se use sin firmar .
geometrikal

1
@ 23ars La razón principal por la que Arduino tiene tanto éxito es su biblioteca de abstracción de hardware fácil de usar, si está en contra de las funciones de las bibliotecas, se está limitando un poco. De todos modos, la función de los comentarios es mejorar la respuesta, si tiene una mejor solución, escriba su propia respuesta. ;)
geometrikal

7

delay()tiene sus usos, pero por largas demoras no es bueno. Simplemente le dice al microcontrolador que no haga nada durante los xciclos de reloj. Durante ese tiempo, tu Arduino no puede hacer nada más.

Su mejor opción sería usar una cosa llamada reloj de tiempo real (RTC). Estos chips están hechos específicamente para realizar un seguimiento del tiempo, y puede conectarlos a su Arduino con facilidad. Aquí hay un ejemplo de cómo podrías hacer eso.


+1: la solución RTC es especialmente buena si desea más precisión que la MCU.
Ricardo

1
@Ricardo: no es probable que un RTC sea más preciso que un MCU con un cristal de reloj que usa uno de sus temporizadores de hardware para disparar una interrupción periódica; lo que sí suele obtener es rastrear la pérdida de energía y tal vez algún conocimiento de los esquemas de calendario.
Chris Stratton

1
Afaik uno no utiliza un bit de cuarzo como resonador de cerámica para su reloj, por lo tanto, con mucha menos precisión que un rtc.
jfpoilpret

@ChrisStratton - Correcto. Punto a favor. El RTC será una opción mucho mejor si el OP tiene que abrir o cerrar la puerta en un momento determinado del día.
Ricardo

7

Puede usar la interrupción de vigilancia y hacer que su MCU duerma mientras espera y ahorre energía.

Pero tenga en cuenta que solo ahorrará energía si su placa también lo ahorra. Eso significa que debe tener un regulador de bajo voltaje de reposo en lugar de los reguladores habituales que equipan las placas Arduino más comunes, como la Uno. De lo contrario, no importa si su MCU ahorra energía si su placa no lo hace.

Aquí está el código (no probado):

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

El código que copié es de esta página: Arduino de baja potencia con el temporizador de vigilancia .


1

¿Tiene un sueño (sin int int segundos) disponible?

Si no, esto le permitiría retrasar () mucho tiempo:

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

Podría intentar esto si no logro obtener un rtc como dijo Tom. ¡Gracias por ayudar!
Fred Pannekoek

1

Esto funcionará:

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

        delay(1000);
        p++;

}

44
no es la mejor solución y el OP solicitó 12 horas, no 2 minutos.
Madivad

1

Solo uso para bucles cuando no quiero hacer cosas en el medio:

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

44
Explicando cómo esto es mejor que un simple delay(43200000).

1
Bueno, para empezar, sería más fácil modificar cuánto tiempo quieres esperar. Simplemente cambie el número de cada hora, minutos y segundos sin necesidad de convertirlo en milisegundos.
GeneCode
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.