Programador horario con Arduino

¡Hola a tod@s!

Últimamente estoy inmerso en un proyecto con Arduino. El proyecto en cuestión trata el diseño y programación de un controlador para la Pecera del Quinto. Uno de los primeros escollos a resolver es el programador horario y para ello he hecho la siguiente función. La función between(..) permite saber si la hora actual (o cualquier otra) está entre dos horas diferentes, además permite incluir una hora final en el siguiente día (ver ejemplo).

Código de la función:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
 * Between is a method to check if current time is between two different times (initial time and final time). This method supports a 'final time' in the next day.
 * @param currHour integer (0-23) with the current hour.
 * @param currMinute integer (0-59) with the current minute.
 * @param initHour integer (0-23) with the initial hour.
 * @param initHour integer (0-59) with the initial minute.
 * @param finalHour integer (0-23) with the final hour.
 * @param finalMinute integer (0-59) with the final minute.
 * @return true if the current hour is between the two times (initial and final)
 * @author Oscar Sanchez Montaner (OSanchezMon)
 */
public static boolean between(int currHour, int currMinute, int initHour, int initMinute, int finalHour, int finalMinute) {
    boolean result = false;
 
    // Converting times to minutes.
    int  on = initHour  * 60 +  initMinute;
    int now = currHour  * 60 +  currMinute;
    int off = finalHour * 60 + finalMinute;
 
    // If final time is in the next day...
    if (finalHour < initHour) { // ... must first check if current time is above 12AM (24)...
        if (now > off) {
	    now += 1440; // ... if it is above; increase it 1440 minutes.
	}
	off += 1440; // Final time (for the next day) is always increased 1440 minutes.
    }
    // Development information.
    if (DEBUG_ON) {
        Serial.print("On: "); Serial.print(on); Serial.print(", Now: ");
        Serial.print(now); Serial.print(", Off: "); Serial.println(off);
    }
    // Check if current time is between initial and final time.
    if (now >= on && now < off) {
        result = true;
    }
 
    return result;
}

En el siguiente ejemplo se quiere saber si la hora actual está comprendida entre las 23:10 y las 10:10 (de la mañana siguiente).

Ejemplo de utilización:

1
2
3
4
5
6
7
if (between(hora_actual, minuto_actual, 23, 10, 10, 10)) {
    if (!relay02On) {
      digitalWrite(relay02Pin, HIGH);
      relay02On = true;
      logger("Relay 02 enabled.");
    }
}

Resultados de diferentes casos de prueba:

1
2
3
4
5
6
between(9, 0, 23, 10,  8, 59)); // On: 1390, Now: 1980, Off: 1979 -> false
between(9, 0, 23, 10,  9,  0)); // On: 1390, Now:  540, Off: 1980 -> false
between(9, 0, 23, 10,  9,  1)); // On: 1390, Now:  540, Off: 1981 -> false
between(9, 0, 10, 10,  8, 59)); // On:  610, Now: 1980, Off: 1979 -> false
between(9, 0,  8, 10,  9,  1)); // On:  490, Now:  540, Off:  541 ->  true
between(9, 0,  8, 10,  8, 11)); // On:  490, Now:  540, Off:  491 -> false
  1. uhmmm … no lo veo claro . Que pasa si la hora actual son las 9 de la mañana del primer día ( no el día siguiente). En ese ejemplo el resultado de la funcion sería TRUE y sería incorrecto …. creo.

    • Muchas gracias fran por la aportación. La verdad es que tienes razón, tenemos el primer bug de la función. Como dices el resultado es On: 1390, Now: 1980, Off: 2050, Result: true cuando debería ser false… en cuanto lo tenga resulto publicaré la nueva versión. ¡Un saludo!

      • Hola! Ahora mismo estoy diseñando un sistema de control de iluminacion con 24 canales programables y varios intervalos de tiempo en cada canal. Es por eso que me surgió el problema del cambio de día. El código posteado funciona sin problemas si partimos de la premisa de que se usa el mismo programa de tiempos todos los dias de la semana (como un programador mecánico diario). La cosa se complica un pelín si pretendemos usar programas diferentes para cada día de la semana e incluso tener en cuenta el cambio horario ( por aquello del ahorro energético ) … en fin, he estado dándole vueltas y creo que he llegado a una solucion … quizas no muy elegante, pero solucion al fin y al cabo. Cuando tenga el código listo te lo paso si quieres … por dar ideas mas que nada . Aún no tengo muy claro cual sería el algoritmo mas eficiente en cuanto a recursos de memoria y velocidad de ejecucion … en eso ando, bye!

    • Buenos días fran, ya he solucionado el bug y he añadido resultados de unos casos de pruebas. El error estaba en la comparación if (now < off) que debería ser if (now > off). Un saludo y gracias por visitar el blog.

      • Buenos días! 😀
        Antes no había visto tu actualizacion porque escribí mi comentario en la ventana que tenía abierta desde ayer , sin recargar la página.
        No es por incordiar en una mañana de domingo peeero … sigo sin verlo claro jeje.
        En el tercer caso debería ser TRUE ❓
        Creo que hay que cocinar esto un pelín más.

        • Hola fran, el resultado es correcto. Fíjate que en el tercer caso, que son las 09:00 de hoy y quieres saber si estás entre las 23:00 y las 09:01 de mañana, por eso el resultado es false 😉 . Fijate que la función necesita hoy la actual, hora de inicio y hora de final. En el tercer caso, la hora final son las 09:01 que es “menor” que la hora de inicio, lo que indica que nos referimos al día siguiente. Como la hora actual son las 09:00, ni siquiera todavía la hora actual está en el rango entre hora inicio y hora final. El método está pensado para un programador horario diario, no soporta días de la semana… por ahora 😎 .

  2. ay dios … tengo la cabeza como un bombo de tanto pensar en horas jeje 😯 …. a ver … uhmmm de acuerdo … si la rutina se ejecuta hoy a las 9:00 daría resultado FALSE y sería correcto … pero …. y que pasa cuando se ejecute mañana a las 9:00 ❓ quiero decir, si tenemos este codigo funcionando y hay un relé que tiene que activarse desde las 23:10 de hoy hasta las 9:01 de mañana …. siempre daría false ….. pufff tengo que tomarme un respiro y salir a despejarme o me vuelvo tarumba …. Ya seguiré dándole vueltas mas tarde. Gracias por postear tan rápido … a ver si pillo la idea cuando me despeje 😀

  3. Una pista aunque tarde.
    Coje la hora actual y calcula lo que “pesa” en minutos. Coje la hora programa y haz lo mismo. Compara la cantidad de minutos de los dos.

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>