Contador con 74HC595 + DISPLAY 7 SEGMENTOS [Solucionado]

Hola,

Tengo dos displays de un digito conectados cada uno a un 74HC595 funcionando perfectamente para contar de 0 a 99. El código siguiente lo muestra.

int dataPIN = 8;
int latchPIN = 11;
int clockPIN = 12;

byte numero[] = {B00011000, B01111011, B00101100, B00101001, B01001011,
                 B10001001, B10001000, B00111011, B00001000, B00001001};

void mostrar_numero(byte x) {
    shiftOut(dataPIN, clockPIN, MSBFIRST, numero[x]);
} 

void setup() {
  // initialize digital pin as an output.
  pinMode(dataPIN, OUTPUT);
  pinMode(latchPIN, OUTPUT);
  pinMode(clockPIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  for (int x=0; x<1000; x++){
      digitalWrite (latchPIN, LOW);
      mostrar_numero(x%10);
      mostrar_numero((x/10)%10);
      mostrar_numero(x/100);
      digitalWrite (latchPIN, HIGH);delay(100);
  }
}

Este hace la función de un reloj, pero lo que deseo es que deje de ser un reloj para convertirse en un contador que inicie desde 00 (cero-cero).
Qué pines y/o código debo modificar y/o eliminar o aumentar???

El contador deberá incrementar una unidad cada vez que un LDR reciba un haz de luz.

Por ejemplo en el momento siguiente:

ldr0Value = analogRead(ldrPin0);
if (ldr0Value > 450)
{aciertos++;

Gracias anticipadamente por la ayuda.

No entiendo donde está la duda.

Con este código muestras un numero:

  digitalWrite (latchPIN, LOW);
  mostrar_numero(x%10);
  mostrar_numero((x/10)%10);
  mostrar_numero(x/100);
  digitalWrite (latchPIN, HIGH);

Y con este otro miras la LDR y aumentas:

ldr0Value = analogRead(ldrPin0);
if (ldr0Value > 450)
  aciertos++;

Si los unes:

ldr0Value = analogRead(ldrPin0);
if (ldr0Value > 450)  {
  aciertos++;
  digitalWrite (latchPIN, LOW);
  mostrar_numero(aciertos%10);
  mostrar_numero((aciertos/10)%10);
  mostrar_numero(aciertos/100);
  digitalWrite (latchPIN, HIGH);
}

¿No hace lo que quieres?

Perdón por la pregunta pero acabas de poner solucionado a un tema similar y ahora abres otro preguntado por una variante menor?
Por que no sigues hasta agotar el tema en lugar de abrir múltiples hilos por temas o tareas menores?

Coincido que esto para comenzar no es un reloj

Lo único que puede hacerlo un reloj es ese delay(100) que además me parece arbitrario considerando el resto de las instrucciones que insumen tiempo pero eso es hilar demasiado fino para este momento de tus consultas.
Solo para que lo tengas en cuenta y ya entendí que no hablas del reloj sino de usar tu display de 2 digitos para mostar otras cosas.

Uno transforma tu rutina en algo que muestre lo que deses y no al revés.

Esta es tu rutina de presentación

void display7seg(int x) {
      digitalWrite (latchPIN, LOW);
      mostrar_numero(x%10);
      mostrar_numero((x/10)%10);
      mostrar_numero(x/100);
      digitalWrite (latchPIN, HIGH);
}

ahora sigo con la idea de victorjam que esta perfecta y mira

ldr0Value = analogRead(ldrPin0);
if (ldr0Value > 450)  {
  display7seg(aciertos++);
}

Si quisieras usarla para un reloj usa millis() que te va garantizar que lo hará bien en tiempo

acá debes definir una variable del tipo

unsigned long start;
byte contador = 0;
if (millis() - start > 100UL) {
    display7seg(contador++);
    if (contador>99) contador = 0;
}

Las disculpas del caso surbyte, no me percaté de ese detalle (que podía seguir el hilo anterior). Seré más ordenado para una proxima.

Gracias por ambas respuestas, he recapitulado un poco llevando las respuestas al código pero no me resulta el aumento del "(aciertos++)". En algo estoy fallando. Se inicia el arduino con los displays en 00 (cero-cero), pero no aumentan los aciertos, se queda en 00.

Aquí el código que estoy probando:

#include <Servo.h>
int sensorPin0 = A0;
int ldr0Value;
byte fin = 0;
int x=0;
int aciertos=0;
Servo myservo2; 
int dataPIN = 8;
int latchPIN = 9;
int clockPIN = 10;
byte numero[] = {B00011000, B01111011, B00101100, B00101001, B01001011, B10001001, B10001000, B00111011, B00001000, B00001001};
void mostrar_numero(int x) {
    shiftOut(dataPIN, clockPIN, MSBFIRST, numero[x]);
}

void display7seg(int x) {
      digitalWrite (latchPIN, LOW);
      mostrar_numero(x%10);
      mostrar_numero((x/10)%10);
      mostrar_numero(x/100);
      digitalWrite (latchPIN, HIGH);
}

void setup() {
myservo2.attach(2); 
  pinMode(dataPIN, OUTPUT);
  pinMode(latchPIN, OUTPUT);
  pinMode(clockPIN, OUTPUT);
}

void loop() {
while (millis() < 15000) { 

  
ldr0Value = analogRead(sensorPin0);
if (ldr0Value < 450)
{myservo2.write(90);
delay(15);}
else {
myservo2.write(0);
display7seg(aciertos++);
delay(1500);}
}
if (!fin) {
myservo2.write(0);
fin = 1;
}}

Bueno analicemos lo que tienes ahora en tu loop()

void loop() {
	while (millis() < 15000) {
		ldr0Value = analogRead(sensorPin0);
		if (ldr0Value < 450) {
			myservo2.write(90);
			delay(15);
		}
		else {
			myservo2.write(0);
			display7seg(aciertos++);
			delay(1500);
		}
	}
	if (!fin) {
		myservo2.write(0);
		fin = 1;
	}
}

NOTA: te pido por favor, que te tomes el tiempo en presetar códigos con la debida identación. Ya que pides ayuda colabora haciéndolo para que nos resuelte mas fácil. En lo personal, debo corregir todos los días códigos que estan pegados contra el borde izquierdo lo que dificulta su lectura e interpretación.

Observando tu código lo primero que has hecho mal es esto

while (millis() < 15000) {

Eso le dice al Arduino que solo preste atención a lo que hará en los primeros 15 segundos lo que es nada considerando el funcionamiento de tu programa.

Asi que empiezas mal.

Modifiqué tu código pero no me convence lo que he hecho porque cada 15 segundos consultaría el LDR y si es menor a 450 entonces mueve el servo y sino hace lo demás.

//antes del setup define
unsigned long start, start2;

// aca va el setup

void loop() {
	ldr0Value = analogRead(sensorPin0);
	if (millis() - start > 15000UL) {
		if (ldr0Value < 450) {
			myservo2.write(90);
		}
		else {
			if (millis() - start2 > 1500UL) {
				myservo2.write(0);
				display7seg(aciertos++);
				start2 = millis();
			}
		}
		if (!fin) {
			myservo2.write(0);
			fin = 1;
		}
		start = millis();
	}
}

Hola surbyte,
Resulta que los 15000 solo los he puesto para hacer las pruebas y no esperar 60000 que será la duración total del juego. Pasados los 60000 el juego deberá reiniciarse con el botón reset.

Todo está funcionando bien excepto el aumento del puntaje.

Por favor, tu ayuda con el mismo código. Hay algo que me falta o me sobra y no logro encontrar la falla y error.

Gracias!!!

#include <Servo.h>
int sensorPin0 = A0;
int ldr0Value;
byte fin = 0;
int x=0;
int aciertos=0;
Servo myservo2; 
int dataPIN = 8;
int latchPIN = 9;
int clockPIN = 10;
byte numero[] = {B00011000, B01111011, B00101100, B00101001, B01001011, B10001001, B10001000, B00111011, B00001000, B00001001};
void mostrar_numero(int x) {
    shiftOut(dataPIN, clockPIN, MSBFIRST, numero[x]);
}

void display7seg(int x) {
      digitalWrite (latchPIN, LOW);
      mostrar_numero(x%10);
      mostrar_numero((x/10)%10);
      mostrar_numero(x/100);
      digitalWrite (latchPIN, HIGH);
}

void setup() {
  myservo2.attach(2); 
    pinMode(dataPIN, OUTPUT);
    pinMode(latchPIN, OUTPUT);
    pinMode(clockPIN, OUTPUT);
}

void loop() {
  while (millis() < 15000) { 

  
  ldr0Value = analogRead(sensorPin0);
  if (ldr0Value < 450)
    {myservo2.write(90);
    delay(15);}
else {
  myservo2.write(0);
  display7seg(aciertos++);
    delay(1500);}
}
if (!fin) {
  myservo2.write(0);
  fin = 1;
}}

Vaya vaya.. no sabía que era un juego.
Tampoco sabía que estabas probándolo solo por 15 segundos.
Cuesta tanto explicar el contexto de lo que se esta haciendo?
Tal vez en otro hilo lo has dicho pero no estamos siguiendo tu caso porque lo has puesto en hilos separados.

Esperaba que el código estuviera identado pero veo que no viste mi pedido.
Tu código no dice que hace con la variable fin, que papel debe jugar dicha variable?

#include <Servo.h>

Servo myservo2;

unsigned int ldr0Value;

const byte sensorPin0 	= A0;
const byte dataPIN 		=  8;
const byte latchPIN 	=  9;
const byte clockPIN 	= 10;

byte fin 				= 0;
int aciertos			= 0;
unsigned long start, start2;

// aca va el setup


byte numero[] = {B00011000, B01111011, B00101100, B00101001, B01001011, B10001001, B10001000, B00111011, B00001000, B00001001};

void mostrar_numero(int x) {
    shiftOut(dataPIN, clockPIN, MSBFIRST, numero[x]);
}

void display7seg(int x) {
	digitalWrite (latchPIN, LOW);
	mostrar_numero(x%10);
	mostrar_numero((x/10)%10);
	mostrar_numero(x/100);
	digitalWrite (latchPIN, HIGH);
}

void setup() {
  myservo2.attach(2);
    pinMode(dataPIN, OUTPUT);
    pinMode(latchPIN, OUTPUT);
    pinMode(clockPIN, OUTPUT);
}

void loop() {
	while (millis() < 15000) {
		ldr0Value = analogRead(sensorPin0);
		if (ldr0Value < 450) {
			myservo2.write(90);
			delay(15);
		}
		else {
			myservo2.write(0);
			display7seg(aciertos++);
			delay(1500);
		}
	}
	if (!fin) {
		myservo2.write(0);
		fin = 1;
	}
}

El aumento de puntaje se resuelve colocando indicación en el monito Serie.
inicializa el monitor serie con Serial.begin() y luego un Serial.print(aciertos)
Es posible que tu LDR siempre este en valores < 450? Para mi, ese es el problema. El código luce aparentemente bien.

Todo eso se responde colocando impresiones en el monitor Serie.

Tienes la razón, con Serial.printnl(aciertos) puedo ver en el monitor que sí aumenta el puntaje (aciertos++) cada vez que se le da al blanco al LDR con un láser. Además que el servo también reacciona adecuadamente.

Para estar seguro de las conexiones hacia los displays he vuelto a probar cargando el sketch "contador de 0 a 99" y funciona perfectamente.

Hay algo que falta para que el puntaje se muestre en los displays y no logro detectar que es lo que está mal.

El código siguiente es el último con las recopilaciones indicadas.

#include <Servo.h>

Servo myservo2; 
unsigned int ldr0Value;
const byte sensorPin0 = A0;

const byte dataPIN = 8;
const byte latchPIN = 9;
const byte clockPIN = 10;
byte fin = 0;
int aciertos=0;
int x=0;

byte numero[] = {B00011000, B01111011, B00101100, B00101001, B01001011, B10001001, B10001000, B00111011, B00001000, B00001001};
void mostrar_numero(int x) {
    shiftOut(dataPIN, clockPIN, MSBFIRST, numero[x]);
}

void display7seg(int x) {
      digitalWrite (latchPIN, LOW);
      mostrar_numero(x%10);
      mostrar_numero((x/10)%10);
      mostrar_numero(x/100);
      digitalWrite (latchPIN, HIGH);
}

void setup() {
    Serial.begin(9600);
    myservo2.attach(2); 
    pinMode(dataPIN, OUTPUT);
    pinMode(latchPIN, OUTPUT);
    pinMode(clockPIN, OUTPUT);
}

void loop() {
  while (millis() < 15000) { 
          ldr0Value = analogRead(sensorPin0);
          if (ldr0Value < 450)
          {myservo2.write(90);
          delay(15);
          }
          else {
                myservo2.write(0);
                display7seg(aciertos++);
                Serial.println(aciertos);
                delay(1500);}
}
if (!fin) {
  myservo2.write(0);
  fin = 1;
}}

Gracias por la atención, espero la gentil ayuda.

¿Cuantos 74xx595 hay: dos o tres?

Mira el código:

void display7seg(int x) {
      digitalWrite (latchPIN, LOW);
      mostrar_numero(x%10);      //<-- escribe las unidades.
      mostrar_numero((x/10)%10); //<-- escribe las decenas.
      mostrar_numero(x/100);     //<-- escribe las cententas.
      digitalWrite (latchPIN, HIGH);
}

Si solo tienes dos registros solo podrás mostrar dos digitos.

Si aciertos es 1, envias primero las unidades (1), luego las decenas (0) y luego las centenas (0); el "1" se ha desplazado al tercer registro que no existe, por lo tanto te aparece en el display 0. No mostrará nada hasta que aciertos sea mayor o igual que 10, que debe mostrar un "1" en el lugar de las decenas.

Hay que cambiar el orden de envio: centenas, decenas, unidades.

Un consejo: Deja de copiar y pegar e intenta entender que hace cada parte del programa!!
Como ya te he dicho usa Serial para mostrar en cada parte que está haciendo y asi podrás saber como funciona el código.

Muchas gracias victorjam!!!.... Bien detectado el error, buen ojo.

Gracias surbyte!!!...

El código quedó OK de la siguiente forma:

#include <Servo.h>

Servo myservo2; 
unsigned int ldr0Value;
const byte sensorPin0 = A0;

const byte dataPIN = 8;
const byte latchPIN = 9;
const byte clockPIN = 10;
byte fin = 0;
int aciertos=0;
int x=0;

byte numero[] = {B00011000, B01111011, B00101100, B00101001, B01001011, B10001001, B10001000, B00111011, B00001000, B00001001};
void mostrar_numero(int x) {
    shiftOut(dataPIN, clockPIN, MSBFIRST, numero[x]);
}

void display7seg(int x) {
      digitalWrite (latchPIN, LOW);
      mostrar_numero(x/100);  //se cambió el orden para que aparezca primero las UNIDADES    
      mostrar_numero(x%10);
      mostrar_numero((x/10)%10);

      digitalWrite (latchPIN, HIGH);
}

void setup() {

    Serial.begin(9600);
    myservo2.attach(2); 
    pinMode(dataPIN, OUTPUT);
    pinMode(latchPIN, OUTPUT);
    pinMode(clockPIN, OUTPUT);
}

void loop() {     
  display7seg(0);
  while (millis() < 15000) { 
          ldr0Value = analogRead(sensorPin0);
          if (ldr0Value < 450)
          {myservo2.write(90);
          delay(15);
          }
          else {
                myservo2.write(0);
                display7seg(++aciertos);
                Serial.println(aciertos);
                delay(1500);}
}
if (!fin) {
  myservo2.write(0);
  delay(10000);display7seg(0);
  fin = 1;
}}