Cronómetro 5 dígitos modificación hilo de manipulable con 74HC595

Hola
Abro este hilo para que podamos completar un código que se inicio al final de este hilo de los compañeros,el hilo cambió demasiado del original y por eso abro este para un cronómetro que se inicia, para y reinicia con un solo botón, estaría también compuesto por 5 dígitos, siendo 3 de ellos para segundos, uno para décimas y otro para centésimas utilizando 74HC595, dejo el diagrama que he modificado del anterior hilo para un quinto número y las primeras partes que un compañero del foro comenzó a realizar para ayudarme
gracias de antemano, toda idea o ayuda es buena

void display(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[miles]); 
	shiftOut(data, clock, MSBFIRST, digito[centenas]); 
	shiftOut(data, clock, MSBFIRST, digito[decenas]);
	shiftOut(data, clock, MSBFIRST, digito[unidades]);
	digitalWrite(LATCH, HIGH);
}

Bueno como conversamos antes, 999.99 segundos es lo que buscas
1 boton start/stop
1 botón reset?

Y además ascendente no?

Eso seria, lo de un mismo botón para las tres cosas se me a ocurrido al ver en el mismo hilo que habíais puesto el inicio con un mando a distancia pienso que poniendo un poco de retardo a la hora de poder volver a pulsar el botón para pararlo se podría solucionar

Solo confirma los alcances de tu cronometro porque luego que esta hecho siempre se acuerden de algo mas y ahi es donde pierdo la paciencia..jaja

Jajaja normal que pierdas la paciencia, seria eso 3 numero en segundos ,1 décimas y otro centésimas marcando como tu dices 999.99 y un solo botón que inicia,para y haciendo que al pulsar de nuevo el botón en parado comienze la cuenta otra vez de cero

Bueno amigo como te comente en el anterior hilo colocando una nueva línea de decenas podría valer para que cuente en 5 dígito?

Yo muchas veces hago las cosas de esta manera (y supongo que muchos harán lo mismo) y tu desarrolla luego tu propio método o criterio.

No siempre se sabe como hacer algo.
Puedes estudiarlo y aún tener dudas. Dudas que se disipan con algo de experiencia sobre el tema.

En este caso, agregar un nuevo digito por hardware, parece y es lógico.
Sigue la corriente de la cascada de 595's y agregas uno mas.

Ahora eso tienen una correspondencia con el código.
Miras el código y luego observa, que son dígitos que están en cascada. Que se transmite todo en serie, asi que desde el primer dígito al 4to digito no ha cambiado nada, por lo que debes sumar uno mas, pero en la rutina, separamos el número porque viene no de este modo 999.99 sino como un unsigned long 99999 ya que supera a un unsigned int (65535).

Así que debes agregar como bien dices decena y hacer la matemática que lo separe del resto.

cambia esto

void display(int numero)

por

void display(unsigned long numero) {

        int centenas = numero / 10000;
	numero %= 10000;	
        int decenas = numero / 1000;
	numero %= 1000;
	int unidades = numero / 100;
	numero %= 100;
	int decimas = numero / 10;
	numero %= 10;
	int centesimas = numero;

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

Perfecto gracias
Una vez hecha esta parte tendríamos que asignar al puerto 12 el start,stop y el reinicio a contar desde 0 no?
Creo que algo como esto pinMode(12, INPUT);
Había pensado en que cuando el pin 12 diese el start haya 5 o3 segundos en los q el botón no pueda hacer el stop (que no pueda recibir la señal),una vez pasado se pueda accionar el stop y al presionarse se vuelva a iniciar de 0 el cronometro

Seria algo asi? o me falta algo para que sea cronometro ascendente normal

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

/* 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] = { B01111011, B00010010, B01100111, B00110111, B00011110, B00111101, B01111101, B00010011, B01111111, B00011111};
const byte StartCronPin = 12;

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;
unsigned long timeCronometro = 0;
unsigned long Cronometro        = 0;
unsigned long ComparoCronometro;
bool bStartTime = false;

void setup()
{

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;   
    }
  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 long numero) {

       int centenas = numero / 10000;
numero %= 10000; 
       int decenas = numero / 1000;
numero %= 1000;
int unidades = numero / 100;
numero %= 100;
int decimas = numero / 10;
numero %= 10;
int centesimas = numero;

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

Bueno investigando un poco mas me acorde del post en el que empezamos hablar surbyte y era también un crono de 5 dígitos pero el problema era que no tenia botón de stop ni de reset he intentado modificar el código por si me pudiese valer y me faltaría poner los botones que no se como hacelo si me pudieras revisar el código y darme alguna pista con lo del botón te lo agradecería también recordar que seria para arduino uno gracias de antemano

Programa base tomado de http://playground.arduino.cc/Code/Stopwatch
*/



const int buttonPin = 12;

int value = LOW;                    // previous value of the LED
int buttonState;                    // variable to store button state
int lastButtonState;                // variable to store last button state
int blinking;                       // condition for blinking - timer is timing
long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
int fractional;                     // variable used to store fractional part of time


// Definiciones de los 74HC595

int pinLatch	= 4;	//Pin para el latch de los 74CH495
int pinDatos	= 2;	//Pin para Datos serie del 74CH495
int pinReloj	= 3;	//Pin para reloj del 74CH495

byte digitOne[10]= {
	// Codificaci�n hexadecimal de los d�gitos decimales en el display de 7 segmentos
	//0xEE, 0x82, 0xDC, 0xD6, 0xB2, 0x76, 0x7E, 0xC2, 0xFE, 0xF6};
	// Codificacion del autor del Hilo
	
	0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xb6, 0x3E, 0xE0, 0xFE, 0xF6};
	// con esta codificaci�n los leds encienden correctamente
 
 
int  centenas	= 0;	//N�mero de las centenas
int decenas	= 0;    //N�mero de las decenas		= 0;	//Numero de las decimas
int decimas 	= 0;    //Numero de las decimas
int centesimas	= 0;    //numero de las centesimas
void setup(){

	Serial.begin(19200);
	pinMode(pinLatch, OUTPUT);
	pinMode(pinDatos, OUTPUT);
	pinMode(pinReloj, OUTPUT);
	//pinMode(buttonPin, INPUT);
	Serial.println("Cronometro Ok");

	pinMode(ledPin, OUTPUT);         // seteo el pin digital LED como salida

	pinMode(buttonPin, INPUT);       // buttonPin como entrada 
	digitalWrite(buttonPin, HIGH);   // activo el resistor pullup. Cablear el boton de modo que cuando se presione vaya a masa

	}

void loop()
{
	// check for button press
	buttonState = digitalRead(buttonPin);                   // leo el estado del bot�n y lo guardo

	if (buttonState == LOW && lastButtonState == HIGH  &&  blinking == false){     // check for a high to low transition
		// if true then found a new button press while clock is not running - start the clock

		startTime = millis();                                // almacena el tiempo de arranque del cron�metro
		blinking = true;                                     // activar el led durante el cronometrado
		delay(5);                                            // peque�o retardo para evitar rebotes
		lastButtonState = buttonState;                       // guardo buttonState en lastButtonState para luego comparar

	}

	else if (buttonState == LOW && lastButtonState == HIGH && blinking == true){     
			// chequear una transici�n de alto a bajo 
			// si es verdadero luego encontrar una nueva presion del boton mientras el reloj corre - parar el reloj y presentar

			elapsedTime =   millis() - startTime;              // guardo el tiempo transcurrido
			blinking = false;                                  // apago parpadeo
			lastButtonState = buttonState;                     // guardo buttonState en lastButtonState para luego compararlo
			display(elapsedTime );
			// presento el tiempo transcurrido
			Serial.print( (int)(elapsedTime / 1000L));         // divido por 1000 para convertir a segundos luego tomo el entero
		
			Serial.print(".");									// imprimo el punto decimal

			// calculo la parte fraccional
			fractional = (int)(elapsedTime % 1000L);

			// pad in leading zeros - wouldn't it be nice if
			// Arduino language had a flag for this? :)
			if (fractional == 0)
				Serial.print("000");      // add three zero's
			else if (fractional < 10)    // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
				Serial.print("00");       // add two zeros
			else if (fractional < 100)
				Serial.print("0");        // add one zero

			Serial.println(fractional);  // print fractional part of time

		}
		else{
			lastButtonState = buttonState;                         // store buttonState in lastButtonState, to compare next time
		}
	if (blinking){ 
		display(millis() - startTime); 
	}

	// Rutina para hacer parpadear un led pin 13 indicando que esta contando.

	if ( (millis() - previousMillis > interval) ) {

		if (blinking == true){
			previousMillis = millis();                         // Recuerndo el momento en que parpadea el led

			// cambio el estado del led
			if (value == LOW)
			value = HIGH;
			else
			value = LOW;
			digitalWrite(ledPin, value);
		}
		else{
			digitalWrite(ledPin, LOW);                         // apago el led cuando no parpadea
		}
	}

}



void display(unsigned long numero) {

        int centenas = numero / 10000;
	numero %= 10000;	
        int decenas = numero / 1000;
	numero %= 1000;
	int unidades = numero / 100;
	numero %= 100;
	int decimas = numero / 10;
	numero %= 10;
	int centesimas = numero;

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

Hola, soy nuevo en el foro, y llevo poco tiempo con arduino, por lo que creo que este es el mejor lugar para ir aprendiendo de los usuarios mas expertos, y este tema en concreto me interesa especialmente, ya que estoy empezando un cronometro y ando un poco perdido, me gustaría saber si el código que ha puesto chelas es con el que funciona el cronometro y que tipo de arduino se necesita para que funcione, muchas gracias a todos por vuestros aportes y vuestra paciencia con los nuevos. Un saludo.

Buenas el circuito es para arduino uno pero el código todavía no esta hecho poco a poco surbyte me esta ayudando hacerlo si puedes ir aportando partes del código estaría bien

surbyte estado mirando y he visto este código para los botones no se si valdra por que aparte es para una lcd y nose si el otro código que puse esta bien cuando puedas echale un vistazo por favor ya estoy muy perdido y nose como hacerlo, me gustaría montarlo en la protoboard para verlo funcionar
gracias

long time1=0;  
long time2=0;  
long startTime ;                    
long elapsedTime ;                  

int fractional;                    
int buttonPin1 = 10;  //pin para el boton 1
int buttonState1 = 0; //Variable para leer boton1


void loop() {
  TKLCD_Serial lcd = TKLCD_Serial();
    time1 = millis();  
    buttonState1 = digitalRead(buttonPin1); 
    }

  
    if (buttonState1 == LOW  &&  buttonState1 == LOW) {  
        dcsec = 0;
        run=false;          
        delay(500);  
        digital.print("Parado");
  }
  
if (buttonState1 == HIGH)
{
    run == true;
  }
  
 if (run == true);
 {
   startTime = millis();
}

if (buttonState1 == HIGH)
{
  elapsedTime = millis() - startTime;
  tempsfinal = ( (int)(elapsedTime / 1000L));
  friccion = (((-(0,03 / tiempofinal)^2) / (11,76 * cos angle)) + tan angle)
  digital.print = friccion  
}

Bueno pues gracias a Surbyte el código esta prácticamente terminado lo único que quedaría seria que al darle al botón cada vez que empieze desde 0 se desactivase el botón 3 segundos mientras que el crono siguiera contando y de ese modo que el cronometro no pudiese parar aunque se presionase el boton en los 3 primeros segundos, transcurrido esos segundos se pudiese parar y al volver a pulsar pasara lo mismo otra vez
Si alguien tiene alguna idea que lo comente
gracias

 /* StopWatch
* Paul Badger 2008
* Demonstrates using millis(), pullup resistors,
* making two things happen at once, printing fractions
*
* Physical setup: momentary switch connected to pin 4, other side connected to ground
* LED with series resistor between pin 13 and ground

Programa base tomado de http://playground.arduino.cc/Code/Stopwatch
*/


#define ledPin  13                  // LED connected to digital pin 13
const int buttonPin = 2;

int value = LOW;                    // previous value of the LED
int buttonState;                    // variable to store button state
int lastButtonState;                // variable to store last button state
int blinking;                       // condition for blinking - timer is timing
long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long demoroBoton;
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
int fractional;                     // variable used to store fractional part of time


// Definiciones de los 74HC595

int pinLatch	= 10;	//Pin para el latch de los 74CH495
int pinDatos	= 11;	//Pin para Datos serie del 74CH495
int pinReloj	= 12;	//Pin para reloj del 74CH495

byte digitOne[10]= {
	// Codificación hexadecimal de los dígitos decimales en el display de 7 segmentos
	//0xEE, 0x82, 0xDC, 0xD6, 0xB2, 0x76, 0x7E, 0xC2, 0xFE, 0xF6};
	// Codificacion del autor del Hilo
	
	0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xb6, 0x3E, 0xE0, 0xFE, 0xF6};
	// con esta codificación los leds encienden correctamente
 
int  centenas	= 0;	//Número de las centenas 
int  decenas	= 0;	//Número de las decenas
int unidades	= 0;    //Número de las unidades
int decimas		= 0;	//Numero de las decimas
int centesimas	= 0;    //Numero de las centesimas


void setup(){


	Serial.begin(19200);
	pinMode(pinLatch, OUTPUT);
	pinMode(pinDatos, OUTPUT);
	pinMode(pinReloj, OUTPUT);
	//pinMode(buttonPin, INPUT);
	Serial.println("Cronometro Ok");

	pinMode(ledPin, OUTPUT);         // seteo el pin digital LED como salida

	pinMode(buttonPin, INPUT_PULLUP);       // buttonPin como entrada 
	digitalWrite(buttonPin, HIGH);   // activo el resistor pullup. Cablear el boton de modo que cuando se presione vaya a masa
	demoroBoton = millis()+3000UL;
        display(0);
}

void loop()
{
	// check for button press
	buttonState = digitalRead(buttonPin);                   // leo el estado del botón y lo guardo

	if (buttonState == LOW && lastButtonState == HIGH  &&  blinking == false){     // check for a high to low transition
		// if true then found a new button press while clock is not running - start the clock

		if (millis() - demoroBoton > 3000UL) {
			startTime = millis();                                // almacena el tiempo de arranque del cronómetro
			blinking = true;                                     // activar el led durante el cronometrado
			delay(5);                                            // pequeño retardo para evitar rebotes
			lastButtonState = buttonState;                       // guardo buttonState en lastButtonState para luego comparar
			Serial.println("Startime =");
			Serial.print(startTime);
			display(0);
			demoroBoton = millis();
		}
	}

	else if (buttonState == LOW && lastButtonState == HIGH && blinking == true){     
			// chequear una transición de alto a bajo 
			// si es verdadero luego encontrar una nueva presion del boton mientras el reloj corre - parar el reloj y presentar

    		        elapsedTime =   millis() - startTime;              // guardo el tiempo transcurrido
			blinking = false;                                  // apago parpadeo
			lastButtonState = buttonState;                     // guardo buttonState en lastButtonState para luego compararlo
			display(elapsedTime );
			Serial.println("ElapsedTime =");
			Serial.print(elapsedTime);

			// presento el tiempo transcurrido
			Serial.print( (int)(elapsedTime / 100L));         // divido por 1000 para convertir a segundos luego tomo el entero
		
			Serial.print(".");									// imprimo el punto decimal

			// calculo la parte fraccional
			fractional = (int)(elapsedTime % 1000L);

			// pad in leading zeros - wouldn't it be nice if
			// Arduino language had a flag for this? :)
			if (fractional == 0)
				Serial.print("000");      // add three zero's
			else if (fractional < 10)    // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
				Serial.print("00");       // add two zeros
			else if (fractional < 100)
				Serial.print("0");        // add one zero

			Serial.println(fractional);  // print fractional part of time

		}
		else{
			lastButtonState = buttonState;                         // store buttonState in lastButtonState, to compare next time
		}
	if (blinking){ 
		display(millis() - startTime); 
	}

	// Rutina para hacer parpadear un led pin 13 indicando que esta contando.

	if ( (millis() - previousMillis > interval) ) {

		if (blinking == true){
			previousMillis = millis();                         // Recuerndo el momento en que parpadea el led

			// cambio el estado del led
			if (value == LOW)
			value = HIGH;
			else
			value = LOW;
			digitalWrite(ledPin, value);
		}
		else{
			digitalWrite(ledPin, LOW);                         // apago el led cuando no parpadea
		}
	}

}



void display(unsigned long numero){

	centenas  = numero/10000;
	numero    %= 10000;
	decenas   = numero/1000;
	numero    %= 1000;
	unidades	   = numero/100;
	numero	  %= 100;
	decimas = numero/10;
	numero    %= 10;
	centesimas = numero;
	
	digitalWrite(pinLatch, LOW);
	shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[centesimas]);	//digitOne centesimas
	shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[decimas]);		//digitOne decimas
	shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[unidades]);		// digitOne unidades
	shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[decenas]);		//digitOne decenas
	shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[centenas]);		//digitOne centenas
	digitalWrite(pinLatch, HIGH);
}

Y tu dices Chelas que esto no satisface lo que quieres: mira y me respondes
Antes que nada: lo probaste en tu cronómetro?
Ayer quedaste en hacerlo.

if (buttonState == LOW && lastButtonState == HIGH  &&  blinking == false){     // check for a high to low transition
		// if true then found a new button press while clock is not running - start the clock

		if (millis() - demoroBoton > 3000UL) {
			startTime = millis();                                // almacena el tiempo de arranque del cronómetro
			blinking = true;                                     // activar el led durante el cronometrado
			delay(5);                                            // pequeño retardo para evitar rebotes
			lastButtonState = buttonState;                       // guardo buttonState en lastButtonState para luego comparar
			Serial.println("Startime =");
			Serial.print(startTime);
			display(0);
			demoroBoton = millis();
		}
	}

Al final de los 3 segundos yo puse demoroBoton = millis(); asi que si tu cronometras 3.01 segundos por lo que lo detuviste y quieres arrancarlo podrás porque ya se ha armado de nuevo.
QUe esta mal?

No surbyte lo estuve probando y lo hace después de parar el crono no al iniciar la cuenta