74hc595 arduino uno agregar display 7 segmentos para tomar tiempos

La idea de este hilo es agregar un display 7 segmentos, dos pulsadores con el cual podamos llevar alguna cuenta (los dos pulsadores me cumplirán la función de aumentar o decrementar)mientras se esta ejecutando el temporizado que hayamos programado;

ejemplo: tengo los cuatro displays del temporizado y el quinto que es donde llevaremos la cuenta.

Para este caso programamos 5 minutos.Una vez se cumplan esos cinco minutos puedo escribir mediante los pulsadores cuantos tiempos llevo tomados y puedo volver a programar el temporizado que necesito.

#include <Arduino.h>
#include <NECIRrcv.h> //Libreria del protocolo NEC
#define IRPIN 7 // Pin del receptor IR

NECIRrcv ir(IRPIN);

//////////////////////////////botoes ///////////////////////////////////////////////////////

long IRIncrementoMinDtv = 0xFD02FB04; //Codigo correspondiente al boton nueve del mando a distancia
long IRDecrementoMinDtv = 0xFC03FB04; //Codigo correspondiente al boton siete del mando a distancia
long IRStartCronometroDtv = 0xF708FB04; //Este es el boton ocho para el start


#define data 2// cable naranja
#define clock 4//cable blanco
#define LATCH 3//cable verde
/* 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] = {B00000001, B01001111, B00010010, B00000110, B01001100, B00100100, B00100000, B00001111, B00000000, B00001100};

int contador = 0;

const byte IncrMinPin   = 12;
const byte DecrMinPin   = 10;
const byte StartCronPin = 11;
const byte Alarma       = 8;

const byte ConteoQuintoDisplay   = 9;

unsigned long StartTime = 0;

byte IncrementoMin = 0;
byte IncrementoMinLast = 0;
// declarar nuevo boton
byte DecrementoMin = 0;
byte DecrementoMinLast = 0;

byte StartCronometro = 0;
byte StartCronometroLast = 0;
byte EstadoAlarma = 2; //inicializo la alarma en el caso 2 que es apagada

unsigned long timeCronometro = 0;
unsigned long Cronometro        = 0;
unsigned long ComparoCronometro;
unsigned long tintervalo; //variable de tiempo de encendido de la alarma

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);

 ir.begin(); //Iniciamos la recepcion IR

 pinMode(11, INPUT);
 pinMode(12, INPUT);
 pinMode(10, INPUT);
 pinMode(8, OUTPUT);
 pinMode(9, INPUT);

 digitalWrite(IncrMinPin,LOW);
 digitalWrite(DecrMinPin,LOW);
 digitalWrite(StartCronPin,LOW);
 
 display(0);
}

void loop(){

  unsigned long ircode; //Variable que contendra el codigo decimal del boton pulsado
 
  while (ir.available()) {
  ircode  = ir.read(); //Leemos el codigo del boton pulsado
  }
  
  IncrementoMinLast = IncrementoMin;
  IncrementoMin = digitalRead(IncrMinPin); 

  DecrementoMinLast = DecrementoMin;
  DecrementoMin = digitalRead(DecrMinPin);
 
 if ( (IncrementoMin == LOW && IncrementoMinLast == HIGH) || (ircode == IRIncrementoMinDtv  ) ){ 
 StartTime += 5;
 if (StartTime >= 60) // m?ximo 60 minutos. 
 StartTime = 60;          // Si esta mal cambiar por 60 min o el valor que desees
 time(StartTime*60);
 Serial.println(StartTime);
 Cronometro = (unsigned long) StartTime * 60UL; 
 }    
 //////

 
//  Segmento de codigo  para agregar otro boton

 if ( (DecrementoMin == LOW && DecrementoMinLast == HIGH) || (ircode == IRDecrementoMinDtv) ){ 
 StartTime -= 5;
 if (StartTime >= 60) // m?ximo 60 minutos. 
 StartTime = 0;          // Si esta mal cambiar por 60 min o el valor que desees
 time(StartTime*60);
 Serial.println(StartTime);
 Cronometro = (unsigned long) StartTime * 60UL; 
 }   

 StartCronometroLast = StartCronometro;
 StartCronometro = digitalRead(StartCronPin); 

 if( (StartCronometro == LOW && StartCronometroLast == HIGH) || (ircode == IRStartCronometroDtv) ){
        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) { // espero 1000 mseg
         if (Cronometro > 0){

         Cronometro -= 1;
         ComparoCronometro = millis()+1000UL;
         time((unsigned int) Cronometro);

         if (Cronometro == 0){
           bStartTime = false;   
         }
        /////////////// inicializo la alarma para 5 segundos//////////////////
        if (Cronometro <=0) {
            if (EstadoAlarma ==2) {
              EstadoAlarma = 1;	
              tintervalo = millis()+10000UL;
            }
        }
        ///////////////finaliza la configuracion de la alarma//////////
      }
    } // se cumplen 1000 mseg
  } // Fin de bstarTime 
  switch(EstadoAlarma) {

         case 1:
               digitalWrite(Alarma,HIGH);   
               if (millis() > tintervalo) {
                 EstadoAlarma = 2;
               }
               break;

         case 2:
         default:
               digitalWrite(Alarma,LOW);
               EstadoAlarma = 2;
               break;
        } // fin del switch
}   


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 Umiles = numero / 10000; // FORMULA PARA AGREGAR UNA QUINTA POSICION DE MUESTREO
 numero %= 10000;
 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[Umiles]); // PRESENTAR EN EL QUINTO DISPLAY PARA LLEVAR LA CUENTA
 
 
 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);

}

Lo primero seria declarar las nuevas entradas para los dos pulsadores

De esta forma agregue la formula para el quinto display y poder visualizarlo

void display(unsigned int numero){


 int Umiles = numero / 10000; // FORMULA PARA AGREGAR UNA QUINTA POSICION DE MUESTREO
 numero %= 10000;
 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[Umiles]); // PRESENTAR EN EL QUINTO DISPLAY PARA LLEVAR LA CUENTA
 
 
 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);

}

Para llevar el conteo adecuaría un contador

	if (digitalRead(9) == HIGH){ 
        delay(5); // antirrebote
		if (contador++>= 9)
		   contador = 0;
	}    

	if(digitalRead(6) == HIGH){
        delay(5);// antirrebote
		if (contador-- < 0) 
		    contador = 0;
	}

si hay algún error me dicen

pero en realidad el problema o la duda que tengo es como mostrar este conteo en el quinto display
ya que he probado bastante y no lo he conseguido

gracias.

ves esta linea

unsigned int presentoTime = minutos*100 + numeroDeSegundos (val);
  display(presentoTime);

desplazas por 10 y sumas tu contador y tienes 4 digitos con lo anterior MM:SS + CONTADOR

Solo has esto,

unsigned int presentoTime = (minutos*100 + numeroDeSegundos (val))*10+contador;

No se si tenga un problema a la hora de plantear la formula para el contador o si esta linea tenga algún problema por que la probé pero no me visualiza el conteo

unsigned int presentoTime = (Minutos * 100 + numeroDeSegundos (val)) * 10 + contador;

codigo completo

#include <Arduino.h>
#include <NECIRrcv.h> //Libreria del protocolo NEC
#define IRPIN 7 // Pin del receptor IR

NECIRrcv ir(IRPIN);

//////////////////////////////botoes ///////////////////////////////////////////////////////

long IRIncrementoMinDtv = 0xFD02FB04; //Codigo correspondiente al boton nueve del mando a distancia
long IRDecrementoMinDtv = 0xFC03FB04; //Codigo correspondiente al boton siete del mando a distancia
long IRStartCronometroDtv = 0xF708FB04; //Este es el boton ocho para el start


#define data 2// cable naranja
#define clock 4//cable blanco
#define LATCH 3//cable verde
/* 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] = {B00000001, B01001111, B00010010, B00000110, B01001100, B00100100, B00100000, B00001111, B00000000, B00001100};

int contador = 0;

const byte IncrMinPin   = 12;
const byte DecrMinPin   = 10;
const byte StartCronPin = 11;
const byte Alarma       = 8;

const byte DecrementoConteoQuintoDisplay   = 6;
const byte IncrementoConteoQuintoDisplay   = 9;

unsigned long StartTime = 0;

byte IncrementoMin = 0;
byte IncrementoMinLast = 0;
// declarar nuevo boton
byte DecrementoMin = 0;
byte DecrementoMinLast = 0;

byte StartCronometro = 0;
byte StartCronometroLast = 0;
byte EstadoAlarma = 2; //inicializo la alarma en el caso 2 que es apagada

unsigned long timeCronometro = 0;
unsigned long Cronometro        = 0;
unsigned long ComparoCronometro;
unsigned long tintervalo; //variable de tiempo de encendido de la alarma

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);

 ir.begin(); //Iniciamos la recepcion IR

 pinMode(11, INPUT);
 pinMode(12, INPUT);
 pinMode(10, INPUT);
 pinMode(8, OUTPUT);
 
 pinMode(6, INPUT);
 pinMode(9, INPUT);

 digitalWrite(IncrMinPin,LOW);
 digitalWrite(DecrMinPin,LOW);
 digitalWrite(StartCronPin,LOW);
 
 display(0);
}

void loop(){

  unsigned long ircode; //Variable que contendra el codigo decimal del boton pulsado
 
  while (ir.available()) {
  ircode  = ir.read(); //Leemos el codigo del boton pulsado
  }
  
  //////conteo independiente/////////
 if (digitalRead(IncrementoConteoQuintoDisplay ) == HIGH){ 
        delay(5); // antirrebote
 if (contador++>= 9)
   contador = 0;
 }    

 if(digitalRead(IncrementoConteoQuintoDisplay ) == HIGH){
        delay(5);// antirrebote
 if (contador-- < 0) 
    contador = 0;
 }
//////////////////////////////////////////
  IncrementoMinLast = IncrementoMin;
  IncrementoMin = digitalRead(IncrMinPin); 

  DecrementoMinLast = DecrementoMin;
  DecrementoMin = digitalRead(DecrMinPin);
 
 if ( (IncrementoMin == LOW && IncrementoMinLast == HIGH) || (ircode == IRIncrementoMinDtv  ) ){ 
 StartTime += 5;
 if (StartTime >= 60) // m?ximo 60 minutos. 
 StartTime = 60;          // Si esta mal cambiar por 60 min o el valor que desees
 time(StartTime*60);
 Serial.println(StartTime);
 Cronometro = (unsigned long) StartTime * 60UL; 
 }    
 //////

 
//  Segmento de codigo  para agregar otro boton

 if ( (DecrementoMin == LOW && DecrementoMinLast == HIGH) || (ircode == IRDecrementoMinDtv) ){ 
 StartTime -= 5;
 if (StartTime >= 60) // m?ximo 60 minutos. 
 StartTime = 0;          // Si esta mal cambiar por 60 min o el valor que desees
 time(StartTime*60);
 Serial.println(StartTime);
 Cronometro = (unsigned long) StartTime * 60UL; 
 }   

 StartCronometroLast = StartCronometro;
 StartCronometro = digitalRead(StartCronPin); 

 if( (StartCronometro == LOW && StartCronometroLast == HIGH) || (ircode == IRStartCronometroDtv) ){
        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) { // espero 1000 mseg
         if (Cronometro > 0){

         Cronometro -= 1;
         ComparoCronometro = millis()+1000UL;
         time((unsigned int) Cronometro);

         if (Cronometro == 0){
           bStartTime = false;   
         }
        /////////////// inicializo la alarma para 5 segundos//////////////////
        if (Cronometro <=0) {
            if (EstadoAlarma ==2) {
              EstadoAlarma = 1; 
              tintervalo = millis()+10000UL;
            }
        }
        ///////////////finaliza la configuracion de la alarma//////////
      }
    } // se cumplen 1000 mseg
  } // Fin de bstarTime 
  switch(EstadoAlarma) {

         case 1:
               digitalWrite(Alarma,HIGH);   
               if (millis() > tintervalo) {
                 EstadoAlarma = 2;
               }
               break;

         case 2:
         default:
               digitalWrite(Alarma,LOW);
               EstadoAlarma = 2;
               break;
        } // fin del switch
}   


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))*10+contador; // AGREGAR LA PRESENTACION DEL CONTADOR
  display(presentoTime);

}

void display(unsigned int numero){


 int Umiles = numero / 10000; // FORMULA PARA AGREGAR UNA QUINTA POSICION DE MUESTREO
 numero %= 10000;
 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[Umiles]); // PRESENTAR EN EL QUINTO DISPLAY PARA LLEVAR LA CUENTA
 
 
 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);

}

Cuando de refiere a multiplicar *10+contador a que se refiere acaso es a el desplazamiento entre los registros, como calculo esto

unsigned int presentoTime = (Minutos * 100 + numeroDeSegundos (val)) * 10 + contador;

seguramente hemos desbordado al unsigned int y debas usar unsigned long.
Aclaremos
contador de 0 a 9. No mas dígitos o sea solo un digito.
corro tu cuenta presentoTime un lugar * 10 y sumo contador

unsigned long presentoTime = (minutos*100 + numeroDeSegundos (val))*10+contador; 
// AGREGAR LA PRESENTACION DEL CONTADOR
  display(presentoTime);

y ajusto esto

void display(unsigned int numero){
por esto
void display(unsigned long numero){

El contador es de 0 a 9 pero probe lo que me dijiste y me mustra unas cosas raras en los displays

Vamos para atras. Cuando no agregabas el contador, funcionaba bien el cronométro?

si funciona bien pero apenas le agregue el contador empezó a mostrarme cosas raras

ahhh claro. El contador esta pensado para motrar MM:SS y lo ordena de ese modo.
Dejame ver y te respondo.

una vez agregado el display y el pulsador del contador , uno puede basarse en el para agregar mas displays y pulsadores de estos en caso de que llegue a necesitar mas?

Surbyte puedes indicarme algo para probarlo este fin de semana, gracias

Vamos a hacerlo mas facil.
Voy a desdoblar la presentación de modo tal que la parte que responde a MM:SS siga como esta y la del contador sea aparte, okay.

Entonces lo que cambia es esto

void display(unsigned int numero, int contador){ // ahora desbes presentar display(algo, contador);


 int Umiles = numero / 10000; // FORMULA PARA AGREGAR UNA QUINTA POSICION DE MUESTREO
 numero %= 10000;
 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]); 
 shiftOut(data, clock, MSBFIRST, digito[contador]);  

 digitalWrite(LATCH, HIGH);

}

cuando lo usas en el sketch ponías antes

display(presentoTime);

ahora pones

display(presentoTime, contador);

no se que estoy colocando mal me marca errores