Una función para imprimir el tiempo en LCD o Serial, correctamente.

Hola, que tal, espero que se encuentre bien, me encuentro trabajando en un proyecto que tiene
muchísimos timers y bueno, me canse de ver que la LCD mostrara, " Faltan 595 Segundos".

Así que invertí un poco de tiempo en hacer esta función para mostrarlo correctamente, para mi y dentro de lo que tengo planeado hacer las ventajas son las siguientes;

---> Una sola función puede imprimir cualquier timer de mi programa.
---> Es relativamente liviana
---> Puedo re-utilizar todas las variables y ahorrarme la necesidad de tener un puño de variables que
hagan lo mismo.
---> Los datos puedo imprimirlos en serial y en LCD si asi lo requiero.
---> Compatible con todos los sof-delay escritos en Milisegundos (solo requerimos declarar los define)

Aquí el código;

#define _SEGUNDO   1000                        //definimos un segundo 
#define _MINUTO    (60UL*_SEGUNDO)     //definimos un minuto
#define _HORA      (60UL*_MINUTO)         //definimos una hora

char data[21]       = "";                             //en esta linea mostraremos el resultado en display o Serial 
int  curSec           = 0;                              //solo para saber que ha pasado un segundo  
int  pasSec           = 0;                   
unsigned long delay1inSec = 0;                 //transporta nuestro tiempo a la funcion     

unsigned long delay1 = 10 * _MINUTO;      //definimos un delay  para el ejemplo 
unsigned long time1  = 0;                         //tiempo del cual se comienza el delay 



void setup() 
{
  Serial.begin (9600); 
  Serial.print("El delay es de "); Serial.println(delay1); 
  time1 = millis();                         //inicializamos el tiempo aqui. 

 // Serial.print("MIN: "); Serial.println(NumMin); 
 // Serial.print("SEC: "); Serial.println(NumSec); 
}

void loop() 
{
  if (millis() - time1 < delay1)            //empezamos el timer 
    {
      curSec = (delay1 - time1) - millis();        //estimamos cual es el segundo del conteo en le que estamos
      curSec =      curSec /1000;               
      delay1inSec = (delay1 - time1) - millis();   //pasamos este valor a una variable separada 

      if(curSec != pasSec)                  //si ha pasado un segundo actualizamos el display 
      {
         displayTime();                     //funcion que actualiza el display 
         Serial.println(data);              //imprimimos en serial, lo mismo que en LCD 
         pasSec = curSec;                     
      }
    }
}

void displayTime()
{
  int  NumMin  = 0; 
  int  NumSec  = 0;
  
  NumMin = delay1inSec / _MINUTO  ;  //DIVIDIMOS ENTRE MINUTO, PARA SABER CUANTOS MINUTOS ENTEROS HAY 
  NumSec = ((delay1inSec - (NumMin * _MINUTO)) / _SEGUNDO);   
  sprintf(data, "Tiempo = %02i:%02i", NumMin, NumSec); 
}

Y bueno, aquí la salida por serial;

El delay es de 600000
Tiempo = 10:00
Tiempo = 09:59
Tiempo = 09:58
Tiempo = 09:57
Tiempo = 09:56
Tiempo = 09:55
Tiempo = 09:54
Tiempo = 09:53
Tiempo = 09:52
Tiempo = 09:51
Tiempo = 09:50
Tiempo = 09:48
Tiempo = 09:47
Tiempo = 09:46
Tiempo = 09:45
Tiempo = 09:44
Tiempo = 09:43
Tiempo = 09:42
Tiempo = 09:41
Tiempo = 09:40
Tiempo = 09:39
Tiempo = 09:38
Tiempo = 09:37
Tiempo = 09:36
Tiempo = 09:35
Tiempo = 09:34
Tiempo = 09:33
Tiempo = 09:32
Tiempo = 09:31
Tiempo = 09:30
Tiempo = 09:29
Tiempo = 09:28
Tiempo = 09:27
Tiempo = 09:26
Tiempo = 09:25
Tiempo = 09:24
Tiempo = 09:23
Tiempo = 09:22
Tiempo = 09:21
Tiempo = 09:20
Tiempo = 09:19
Tiempo = 09:18
Tiempo = 09:17
Tiempo = 09:17
Tiempo = 09:16
Tiempo = 09:15
Tiempo = 09:14
Tiempo = 09:13
Tiempo = 09:12
Tiempo = 09:11
Tiempo = 09:10
Tiempo = 09:09
Tiempo = 09:08
Tiempo = 09:07
Tiempo = 09:06
Tiempo = 09:05
Tiempo = 09:04
Tiempo = 09:03
Tiempo = 09:02
Tiempo = 09:01
Tiempo = 09:00
Tiempo = 08:59
Tiempo = 08:58
Tiempo = 08:57
Tiempo = 08:56
Tiempo = 08:55

Sin mas por el momento, espero que les sirva de algo.
Es fácilmente extensible a horas, siguiendo la misma lógica del ejemplo.

Saludos.
-Alex.

Tengo algunas dudas...

  1. Para que sirve delay1inSec si es casi lo mismo que curSec ?
  2. delay1 no debería ser una constante ?
  3. Para usar sprintf() no se requiere ninguna librería ?

Gracias de antemano.

  1. Para que sirve delay1inSec si es casi lo mismo que curSec ?

Es una variable para millis().

  1. delay1 no debería ser una constante ?

Podría ser una constante pero no altera nada que sea variable, dependiendo del uso de RAM disponible.
De lo contrario coincido con KILE_KG que debería ser un #define o constante.

  1. Para usar sprintf() no se requiere ninguna librería ?

Deberías saber que no se requiere nada usando Arduino. Si con AVR.

surbyte:
Es una variable para millis().

Me referencia a que curSec se toma unos intantes antes que delay1inSec quizas con un par de ciclos de reloj despues asi que son "casi" iguales.

curSec = (delay1 - time1) - millis();        //estimamos cual es el segundo del conteo en le que estamos
curSec =      curSec /1000;               
delay1inSec = (delay1 - time1) - millis();   //pasamos este valor a una variable separada

surbyte:
Deberías saber que no se requiere nada usando Arduino. Si con AVR.

No lo sabia, donde esta escondida la documentación sobre sprintf() ?

AVR no es la linea ATmega de Microchip Technology Inc que llevan los Arduino dentro ? UNO, MINI, NANO, PRO y Duemilanova (Atmega328P) y MEGA (ATmega1280).

Cuando me reviero a AVR hablo deprogramar con ATMEL STUDIO usando el concepto de C con main() y no como hace Arduino que usa setup() loop().

Cuando programas en C para ATMEL debes indicar todas las librerias.

Print Floating Point Numbers in AVR C with Atmel Studio 7

O este usando GCC-AVR

Using sprintf function for float numbers in AVR-GCC