Timers con Arduino

Tema en 'Hagalo usted mismo' comenzado por aztlanco, 5 Septiembre 2016.

  1. aztlanco

    aztlanco Patrón de las profundidades

    Se incorporó:
    18 Octubre 2004
    Mensajes:
    1,317
    Me gusta recibidos:
    240
    Género:
    Hombre
    Ocupación:
    Ing. en Sistemas
    Localización:
    Madrid, España
    Hola:

    Me ha escrito por privado @Danyelcor@Danyelcor preguntándome:
    Luego entonces lo contesto en el foro a modo publico para ver si esto le sirve a mas aventureros del Arduino.

    Arduino, en sus múltiples sabores (Nano, Mega, One, etc) utiliza su IDE para programarlo, y en esencia la programación es "SIMPLE", mas para aquellos que tienen nociones de programación orientada a objetos, para los que no, pues ... aquí estamos para ver si los confundimos mas....

    Bueno al toro...

    Todo programa (sketch) en arduino tiene un par de funciones, el SETUP y el LOOP sin ellos no puede funcionar.
    El SETUP es la función INICIAL, en cuanto el arduino recibe corriente corriente es lo primero que ejecuta, así pues nos sirve para prepararlo para la acción.
    El LOOP es lo que estará haciendo el arduino mientras tenga corriente y después de hacer lo que tenia en el SETUP, el código contenido en LOOP, lo repetirá hasta el infinito cada vez que termine de ejecutarlo, ejemplo:
    Conectamos el Arduino, su memoria, se llena con las variables declaradas, ejecuta el SETUP, termina y ejecuta el LOOP, termina y ejecuta el LOOP, .... hasta que deja de tener corriente.

    Una vez que entendemos esto hemos ganado la mitad del camino.

    Vale vamos a pensar en lo que plantea @Danyelcor@Danyelcor sin darle muchas vueltas y lo mas sencillo posible:
    1. Supondré que ha comprado un reloj DS3232RTC, por que?? por que el arduino no tiene reloj, hay que ponerle uno, y si no lo han comprado esta la opción que yo les recomiendo, se conecta a la salida de 5v, gnd (tierra) y a los puertos SLA y SCD del tu arduino, dependerá del sabor del mismo para saber donde esta cada puerto.
    2. Supondré que tiene una placa de relé, que ha conectado a corriente (5v) y gnd, y ha asignado el puerto 6 al primer relé.

    Asi pues con estas suposiciones el sketch o programa seria algo similar a esto:
    Código:
    #include <DS3232RTC.h>
    #include <Time.h>
    #define rele_luz 6
    String encendido = "10:00:00";
    String apagado = "20:00:00";
    
    Aquí le digo que tome la librería del reloj, la librería para el uso de tiempo, defino el puerto al que conecte el relé, le digo una hora de encendido y una de apagado.
    ahora vamos ha hacer la función SETUP, que como dijimos será lo primerito que haga cuando reciba corriente:
    Código:
    void setup() {
     setSyncProvider(RTC.get);
     pinMode(rele_luz, OUTPUT);
    }
    
    Bueno como se imaginaran lo primero es decirle que recupere los datos del reloj, vaya sincronizarlo con el arduino.
    La segunda línea le decimos que el puerto al que conectamos el relé, y lo usaremos como puerto de salida.

    ahora el Loop
    Código:
    void loop() {
     if (getTime()==encendido) {
     rel_state[rele_luz]=HIGH;
     }
     if (getTime()==apagado) {
     rel_state[rele_luz]=LOW;
     }
    }
    
    String getTime() {
      String hr = "";
      if (hour()<10) { hr += "0"; }
      hr.concat(hour());
      hr += ":";
      if (minute()<10) { hr += "0";}
      hr.concat(minute());
      hr += ":";
      if (second()<10) { hr += "0"; }
      hr.concat(second());
      return hr;
    }
    
    Dentro del LOOP verificamos si la hora actual coincide con la hora de encendido si es el caso ponemos el pin en HIGH o mandando señal con lo que enciende el relé.
    Si coincide con la hora de apagado lo ponemos en LOW y deja de mandar señal con lo que el relé se apaga.

    Utilizo este ejemplo para mostrar como haríamos otra función y la llamaríamos en este caso getTime, que arma una cadena con la cual comparamos la hora.

    Así tendríamos un time que encendiera a las 10 am y apagara a las 20 hrs, para modificar este horario bastaría con modificar esos horarios.

    Ahora pongamos los 4 timers....

    Código:
    #include <DS3232RTC.h>
    #include <Time.h>
    #define rele_luz_1 6
    #define rele_luz_2 6
    #define rele_luz_3 6
    #define rele_luz_4 6
    String encendido_1 = "09:00:00";
    String encendido_2 = "09:15:00";
    String encendido_3 = "09:45:00";
    String encendido_4 = "10:00:00";
    String apagado_1 = "20:00:00";
    String apagado_2 = "20:15:00";
    String apagado_3 = "20:30:00";
    String apagado_4 = "21:00:00";
    void setup() {
     setSyncProvider(RTC.get);
     pinMode(rele_luz_1, OUTPUT);
     pinMode(rele_luz_2, OUTPUT);
     pinMode(rele_luz_3, OUTPUT);
     pinMode(rele_luz_4, OUTPUT);
    }
    String getTime() {
      String hr = "";
      if (hour()<10) { hr += "0"; }
      hr.concat(hour());
      hr += ":";
      if (minute()<10) { hr += "0";}
      hr.concat(minute());
      hr += ":";
      if (second()<10) { hr += "0"; }
      hr.concat(second());
      return hr;
    }
    void loop() {
     if (getTime()==encendido_1) {
     rel_state[rele_luz_1]=HIGH;
     }
     if (getTime()==apagado_1) {
     rel_state[rele_luz_1]=LOW;
     }
     if (getTime()==encendido_2) {
     rel_state[rele_luz_2]=HIGH;
     }
     if (getTime()==apagado_2) {
     rel_state[rele_luz_2]=LOW;
     }
     if (getTime()==encendido_3) {
     rel_state[rele_luz_3]=HIGH;
     }
     if (getTime()==apagado_3) {
     rel_state[rele_luz_3]=LOW;
     }
     if (getTime()==encendido_4) {
     rel_state[rele_luz_4]=HIGH;
     }
     if (getTime()==apagado_4) {
     rel_state[rele_luz_4]=LOW;
     }
    }
    
    Y bueno este seria el tema sencillo y básico, se pueden usar arrays, y otras cosas para hacerlo pero digamos que como intro es lo que mas simple, si quieren saber como hacer mas cosas.... pongan sus dudas con el código y vamos haciendo cosillas...

    Saludos a todos.
     
    • Danyelcor

      Danyelcor Aprendiz de arrecife

      Se incorporó:
      22 Agosto 2016
      Mensajes:
      154
      Me gusta recibidos:
      26
      Género:
      Hombre
      Ocupación:
      Ing. Biomedico
      Localización:
      Jalisco
      Maestro era lo que no entendía entonces se tiene que poner un reloj, hasta me da risa mi idea principal. Como no sabia como programar eso se me ocurría que cada que aprera un push le diera una hora x para que iniciará el conteo pero obvioamente no es nada práctico con esto ya se. Ahora solo falta ponerle un sleep para que no esté adquiriendo datos a lo "tonto" y no se sobrecaliente. También a esto le quiero incluir el sensado de temperatura. Una pregunta más debo bajar la librería de time para programar el reloj no?
      Muchas gracias por la ayuda
       
    • Badstraw

      Badstraw Webmaster Miembro del STAFF

      Se incorporó:
      21 Agosto 2010
      Mensajes:
      10,946
      Me gusta recibidos:
      1,825
      Localización:
      Estado de México
      Increíble post @aztlanco@aztlanco, te volaste la barda al ayudar con código ..

      ¿Entones recomiendas más el que propones al popular DS1307?

      ¿Crees que influya la calidad del cristal para la precisión de la hora?
       
    • Danyelcor

      Danyelcor Aprendiz de arrecife

      Se incorporó:
      22 Agosto 2016
      Mensajes:
      154
      Me gusta recibidos:
      26
      Género:
      Hombre
      Ocupación:
      Ing. Biomedico
      Localización:
      Jalisco
      Yo he leído que si hay un mundo diferencia pero la diferencia no la hacer el cristal que la hace el control de temperatura que tiene integrado el que gradúa la frecuencia para que no se caliente
       
    • Badstraw

      Badstraw Webmaster Miembro del STAFF

      Se incorporó:
      21 Agosto 2010
      Mensajes:
      10,946
      Me gusta recibidos:
      1,825
      Localización:
      Estado de México
      ¿Pudieras ampliar un poquito más la información? No me quedó muy claro a lo que te refieres..
       
    • Danyelcor

      Danyelcor Aprendiz de arrecife

      Se incorporó:
      22 Agosto 2016
      Mensajes:
      154
      Me gusta recibidos:
      26
      Género:
      Hombre
      Ocupación:
      Ing. Biomedico
      Localización:
      Jalisco
      Si es que yo leí que el DS3231 ya es más completo que el DS1307 por que el 1307 tiende a calentarse el cuarzo que es el que te da las oscilaciones para el horario, entonces al calentarse el cuarzo comienza a fallar su oscilación por lo que el horario se puede adelantar o atrasar. El 3231 ya tiene un cuarzo más resistente y cuenta con un termómetro el cual permite bajar la intensidad cuando este se caliente por lo que es más seguro en proyectos donde estará conectado por más tiempo. Lo que no se es que si al 1307 se le baja la intensidad por medio de arduino con un sleep se pueda evitar este calentamiento
       
    • Danyelcor

      Danyelcor Aprendiz de arrecife

      Se incorporó:
      22 Agosto 2016
      Mensajes:
      154
      Me gusta recibidos:
      26
      Género:
      Hombre
      Ocupación:
      Ing. Biomedico
      Localización:
      Jalisco
    • aztlanco

      aztlanco Patrón de las profundidades

      Se incorporó:
      18 Octubre 2004
      Mensajes:
      1,317
      Me gusta recibidos:
      240
      Género:
      Hombre
      Ocupación:
      Ing. en Sistemas
      Localización:
      Madrid, España
      El problema esta en el uso continuado, el cuarzo del popular DS1307 como bien comenta Danyelcor se calienta, NO hay forma de enfriarlo, su rango de operación es muy limitado, lo que hace que al poco tiempo tu aplicación tenga saltos temporales.

      El DS3231 o mejor aun el DS3232, añade un regulador de temp que le permite estar trabajando durante mas tiempo sin riesgo de saltos. por ende mas precisión.

      Ahora el tema del SLEEP... salvo cosas puntuales yo no lo uso, lo suyo es que el arduino se encuentre sensando y este dentro del loop todo el tiempo, no se sobre calienta si tiene la corriente adecuada, sabemos que el arduino puede trabajar desde 5v a 12v yo te recomiendo que lo alimentes con 10v, compras una fuente de poder de 12 y le regulas la entrada a 10v como??? con un LM7810 que es un regulador de voltaje positivo. Así garantizas que recibe constantemente 10v ni mucho ni poco.

      La idea de contar el tiempo no es descabellada, imagina que conectaras el termómetro... y quieres una lectura cada 10 segundos, no pondrás todas las horas "00:00:10" y luego "00:00:20", seria loco... lo que haces es añadir en el loop un timer asi:

      Código:
      void loop() {
          static unsigned long temperaturaTimer = millis();
      
         if (millis()-temperaturaTimer >= 10000) {
            sensors.requestTemperature();
            float temp = sensors.getTempC(temometro);
            temperaturaTimer = millis();
         }
      
          if (getTime()==encendido_1) {
              rel_state[rele_luz_1]=HIGH;
          }
      
      ... //Bueno y el resto escrito anteriormente //
      }
      
      A ver que hemos hecho???
      millis() es una función de arduino que te dice el tiempo que lleva encendido, y cuando se desborda (casi cada 50 días) vuelve a cero.

      Asi pues la primer vez que se ejecuta el LOOP, toma el tiempo de encendido y lo asigna a la variable temperaturaTimer, posteriormente lo que hace es al tiempo actual le resta el tiempo que le grabamos, si han pasado 10000 milisegundos (es decir 10 segundos) entonces lee la temperatura y reinicia el timer, si aun no ha pasado pues nada no lo lee...

      Por que digo que no seria tan descabellado, por que podrías poner el encendido a 24 horas, es decir 86400000 milisegundos, y cada 24 hrs se encendería la luz, el problema esta cuando el contador (los 50 días mencionados anteriormente) se vuelven 0 seguro te da un desfase.

      Pero con estos timers puedes programar tareas recursivas que se realizan cada n segundos, otro ejemplo seria que pones una pantalla (ojo de cualquier tipo) y pones un reloj en formato HH:MI:SS y quieres que se vaya actualizando cada segundo... pues un timer para el reloj y cada 1000 milisegundos repintas la pantalla....

      Ahora imagina que en algún sitio del código pones un SLEEP, al traste con tus timers. por que un sleep obliga a que el resto del código no se ejecute que se detenga por completo el procesador... asi pues lo que tenias cada 10 segundos ... se hará en "n"
       
    • aztlanco

      aztlanco Patrón de las profundidades

      Se incorporó:
      18 Octubre 2004
      Mensajes:
      1,317
      Me gusta recibidos:
      240
      Género:
      Hombre
      Ocupación:
      Ing. en Sistemas
      Localización:
      Madrid, España
      Y por cierto la libreria Time te sirve para hacer monerías con la función getTime que te describo en el ejemplo... para controlar el reloj necesitas <DS3232RTC.h>
       
    • Danyelcor

      Danyelcor Aprendiz de arrecife

      Se incorporó:
      22 Agosto 2016
      Mensajes:
      154
      Me gusta recibidos:
      26
      Género:
      Hombre
      Ocupación:
      Ing. Biomedico
      Localización:
      Jalisco
      Hola buenos días, tengo una duda, como Ignoras la fecha? Por que a la hora de comparar la hora para que arduino la tome, no la toma creo que es por que arroja la fecha primero
       
    • aztlanco

      aztlanco Patrón de las profundidades

      Se incorporó:
      18 Octubre 2004
      Mensajes:
      1,317
      Me gusta recibidos:
      240
      Género:
      Hombre
      Ocupación:
      Ing. en Sistemas
      Localización:
      Madrid, España
      He puesto una función llamada getTime
      Código:
      String getTime() {
        String hr = "";
        if (hour()<10) { hr += "0"; }
        hr.concat(hour());
        hr += ":";
        if (minute()<10) { hr += "0";}
        hr.concat(minute());
        hr += ":";
        if (second()<10) { hr += "0"; }
        hr.concat(second());
        return hr;
      }
      Que formateo el dato para no tomar el dia... esta en el codigo
       

    ¡Ayúdanos! Comparte en:

    Cargando...