Cronometro manipulable con 74hc595

Muy buena noche a todos, estoy tratando de hacer un temporizador, de momento trabaja con un boton incrementando los minutos para que inicie la cuenta regresiva desde donde se le indica, a parte de ello me gustaría agregarle un boton más para indicarle desde que segundo especifico debe iniciar, es decir si quiero ponerle al temporizador un minuto y 28 segundos. Dejo el código base con el cual he estado trabajando, espero su ayuda

#define data 2
#define clock 3
#define LATCH 4
#define buzz 10

/* Useful Constants */
// Tomados de <DateTime.h>
#define SECS_PER_MIN  (60UL)
#define SECS_PER_HOUR (3600UL)
 
/* Useful Macros for getting elapsed time */
#define numeroDeSegundos(_time_) (_time_ % SECS_PER_MIN) 
#define numeroDeMinutos(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)

const byte digito[10] = { 0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111};
const byte IncrMinPin = 12;
const byte StartCronPin = 11;
const byte ResetCron=9;

byte resetcronometro = 0;
unsigned long StartTime = 0;
byte IncrementoMin = 0;
byte IncrementoMinLast = 0;
byte StartCronometro = 0;
byte StartCronometroLast = 0;
unsigned long timeCronometro = 0;
unsigned long Cronometro        = 0;
unsigned long ComparoCronometro;
bool bStartTime = false;

void setup()
{
 Serial.begin(9600);
 Serial.println("Contador descendente");
 Serial.println("Incr.Minutos = sube de a 5 minutos");
 Serial.println("Start/Stop = controla cronómetro");
 pinMode(clock, OUTPUT);
 pinMode(data , OUTPUT);
 pinMode(LATCH, OUTPUT);

 pinMode(11, INPUT);
 pinMode(12, INPUT);
 display(0);
 pinMode (10, OUTPUT);
 pinMode (9, INPUT);
}

void loop()


{
 IncrementoMinLast = IncrementoMin;
 IncrementoMin = digitalRead(IncrMinPin);
 if ( IncrementoMin == HIGH && IncrementoMinLast == LOW){
 StartTime += 1;
 if (StartTime >= 15) // máximo 15 minutos.
   StartTime = 15;          // Si esta mal cambiar por 60 min o el valor que desees
 time(StartTime*60);
 Serial.println(StartTime);
 Cronometro = (unsigned long) StartTime * 60UL;
 
 }

resetcronometro = digitalRead(ResetCron);
if ( resetcronometro == HIGH){
 StartTime = 0;
 Cronometro = 0;
 display (0);
 
 }

    

 StartCronometroLast = StartCronometro;
 StartCronometro = digitalRead(StartCronPin);
 if( StartCronometro == HIGH && StartCronometroLast == LOW){
 bStartTime = !bStartTime; // Cada pulso cambia el estado de prendido a apagado.

 if (bStartTime) { // Si arranco, entoncer cargo contador descendente con valor StartTime
 Serial.print("Cronometro = ");
 Serial.println(Cronometro);
 ComparoCronometro = millis()+1000UL;
 }
 }

    if (bStartTime){
     if (ComparoCronometro  - millis()> 1000UL) {
     if (Cronometro > 0){
     Cronometro -= 1;
     ComparoCronometro = millis()+1000UL;
     time((unsigned int) Cronometro);
     
     if (Cronometro == 0){
     bStartTime = false;   
     digitalWrite(buzz, HIGH);   // PARA IMPLEMENTAR CHICHARRA
  delay(5000); 
    digitalWrite (buzz, LOW);
     }
   delay(100);
 }}} }   

void time(unsigned long val){ 
  int minutos;
  Serial.print("Crono = ");
  Serial.print(Cronometro);
  Serial.print(" Time = ");
  Serial.print(val);
  Serial.print(" Min= ");

  if (val < 3600)
   minutos = numeroDeMinutos(val);
  else
     minutos = numeroDeMinutos(val)+60;

  Serial.print(minutos);
  Serial.print(" Seg= ");
  Serial.println(numeroDeSegundos(val));
 
  unsigned int presentoTime = minutos*100 + numeroDeSegundos(val);
  display(presentoTime);
}

void display(unsigned int numero)
{
 int miles = numero / 1000;
 numero %= 1000;
 int centenas = numero / 100;
 numero %= 100;
 int decenas = numero / 10;
 numero %= 10;
 int unidades = numero;

 digitalWrite(LATCH, LOW);
 shiftOut(data, clock, MSBFIRST, digito[unidades]);
 shiftOut(data, clock, MSBFIRST, digito[decenas]);
 shiftOut(data, clock, MSBFIRST, digito[centenas]);
 shiftOut(data, clock, MSBFIRST, digito[miles]);
 digitalWrite(LATCH, HIGH);
}

No se si lo copiaste mal pero tal como esta el código esta mal.
Este código lo hice o modifiqué hace algunos aÑos y lo recuerdo link

Recuerdo haber trabajado en ese código y el primer if no puede abarcar todo el loop. Eso esta mal.

Agregué el control de segundos de 0 a 59 y si te pasas vuelve a 0. Lo mismo hice con el de Minutos, si te pasas de 15 vuelve a 0. Lo cambias si te parece

El pulsador a agregar lo puse en el pin 13, cámbialo si te parece

#include <Arduino.h>


#define data    2
#define clock   3
#define LATCH   4
#define BUZZ    10

/* Useful Constants */
// Tomados de <DateTime.h>
#define SECS_PER_MIN  (60UL)
#define SECS_PER_HOUR (3600UL)
 
/* Useful Macros for getting elapsed time */
#define numeroDeSegundos(_time_) (_time_ % SECS_PER_MIN)
#define numeroDeMinutos(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)

const byte digito[10]       = { 0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111};
const byte IncrSegPin       = 13;
const byte IncrMinPin       = 12;
const byte StartCronPin     = 11;
const byte ResetCron=9;

byte resetcronometro        = 0;
unsigned long StartTime     = 0;
unsigned long StartTimeMin  = 0;
unsigned long StartTimeSeg  = 0;

byte IncrementoMin          = 0, IncrementoMinLast  = 0;
byte IncrementoSeg          = 0, IncrementoSegLast  = 0;
byte StartCronometro        = 0, StartCronometroLast = 0;

unsigned long timeCronometro = 0;
unsigned long Cronometro     = 0;
unsigned long ComparoCronometro;
bool bStartTime = false;
bool fTime = false;           // cambio de Min o Segundos

void setup() {
    Serial.begin(9600);
    Serial.println("Contador descendente");
    Serial.println("Incr.Minutos = sube de a 5 minutos");
    Serial.println("Start/Stop = controla cronómetro");
    pinMode(clock, OUTPUT);
    pinMode(data , OUTPUT);
    pinMode(LATCH, OUTPUT);
    pinMode(IncrSegPin, INPUT);
    pinMode(StartCronPin, INPUT);
    pinMode(IncrMinPin, INPUT);
    pinMode(BUZZ, OUTPUT);
    pinMode(9, INPUT);

    display(0);
}

void loop() {

    IncrementoMinLast = IncrementoMin;
    IncrementoMin = digitalRead(IncrMinPin);
    if ( IncrementoMin && !IncrementoMinLast){
        StartTimeMin += 1;
        fTime = true;
        if (StartTimeMin > 15)     // máximo 15 minutos.
            StartTimeMin = 0;      // Si se pasa lo hago cíclico
        }
    }

    IncrementoSegLast = IncrementoSeg;
    IncrementoSeg = digitalRead(IncrSegPin);
    if ( IncrementoSeg && !IncrementoSegLast){
        StartTimeSeg += 1;
        fTime = true;
        if (StartTimeSeg > 59) // máximo 59 segundos
            StartTimeSeg = 0;      // si me paso de 59 lo hago cíclico
        }
    }

    if (fTime) {
        StartTime = StartTimeMin*60+StartTimeSeg;
        time(StartTime);
        Serial.println(StartTime);
        Cronometro = (unsigned long) StartTime;  
        fTime = false;               // solo muestra cambios si hay modificaciones.
    }

    resetcronometro = digitalRead(ResetCron);
    if ( resetcronometro) {
        StartTime   = 0;
        Cronometro  = 0;
        display (0);
    }

    StartCronometroLast = StartCronometro;
    StartCronometro = digitalRead(StartCronPin);
    if( StartCronometro && !StartCronometroLast){
        bStartTime = !bStartTime; // Cada pulso cambia el estado de prendido a apagado.

        if (bStartTime) { // Si arranco, entoncer cargo contador descendente con valor StartTime
            Serial.print("Cronometro = ");
            Serial.println(Cronometro);
            ComparoCronometro = millis()+1000UL;
        }
    }

    if (bStartTime){
        if (ComparoCronometro  - millis()> 1000UL) {
            if (Cronometro > 0) {
                Cronometro -= 1;
                ComparoCronometro = millis()+1000UL;
                time((unsigned int) Cronometro);
            }
            if (Cronometro == 0){
                bStartTime = false;   
                digitalWrite(BUZZ, HIGH);   // PARA IMPLEMENTAR CHICHARRA
                delay(5000);
                digitalWrite (BUZZ, LOW);
            }
        }   
    }
}   

void time(unsigned long val){
  int minutos;
  Serial.print("Crono = ");
  Serial.print(Cronometro);
  Serial.print(" Time = ");
  Serial.print(val);
  Serial.print(" Min= ");

  if (val < 3600)
   minutos = numeroDeMinutos(val);
  else
     minutos = numeroDeMinutos(val)+60;

  Serial.print(minutos);
  Serial.print(" Seg= ");
  Serial.println(numeroDeSegundos(val));
 
  unsigned int presentoTime = minutos*100 + numeroDeSegundos(val);
  display(presentoTime);
}

void display(unsigned int numero) {
    int miles = numero / 1000;
    numero %= 1000;
    int centenas = numero / 100;
    numero %= 100;
    int decenas = numero / 10;
    numero %= 10;
    int unidades = numero;

    digitalWrite(LATCH, LOW);
    shiftOut(data, clock, MSBFIRST, digito[unidades]);
    shiftOut(data, clock, MSBFIRST, digito[decenas]);
    shiftOut(data, clock, MSBFIRST, digito[centenas]);
    shiftOut(data, clock, MSBFIRST, digito[miles]);
    digitalWrite(LATCH, HIGH);
}

Prueba a ver si se comporta como esperas.

Agradezco muchísimo tu apoyo, te comento que solo le he agregado un botón más para decrementar minutos, uno más para decrementar segundos, en el botón reinicio las variables StartTimeMin y StartTimeSeg a 0 para que al volver a iniciar el temporizador no continúe desde el primer tiempo que se le asignó y hasta ahí todo funciona de maravilla, se me presenta un problema al momento de pausar el temporizador y quererle incrementar o decrementar ya sea minutos o segundos debido a que le aumenta al valor inicial y no al valor en el que se pauso, es decir si pongo el temporizador a 3:30 y lo detengo en 3:25 si por X ó Y razón quisiera sumarle dos segundos al 3:25 lo que hace es sumarle a 3:30, he intentado trabajarlo de la manera en la que programaste el botón de pausa pero no lo consigo :frowning:

#include <Arduino.h>


#define data    2
#define clock   3
#define LATCH   4
#define BUZZ    10

/* Useful Constants */
// Tomados de <DateTime.h>
#define SECS_PER_MIN  (60UL)
#define SECS_PER_HOUR (3600UL)
 
/* Useful Macros for getting elapsed time */
#define numeroDeSegundos(_time_) (_time_ % SECS_PER_MIN)
#define numeroDeMinutos(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)

const byte digito[10]       = { 0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111};
const byte IncrSegPin       = 13;
const byte IncrMinPin       = 12;
const byte StartCronPin     = 11;
const byte ResetCron=9;
const byte DecreSegPin      = 8;
const byte DecreMinPin      = 7;

byte resetcronometro        = 0;
unsigned long StartTime     = 0;
unsigned long StartTimeMin  = 0;
unsigned long StartTimeSeg  = 0;

byte IncrementoMin          = 0, IncrementoMinLast  = 0;
byte IncrementoSeg          = 0, IncrementoSegLast  = 0;
byte StartCronometro        = 0, StartCronometroLast = 0;
byte DecrementoSeg          =0, DecrementoSegLast =0;
byte DecrementoMinLast      =0, DecrementoMin=0;

unsigned long timeCronometro = 0;
unsigned long Cronometro     = 0;
unsigned long ComparoCronometro;
bool bStartTime = false;
bool fTime = false;           // cambio de Min o Segundos

void setup() {
    Serial.begin(9600);
    Serial.println("Contador descendente");
    Serial.println("Incr.Minutos = sube de a 1 minutos");
    Serial.println("Start/Stop = controla cronómetro");
    pinMode(clock, OUTPUT);
    pinMode(data , OUTPUT);
    pinMode(LATCH, OUTPUT);
    pinMode(IncrSegPin, INPUT);
    pinMode(StartCronPin, INPUT);
    pinMode(IncrMinPin, INPUT);
    pinMode(BUZZ, OUTPUT);
    pinMode(9, INPUT);
    display (0);
    
}

void loop() {
    
    IncrementoMinLast = IncrementoMin;
    IncrementoMin = digitalRead(IncrMinPin);
    if ( IncrementoMin && !IncrementoMinLast){
        StartTimeMin += 1;
        fTime = true;
        if (StartTimeMin > 15)     // máximo 15 minutos.
            StartTimeMin = 0;      // Si se pasa lo hago cíclico
        }
    

    IncrementoSegLast = IncrementoSeg;
    IncrementoSeg = digitalRead(IncrSegPin);
    if ( IncrementoSeg && !IncrementoSegLast){
        StartTimeSeg += 1;
        fTime = true;
        if (StartTimeSeg > 59) // máximo 59 segundos
            StartTimeSeg = 0;      // si me paso de 59 lo hago cíclico
        }

//BOTONES DECREMENTO
   DecrementoSegLast = DecrementoSeg;
    DecrementoSeg = digitalRead(DecreSegPin);
    if ( DecrementoSeg && !DecrementoSegLast){
        StartTimeSeg -= 1;
        fTime = true;
        if (StartTimeSeg <= 0) // máximo 59 segundos
            StartTimeSeg = 59;      // si me paso de 59 lo hago cíclico
        }

DecrementoMinLast = DecrementoMin;
    DecrementoMin = digitalRead(DecreMinPin);
    if ( DecrementoMin && !DecrementoMinLast){
        StartTimeMin -= 1;
        fTime = true;
        if (StartTimeMin > 15)     // máximo 15 minutos.
            StartTimeMin = 0;      // Si se pasa lo hago cíclico
        }        
     

    if (fTime) {
        StartTime = StartTimeMin*60+StartTimeSeg;
        time(StartTime);
        Serial.println(StartTime);
        Cronometro = (unsigned long) StartTime; 
        fTime = false;               // solo muestra cambios si hay modificaciones.
    }


    StartCronometroLast = StartCronometro;
    StartCronometro = digitalRead(StartCronPin);
    if( StartCronometro && !StartCronometroLast){
        bStartTime = !bStartTime; // Cada pulso cambia el estado de prendido a apagado.
        
        if (bStartTime) { // Si arranco, entoncer cargo contador descendente con valor StartTime
            Serial.print("Cronometro = ");
            Serial.println(Cronometro);
            ComparoCronometro = millis()+1000UL;
        }
    } 

    if (bStartTime){
        if (ComparoCronometro  - millis()> 1000UL) {
            if (Cronometro > 0) {
                Cronometro -= 1;
                ComparoCronometro = millis()+1000UL;
                time((unsigned int) Cronometro);
            }
            if (Cronometro == 0){
                bStartTime = false;   
                digitalWrite(BUZZ, HIGH);   // PARA IMPLEMENTAR CHICHARRA
                delay(5000);
                digitalWrite (BUZZ, LOW);
            }
        }   
    }
    
    resetcronometro = digitalRead(ResetCron);
    if ( resetcronometro) {
        StartTimeMin   = 0;
        StartTimeSeg=0;
        Cronometro  = 0;
        display (0);
        
    }
    
}   

void time(unsigned long val){
  int minutos;
  Serial.print("Crono = ");
  Serial.print(Cronometro);
  Serial.print(" Time = ");
  Serial.print(val);
  Serial.print(" Min= ");

  if (val < 3600)
   minutos = numeroDeMinutos(val);
  else
     minutos = numeroDeMinutos(val)+60;

  Serial.print(minutos);
  Serial.print(" Seg= ");
  Serial.println(numeroDeSegundos(val));
 
  unsigned int presentoTime = minutos*100 + numeroDeSegundos(val);
  display(presentoTime);
}

void display(unsigned int numero) {
    int miles = numero / 1000;
    numero %= 1000;
    int centenas = numero / 100;
    numero %= 100;
    int decenas = numero / 10;
    numero %= 10;
    int unidades = numero;

    digitalWrite(LATCH, LOW);
    shiftOut(data, clock, MSBFIRST, digito[unidades]);
    shiftOut(data, clock, MSBFIRST, digito[decenas]);
    shiftOut(data, clock, MSBFIRST, digito[centenas]);
    shiftOut(data, clock, MSBFIRST, digito[miles]);
    digitalWrite(LATCH, HIGH);
}