Temporizador de cuenta regresiva con TM1637

Hola, que tal. Como dice el titulo tengo que hacer un temporizador con el modulo TM1637. Y tengo una duda en cuanto a esto, que es más conveniente ¿Hacerlo usando una biblioteca de interrupciones? o ¿Sin biblioteca de interrupciones, es decir, con la función delay y algunas cosas más?

Agrego que luego tengo que tener fácil acceso a modificar el tiempo con botones o desde otra pantalla, que puede ser un celular. Aclaro que lo voy a hacer con el ESP8266.

Algo que jamas debes considerar es usar delay().
Si por interrupciones te refieres a un TIMER que se encargue del multiplexado, pues si, me parece bien.

Moderador
Todo tema de placas no Arduino.cc van en Microprocesadores.
Movido a dicha Sección.

Como te dice @Surbyte , jamás delay() y menos para algo que controla el tiempo.
Puedes usar la interrupción de un timer, una librería, incluso manejarlo con millis().

Para el TM1637 usa una librería.

¿millis() no es lo mismo que delay()?. Y en respuesta a Surbyte, claro me refiero al TIMER interno de la placa y gracias por mover el hilo.

Absolutamente no.

En Documentación hay un excelente tutorial.

Millis() no es delay().
Usar milllis() no detiene el código.
Usar delay() te deja de brazos cruzados por el tiempo que le pones entre paréntesis.
Deberías tener alguna librería, busca algo adecuado para tu necesidad.

¿Preferible usar una biblioteca antes que millis()? Yo pensaba que millis() era lo mismo que delay(), se ve que no ¿Cuál es la desventaja de millis() por la que decís que preferís una biblioteca?

Creo que no me entendes o no me hago entender.
Entre delay y millis() uso millis().
Entre millis() y Timer uso Timer.
Si tenque que escribir yo el código lo hago pero si enecuentro una librería la uso y no pierdo mi tiempo. Programo bien pero no tanto como alguien que le pudo mas empeño que yo.

Entonces puse en Google: ESp8266 TM1637 Library y salió esto

Y curiosamente implementa una especie de delay pero la llama nanodelay() por la velocidad del microcontrolador pero tambien usa un delaymicroseconds para la comunicación serial de 2 cables.

No, vos no me entendiste jaja. Me refería a una biblioteca de interrupciones. No creo que con la librería esa sola del TM1637 pueda hacer el temporizador de cuenta regresiva, voy a necesitar o la función millis() o la biblioteca de interrupciones.

Con cual librería?

Alguna que haya por ahí para el ESP8266.

Pero te acabo de poner una y tiene un ejemplo que maneja un reloj

Es cuestion que lo mires!!

Si, lo miré. Pero me refería a una biblioteca como esta: ESP8266TimerInterrupt. Y para el TM1637 prefiero usar la biblioteca de Avishay Orpaz, no se si tiene alguna desventaja para mi proyecto.

¿ Una librería para una cuenta regresiva? , es como matar "pulgas a cañonazos". Bastan unas pocas líneas de código.

int segundos, horas, minutos;
unsigned long tp, atp;



tp = (micros() - atp);
if ((unsigned long)(tp >= 1000000)) {
  atp = micros();
  if (segundos > 0) {
    segundos--;
  }
  else {
    if ((segundos == 0) && (minutos == 0) && (horas == 0)) {
      final();
    }
    segundos = 59;
    if (minutos > 0) {
      minutos--;
    }
    else {
      minutos = 59;
      if (horas > 0) {
        horas--;
      }
    }
  }
  pantalla(0);
}

Con los botones o lo que quieras gestionas para entrar con horas, minutos y segundos deseados y tiene dos salidas:
final (); para cuando acabe el conteo, en mi caso un buzzer "blinkeando". y pantalla(0), que gestiona la impresión en una oled en tu caso las llamadas a mostrar en el TM1637.

Tambien me parece que es matar pulgas a cañonazos pero lo decia porque en este ejemplo de la biblioteca del tm1637 de grove se usa la biblioteca timer1:

/*
    A library for the 4 digit display

    Copyright (c) 2012 seeed technology inc.
    Website    : www.seeed.cc
    Author     : Frankie.Chu
    Create Time: 9 April,2012
    Change Log :

    The MIT License (MIT)

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

/*
    example Requirement

    Install libraries on Arduino Library Mnager.

    TimerOne - maintained by Paul Stoffregen
*/

#include <TimerOne.h>
#include "TM1637.h"
#define ON 1
#define OFF 0

int8_t TimeDisp[] = {0x00, 0x00, 0x00, 0x00};
unsigned char ClockPoint = 1;
unsigned char Update;
unsigned char halfsecond = 0;
unsigned char second;
unsigned char minute = 0;
unsigned char hour = 12;


#define CLK 2//pins definitions for TM1637 and can be changed to other ports
#define DIO 3
TM1637 tm1637(CLK, DIO);

void setup() {
    tm1637.set();
    tm1637.init();
    Timer1.initialize(500000);//timing for 500ms
    Timer1.attachInterrupt(TimingISR);//declare the interrupt serve routine:TimingISR
}
void loop() {
    if (Update == ON) {
        TimeUpdate();
        tm1637.display(TimeDisp);
    }

}
void TimingISR() {
    halfsecond ++;
    Update = ON;
    if (halfsecond == 2) {
        second ++;
        if (second == 60) {
            minute ++;
            if (minute == 60) {
                hour ++;
                if (hour == 24) {
                    hour = 0;
                }
                minute = 0;
            }
            second = 0;
        }
        halfsecond = 0;
    }
    // Serial.println(second);
    ClockPoint = (~ClockPoint) & 0x01;
}
void TimeUpdate(void) {
    if (ClockPoint) {
        tm1637.point(POINT_ON);
    } else {
        tm1637.point(POINT_OFF);
    }
    TimeDisp[0] = hour / 10;
    TimeDisp[1] = hour % 10;
    TimeDisp[2] = minute / 10;
    TimeDisp[3] = minute % 10;
    Update = OFF;
}

Ah, y también si no es mucha molestia te puedo pedir que me expliques más el programa, y le encontré un error creo, si yo pongo los minutos en 10 y los segundos en 0 solo bajan los minutos. Tengo el programa así:

int segundos, horas, minutos;
unsigned long tp, atp;

void setup() {
  Serial.begin(9600);
}

void loop() {
tp = (micros() - atp);
if ((unsigned long)(tp >= 1000000)) {
  atp = micros();
  if (segundos > 0) {
    segundos--;
  }
  else {
    if ((segundos == 0) && (minutos == 0) && (horas == 0)) {
    }
    segundos = 0;
    if (minutos > 0) {
      minutos--;
    }
    else {
      minutos = 10;
      if (horas > 0) {
        horas--;
      }
    }
  }
  Serial.print(horas);
  Serial.print(":");
  Serial.print(minutos);
  Serial.print(":");  
  Serial.println(segundos);  
}
}

Siempre me olvido de aclarar algunas cosas. El tm1637 lo voy a usar para mostrar el tiempo de un partido de basquet, empieza el contador en los 10 minutos y cuando baja de 1 minuto, es decir empieza en 00:59 tiene que mostrar una decima, es decir 59:10.....59:09 y así.

El error está en tu código, el que deja de descontar segundos es el tuyo porque si al segundo 0 le descontás 1 debe pasar a 59 (como lo hace @gonpezzi) y no quedar en 0 (como has hecho).

No se que has intentado hacer cambiando el código.
La hora, minutos y segundos se deben cargar en las variables respectivas en setup(), por ej. , no en la rutina de decremento del temporizador.

1 Like

Cierto @MaximoEsfuerzo .
@mirkoam ese trozo de código lo uso en un temporizador de cocina, lo gestiono con tres botones conectados a GND y definidos como IMPUT_PULLUP y el final de mi setup es el siguiente:

 //Coje horas  
  while (rojo == 1){
    pulsadores (1);
    delay (150);
    if (blanco == 0){horas++; if (horas > 99){horas = 0;}}
    if (azul == 0){horas--; if (horas < 0){horas = 99;}}
    if (horas <10){pantallita (0,0,3);}
       else {pantallita (1,0,3);}
  }
//Coje minutos
   rojo = 1;
   while (rojo == 1){
    pulsadores (1);
    delay (150);
    if (blanco == 0){minutos++; if (minutos > 99){minutos = 0;}}
    if (azul == 0){minutos--; if (minutos < 0){minutos = 99;}}
    if (minutos <10){pantallita (0,1,4);}
       else {pantallita (1,1,4);} 
  }
  if (minutos > 59) {horas++; minutos = minutos - 60;}    
  pausa(); 
  atp=micros(); 
}

void loop() {  
pulsadores (0);
// resto del código

En este estado el boton blanco incrementa, el azul decrementa y el rojo funciona como " intro ". todo esto manejado por la función pulsadores (?) ya que dependiendo de donde este cambia el sentido y función de los pulsadores.

Ah ahora ya entendí.

A que llamas pantallita(), pausa() y pulsadores(). Supongo que rojo, blanco, azul y horas son los pulsadores.

Haciendo un mix del ejemplo de la biblioteca del tm1637 (terminé usando la que recomendó @Surbyte porque se puede usar con un array) y el programa de @gonpezzi me quedó algo así:

#include "TM1637.h"
#define ON 1
#define OFF 0
#define CLK 2
#define DIO 3

TM1637 tm1637(CLK, DIO);

int8_t TimeDisp[] = {0x00, 0x00, 0x00, 0x00};
unsigned char Update;

int segundos, horas, minutos;
unsigned long tp, atp;

void setup() {
  Serial.begin(9600);
  tm1637.set();
  tm1637.init();
  tm1637.point(POINT_ON);
  minutos = 10;
  segundos = 0;
}

void loop() {  
  if (Update == ON) {
    TimeUpdate();
    tm1637.display(TimeDisp);
  }
  Update = ON;  
  tp = (micros() - atp);
  if ((unsigned long)(tp >= 1000000)) {
    atp = micros();
    if (segundos > 0) {
      segundos--;
    }
    else {
      if ((segundos == 0) && (minutos == 0) && (horas == 0)) {
      }
      segundos = 59;
      if (minutos > 0) {
        minutos--;
      }
      else {
        minutos = 59;
        if (horas > 0) {
          horas--;
        }
      }
    }
    Serial.print(horas);
    Serial.print(":");
    Serial.print(minutos);
    Serial.print(":");  
    Serial.println(segundos);  
  }
}

void TimeUpdate(void) {
    TimeDisp[0] = minutos / 10;
    TimeDisp[1] = minutos % 10;
    TimeDisp[2] = segundos / 10;
    TimeDisp[3] = segundos % 10;
    Update = OFF;
}

Que por ahora parece funcionar correctamente con el display, la verdad no entiendo porque hay tantas bibliotecas de este módulo. Le deje el void TimeUpdate porque me parecio ordenado separarlo del void loop. Ahora debo probarlo en el esp8266.

Son funciones propias de mi proyecto, pulsadores() llama a la gestión de los pulsadores y pantallita() a la impresión en la pantalla oled,

Si son los pulsadores, horas es la variable que contiene las horas a contar.

En el ultimo código que has subido creo que te has dejado cosas de la librería Timeone.h que ya no hacen falta . Yo lo veo así:

#include "TM1637.h"
#define CLK 2
#define DIO 3

TM1637 tm1637(CLK, DIO);

int segundos, horas, minutos;
unsigned long tp, atp;
bool punto;

void setup() {
  Serial.begin(9600);
  tm1637.set();
  tm1637.init();
  tm1637.point(POINT_ON);
  minutos = 10;
  segundos = 0;
}

void loop() {

  // Gestiona aqui tus pulsadores para fijar horas, minutos y segundos

  tp = (micros() - atp);
  if ((unsigned long)(tp >= 1000000)) {
    atp = micros();
    if (punto == true) {
      tm1637.point(POINT_ON);
    }
    else {
      tm1637.point(POINT_OFF);
    }
    punto = !punto;
    if (segundos > 0) {
      segundos--;
    }
    else {
      if ((segundos == 0) && (minutos == 0) && (horas == 0)) {
      }
      segundos = 59;
      if (minutos > 0) {
        minutos--;
      }
      else {
        minutos = 59;
        if (horas > 0) {
          horas--;
        }
      }
    }
  }
 // añade aqui lo necesario para mostrar en el display
    Serial.print(horas);    
    Serial.print(":");
    Serial.print(minutos);
    Serial.print(":");
    Serial.println(segundos); 
}