Timer de arduino en comunicacion con una pantalla Nextion

Mi proyecto consta de hacer un descontador de al menos 12 hrs en intervalos de 1 seg. Por lo que uso una pantalla Nextion, el problema es que al poner mas de 9:00 hrs tiene un error y se queda pasmado, al poner arriba de 19 hrs. vuelve a descontar pero con un error y ya que inicia con un tiempo irregular aproximadamente al poner 23:00:00 empieza a descontar desde 04:47:50 cuando deberia empezar en 22:59:59. cabe mencionar que antes de las 9:00:00 el proyecto trabaja de manera correcta espero me puedan ayudar saludos. Por cierto tambien utilizo un rtc3231 para la hora.

cabe mencionar que el codigo excede los 9000 caracteres por lo que adjunto el archivo FgTimer4.ino ,y el de la pantalla tiempo.hmi no acepta este tipo de extension por lo que si alguien lo requiere se lo puedo mandar por correo electronico.

fgTimer4.ino (19 KB)

Edita título y código según normas del foro, lee el privado que te envié con instrucciones.

Creo que, en lo que nos muestras, no has puesto la línea de código donde está "el problema". Supongo que has definido la variable tem de tipo int. La has de definir de tipo long int. Busca en el programa la línea que pone:

    int tem;

Y prueba a añadirle "long" para que quede tal que así:

    long int tem;

Si tienes problemas con asignar lapsos prolongados, también puedes echar una probadita a la librería que voy a adjuntar. Las instrucciones de uso se encuentran en el archivo “Léeme.txt”.

La función que imprime el tiempo yo la resumiría así:

void imprimirTiempo(unsigned long ms, char* string) { // El array ingresado debe tener al menos 9 bytes/caracteres de tamaño
 ms /= 1000;
 byte s = ms % 60;
 ms /= 60;
 byte m = ms % 60;
 sprintf(string, "%d:%02d:%02d", ms / 60, m, s);
}

Nótese que de primer parámetro recibe el tiempo en milisegundos; y es justo lo que retorna una función de la librería que acabo de mencionar.
En el segundo parámetro se coloca el nombre de un array de char; que viene siendo donde se almacenará la conversión a texto para posteriormente ser impreso en cualquier pantalla de lo que sea.

Countdown.zip (5.87 KB)

Olvidé mencionar: para convertir horas a milisegundos (necesario para asignar tiempo al temporizador), es tan simple como multiplicar por 3600000.

cuanto tiempo es el maximo que puede durar arduino descontando en intervalos de 1 s. ¿horas, dias o cuanto tiempo?

Alex_MG:
cuanto tiempo es el maximo que puede durar arduino descontando en intervalos de 1 s.

Tanto la librería como el Arduino mismo cuentan milisegundos como mínima granularidad.

Desde que se enciende o reinicia, puede contar hasta (2^32) - 1 = 4294967295 milisegundos (49 días y 17 horas).
Aunque para evitar el desbordamiento, se puede reiniciar el contador de millis sin reiniciar la ejecución del programa.

tendras algun ejemplo de tu libreria? me serviria mucho y mas un descontador,por que utilizo la funcion delay y por lo mismo me impide otras funciones espero me puedas ayudar amigo saludos

Alex_MG, ¿has probado lo que comenté? Añadir el long antes del int en la declaración de temp. No me extrañaría nada que ignorases mi comentario ya que te doy una supuesta solución sin explicación ninguna. Pero es que no he tenido tiempo, hasta ahora, para sentarme a dar una explicación.

Las variables en Arduino pueden ser de diferentes tipos y “tamaños”. En el caso de ser de tipo int se trataría de una variable entera (no admite decimales), con signo (puede tener un valor negativo) y de un tamaño de 16 bits (en la mayoría de los Arduinos es así, pero los hay más potentes que su tamaño es de 32 bits ya que depende mucho de la arquitectura del microprocesador). Esto último es “el problema”, el tamaño. Por ser de 16 bits, y con signo, su rango va de -32768 a 32767. En el caso de tratar de asignarle un valor menor o mayor al rango admitido, ese valor “se trunca”. Sería algo así como que tenemos un display de cuatro dígitos y tratamos de mostrar el número 123456, como sólo puede mostrar cuatro dígitos sólo se vería el número 3456, “perdiéndose” el “12000”. Algo semejante pasa con la variable de Arduino, pero en binario.

Si usamos la variable tem para guardar segundos, nos encontramos con que 9 horas son 32400 segundos (9x60x60) que “caben” perfectamente en una variable de tipo int (su valor máximo es 32767). Pero si tratamos de guardar 10 horas la cantidad de segundo es 36000 (10x60x60) y esa cantidad “desborda” una variable de tipo int y, por “cuestiones técnicas” que no vienen al caso explicar ahora, el valor que toma la variable es -29536, con lo que la hora mostrada es “un disparate”. Por esto deduje que el tipo de la variable tem era int (cuando te respondí no habías puesto más que unas pequeñas partes del programa y no se veía la definición de tem).

Cuando se le asigna a tem 23 horas, lo que se le trata de asignar son 82800 segundos (23x60x60) y lo que se guarda realmente en la variable es el resto de dividir 82800 por 32768 que da 17264. Si guarda 17264 segundos eso son 4 horas, 47 minutos y 44 segundos (no sé por qué has puesto 04:47:50, a mi me da 47 segundos no 50). De ahí vienen esas cuatro horas y pico en lugar de 23 horas.

Entendido el problema busquemos la solución. Y la solución es usar un tipo que nos permita almacenar valores mayores que 32767 y “el siguiente tipo” en tamaño “razonable” es el long int, o simplemente long, cuyo tamaño es de 32 bits y su rango va desde -2147483648 a 2147483647. Con 2147483647 segundos tendríamos para 59652 horas.

Así que “la solución” es cambiarle el tipo a la variable tem añadiendo el long en su declaración. Ahora que has puesto tu programa (fgTimer4.ino) te puedo decir que, para que te funcione correctamente con 23 o más horas, debería de bastar con que la línea 71 ponga:

long int tem = 0;

Buscando en Google se pueden ver los diferentes tipos y los rangos de valores que admiten. Nota: por simplificar y no liarlo mucho, no todo lo explicado es exactamente tal cual lo he dicho.

Explicada mi respuesta, paso a comentar un par de cosas. Además de que con el delay(1000) nos encontramos que durante un segundo el programa “está parado” sin hacer otra cosa que esperar, hay “un detalle” que hace que el segundo se “alargue” y las 23 horas nos dure algunos segundos de más. Entre segundo y segundo de espera el Arduino ha de hacer “unas cosillas”, entre otras mostrar el tiempo en la pantalla, y esto lleva su tiempo… poco tiempo, sí, pero mucho poco se termina notando.

Para evitar ambos problemas se puede utilizar la función millis() y máquinas de estado. Como ejemplos, de los cuales podría sacar ideas e incluso tal vez adaptar el código, aquí tienes dos enlaces a dos entradas de este foro en donde puse unas propuestas de soluciones de cuentas atrás (la segunda es una variante de la primera):

Orientación para proyecto timer

Timer con LCD y salida de Rele

Espero que sirva de ayuda.

Alex_MG:
tendras algun ejemplo de tu libreria?

No solo trae un léeme, sino hasta un par de ejemplos. Ábrelos y estúdialos.

Creo que CountdownSerial es el que mejor explica cómo crearlo, inicializarlo, ponerlo en marcha y saber cuando terminó.

muchas gracias IgnoranteAbsoluto tenias razón ya pude incluso poner 1 semana, con int long, aunque como decias no puedo hacer otra funcion hasta que acabe el tiempo, y lo que necesito es que haga unos procesos en funcion del tiempo, lo intentare con millis(). muchas gracias.