Marcador deportivo con 74HC595 y BT HC-05 (En construcción)

Hola, me presento, Soy David Usaji, de Cádiz (España) tengo 46 años y he empezado ahora en el mundo Arduino. tengo conocimientos de electrónica, pero la programación se me escapa un poco.

Estoy creando un contador con 4 dígitos de 7 segmentos que cuenten decenas. Usando los 74hc595 no logro que el segundo marcador (dos dígitos) haga su función, sólo marca "00" cuando el primero llega a "99"

/*En este proyecto se contará desde el 0 hasta el 99 con contadores que suben y bajan
*/
int pinLatch = 11; //Pin para el latch de los 74CH495 pin 12
int pinDatos = 10; //Pin para Datos serie del 74CH495 pin 14
int pinReloj = 12;  //Pin para reloj del 74CH495 pin 11
int pinLatch2 = 9; //Pin para el latch de los 74CH495
int pinDatos2 = 7; //Pin para Datos serie del 74CH495
int pinReloj2 = 8; //Pin para reloj del 74CH495
int i=0;         //Número de las decenas equipo 1
int j=0;        //Número de las unidades equipo 1
int i2=0;      //Número de las decenas equipo 2
int j2=0;     //Número de las unidades equipo 2
int PULIZSUBE = 6;   // pusaldor izquierdo sube
int PULIZRBAJA = 5; // Pulsador izquierdo baja
int PULDESUBE = 4; // Pulsador derecho sube
int PULDEBAJA = 3; // Pulsador derecho baja

// Salidas 74hc595 para display 7 segmentos
// Pin 15 A
// Pin 1  B
// Pin 2  C
// Pin 3  D
// Pin 4  E
// Pin 5  F
// Pin 6  G
// Pin 7  DP
// Pin 8  GND

byte digitOne[]= {
  // Codificación hexadecimal de los dígitos decimales en el display de 7 segmentos
  //0xEE, 0x82, 0xDC, 0xD6, 0xB2, 0x76, 0x7E, 0xC2, 0xFE, 0xF6};
	B11111100, //0				
 	B01100000, //1
	B11011010, //2
  	B11110010, //3
    B01100110, //4
    B10110110, //5
    B10111110, //6
    B11100000, //7
    B11111111, //8
    B11100110}; //9

byte digitOne1[]= {
  // Codificación hexadecimal de los dígitos decimales en el display de 7 segmentos
  //0xEE, 0x82, 0xDC, 0xD6, 0xB2, 0x76, 0x7E, 0xC2, 0xFE, 0xF6};
	B11111100, //0				
 	B01100000, //1
	B11011010, //2
  	B11110010, //3
        B01100110, //4
        B10110110, //5
       B10111110, //6
       B11100000, //7
       B11111111, //8
       B11100110}; //9


void setup(){
  pinMode(pinLatch,OUTPUT);
  pinMode(pinDatos,OUTPUT);
  pinMode(pinReloj,OUTPUT);
  pinMode(pinLatch2,OUTPUT);
  pinMode(pinDatos2,OUTPUT);
  pinMode(pinReloj2,OUTPUT);
}

void loop(){

 // Para que imprima del 0 al 99
  
  
for(i=0; i<10; i++){      //Aumneta en uno, hasta que llegue a 10, el numero de las decenas
for(j=0; j<10; j++){    //Aumneta en uno, hasta que llegue a 10, el numero de las unidades
      digitalWrite(pinLatch, LOW);
      shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[j]);  // digitOne unidades
      shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[i]);  //digitOne decenas
      digitalWrite(pinLatch, HIGH);
      delay(500);

       }
   }
      
       // Para que imprima del 0 al 99
  for(i=0; i<10; i++){      //Aumneta en uno, hasta que llegue a 10, el numero de las decenas
    for(j=0; j<10; j++){    //Aumneta en uno, hasta que llegue a 10, el numero de las unidades
      digitalWrite(pinLatch2, LOW);
      shiftOut(pinDatos2, pinReloj2, LSBFIRST, digitOne1[i2]);  // digitOne unidades
      shiftOut(pinDatos2, pinReloj2, LSBFIRST, digitOne1[j2]);  //digitOne decenas
      digitalWrite(pinLatch2, HIGH);
      delay(500);
             }
  	  }
     }
 
-----------------------------------------------------------------------------------------------------------------------

Los interruptores aún no los tengo configurados, ya que tengo algo de lio con los códigos.

Estoy empezando en esto, y la verdad no se porque he tardado tanto. El mundo Arduino es fascinante.

Varios errores según mi enfoque.
No separes los 595 ponlos todos en cascada y envias un único número subdividido como corresponda.
Ahora tienes pinDatos y pinDatos2, hablo de tener un solo pin que envia a todos los 595. Los 4 en cascada.
El número sera un entero que va de 0 a 9999. Lo vas subdividiendo en unidades decenas centenas y unidades de mil y envias eso a cada digito del registro de desplazamiento 595.

Bienvenido paisano.
Básicamente el error lo tienes en la variables "contadoras" del segundo bloque de fors "i" y "j", y luego haces un LSBFIRST con las variables "I2" y "J2", debes unificarlas.
Otras cosillas que no afectarían al funcionamiento:

  • Repites la codificación binaria de BCD a 7seg, con una sola bastaría.
  • Esas variables "contadoras" las estas definiendo como globales y te estän gastando memoria, usualmente es mejor declararlas locales solo para los for y cuando acaben estos, se destruyen y no gastamos memoria.

Teniendo en cuenta todo esto prueba tu codigo modificado:

/*En este proyecto se contará desde el 0 hasta el 99 con contadores que suben y bajan
*/
int pinLatch = 11; //Pin para el latch de los 74CH495 pin 12
int pinDatos = 10; //Pin para Datos serie del 74CH495 pin 14
int pinReloj = 12;  //Pin para reloj del 74CH495 pin 11
int pinLatch2 = 9; //Pin para el latch de los 74CH495
int pinDatos2 = 7; //Pin para Datos serie del 74CH495
int pinReloj2 = 8; //Pin para reloj del 74CH495
//int i = 0;       //Número de las decenas equipo 1
//int j = 0;      //Número de las unidades equipo 1
//int i2 = 0;    //Número de las decenas equipo 2
//int j2 = 0;   //Número de las unidades equipo 2
int PULIZSUBE = 6;   // pusaldor izquierdo sube
int PULIZRBAJA = 5; // Pulsador izquierdo baja
int PULDESUBE = 4; // Pulsador derecho sube
int PULDEBAJA = 3; // Pulsador derecho baja

// Salidas 74hc595 para display 7 segmentos
// Pin 15 A
// Pin 1  B
// Pin 2  C
// Pin 3  D
// Pin 4  E
// Pin 5  F
// Pin 6  G
// Pin 7  DP
// Pin 8  GND

byte digitOne[] = {
  // Codificación hexadecimal de los dígitos decimales en el display de 7 segmentos
  //0xEE, 0x82, 0xDC, 0xD6, 0xB2, 0x76, 0x7E, 0xC2, 0xFE, 0xF6};
  B11111100, //0
  B01100000, //1
  B11011010, //2
  B11110010, //3
  B01100110, //4
  B10110110, //5
  B10111110, //6
  B11100000, //7
  B11111111, //8
  B11100110  //9
}; 
/*
byte digitOne1[] = {
  // Codificación hexadecimal de los dígitos decimales en el display de 7 segmentos
  //0xEE, 0x82, 0xDC, 0xD6, 0xB2, 0x76, 0x7E, 0xC2, 0xFE, 0xF6};
  B11111100, //0
  B01100000, //1
  B11011010, //2
  B11110010, //3
  B01100110, //4
  B10110110, //5
  B10111110, //6
  B11100000, //7
  B11111111, //8
  B11100110  //9
}; //9
*/

void setup() {
  pinMode(pinLatch, OUTPUT);
  pinMode(pinDatos, OUTPUT);
  pinMode(pinReloj, OUTPUT);
  pinMode(pinLatch2, OUTPUT);
  pinMode(pinDatos2, OUTPUT);
  pinMode(pinReloj2, OUTPUT);
}

void loop() {

  // Para que imprima del 0 al 99


  for (int i = 0; i < 10; i++) { //Aumneta en uno, hasta que llegue a 10, el numero de las decenas
    for (int j = 0; j < 10; j++) { //Aumneta en uno, hasta que llegue a 10, el numero de las unidades
      digitalWrite(pinLatch, LOW);
      shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[j]);  // digitOne unidades
      shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[i]);  //digitOne decenas
      digitalWrite(pinLatch, HIGH);
      delay(500);

    }
  }

  // Para que imprima del 0 al 99
  for (int i = 0; i < 10; i++) { //Aumneta en uno, hasta que llegue a 10, el numero de las decenas
    for (int j = 0; j < 10; j++) { //Aumneta en uno, hasta que llegue a 10, el numero de las unidades
      digitalWrite(pinLatch2, LOW);
      shiftOut(pinDatos2, pinReloj2, LSBFIRST, digitOne[i]);  // digitOne unidades
      shiftOut(pinDatos2, pinReloj2, LSBFIRST, digitOne[j]);  //digitOne decenas
      digitalWrite(pinLatch2, HIGH);
      delay(500);
    }
  }
}

Saludos.

el segundo (o sea, derecha) no marca nada. El izquierdo empieza a contar.

¿Ni cuando acaba el primero?, bajale los delays para agilizar la prueba un poco.

Nada, hace bucle el primero.
Mira que he buscado y rebuscado para hacer el marcador por Google. Pero sólo encuentro de un dígito y con errores.

Me respondo solo, si, cuando llega a 99 empieza el segundo, pero decenas y unidades, estan invertidos los segmentos cambie i por j en el segundo, para no tocar el circuito

Porque tienes invertidas su impresion respecto al primero cambia en el segundobloque a:

shiftOut(pinDatos2, pinReloj2, LSBFIRST, digitOne[j]);  // digitOne unidades
shiftOut(pinDatos2, pinReloj2, LSBFIRST, digitOne[i]);  //digitOne decenas

Eso hice. y correcto.
Pero claro, lo que yo busco es que los dos empiecen de 00 al mismo tiempo, y ya luego meterle los pulsadores.
Eres de Cádiz tb?

Sevillano,residente en Madrid.
Para lo qur buscas usa un solo for anidado:

void loop() {
  // Para que imprima del 0 al 99
  for (int i = 0; i < 10; i++) { //Aumneta en uno, hasta que llegue a 10, el numero de las decenas
    for (int j = 0; j < 10; j++) { //Aumneta en uno, hasta que llegue a 10, el numero de las unidades
      digitalWrite(pinLatch, LOW);
      shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[j]);  // digitOne unidades
      shiftOut(pinDatos, pinReloj, LSBFIRST, digitOne[i]);  //digitOne decenas
      shiftOut(pinDatos2, pinReloj2, LSBFIRST, digitOne[j]);  // digitOne unidades
      shiftOut(pinDatos2, pinReloj2, LSBFIRST, digitOne[i]);  //digitOne decenas
      digitalWrite(pinLatch, HIGH);
      delay(500);
    }
  }
}

Esquema propuesto

y acá el código coincidente con este esquema. Te faltarán los pulsadores pero te lo dejo a ti.
Puse un contador que se incrementa hasta 9999.

#define NUM_OF_DISPLAY 4

//Pin connected to Strobe (pin 1) of 4094
int pinLatch = 11; //Pin para el latch de los 74CH495 pin 12
//Pin connected to Data (pin 2) of 4094
int pinDatos = 10;      //Pin para Datos serie del 74CH495 pin 14
//Pin connected to Clock (pin 3) of 4094
int pinReloj = 12;  //Pin para reloj del 74CH495 pin 11
char shiftOutBuffer[NUM_OF_DISPLAY]={0};

byte segChar[]={
  0b00111111,
  0b00000110,
  0b01011011,
  0b01001111,
  0b01100110,
  0b01101101,
  0b01111101,
  0b00000111,
  0b01111111,
  0b01101111,
  0b00000000,
};

int contador = 0;

void update_display(int n) {
   i = 0;
   while (n > 0) {
      shiftOutBuffer[i] = n%10;  // módulo del valor, siempre se queda con el último digito
      n = n/10;                  // voy quitando 1 digito x vez
      i++;                       // incremento el digito
  }
  digitalWrite(pinLatch, LOW);
  for (i=NUM_OF_DISPLAY-1;i>-1;i--) {     
      shiftOut(pinDatos, pinReloj, MSBFIRST, segChar[shiftOutBuffer[i]]);             
  }
  digitalWrite(pinLatch, HIGH);      
}

void setup() {
  
  pinMode(pinLatch, OUTPUT);
  pinMode(pinReloj, OUTPUT);
  pinMode(pinDatos, OUTPUT);
}

void loop() {
  update_display(contador++);
  if (contador > 9999) contador = 0;
  delay(500);
}

Estimado @Surbyte todo lo que porpones es correcto, pero aunque el Po no lo indica creo que lo que intenta hacer no es un conador de o a 9999 , creo que es un marcador para dos equipos de no se que juego de ahi que encadene los 595 por parejas.

Ahh okay. Mi enfoque entonces no es el adecuado aunque podria adaptarse pero no es el caso.
Igualmente no usaria 4 595, con 2 basta, o uno solo y multiplexado pero esta aprendiendo asi que excelente lo realizado.

EDITO:

for (int i = 0; i < 10; i++) { //Aumneta en uno, hasta que llegue a 10, el numero de las decenas
    for (int j = 0; j < 10; j++) { //Aumneta en uno, hasta que llegue a 10, el numero de las unidades

Esto nome parece muy inteligente.
Si se trantan de dos contadores independientes, entonces tratemoslos como lo que son.
Dos contadores que pueden simplificarse desde la programación pero que siguen siendo dos.
La única preocupación serán los pulsadores ascendentes y descendentes. Entonces vamos al trabajo y dejemos los ciclos for() que solo enturbian el objetivo.

cont int PULIZSUBE   = 6;    // pusaldor izquierdo sube
cont int PULIZBAJA   = 5;    // Pulsador izquierdo baja
cont int PULDESUBE   = 4;    // Pulsador derecho sube
cont int PULDEBAJA   = 3;    // Pulsador derecho baja

int estadoIzSube, estadoIzBaja, estadoDeSube, estadoDeBaja;
int estadoIzSubeAnt, estadoIzBajaAnt, estadoDeSubeAnt, estadoDeBajaAnt;

#define NUM_OF_DISPLAY 2

int pinLatch = 11; //Pin para el latch de los 74CH495 pin 12
int pinDatos = 10; //Pin para Datos serie del 74CH495 pin 14
int pinReloj = 12;  //Pin para reloj del 74CH495 pin 11
int pinLatch2 = 9; //Pin para el latch de los 74CH495
int pinDatos2 = 7; //Pin para Datos serie del 74CH495
int pinReloj2 = 8; //Pin para reloj del 74CH495


char shiftOutBuffer[NUM_OF_DISPLAY]={0};

byte segChar[]={
  0b00111111,
  0b00000110,
  0b01011011,
  0b01001111,
  0b01100110,
  0b01101101,
  0b01111101,
  0b00000111,
  0b01111111,
  0b01101111,
  0b00000000,
};

int contador1 = 0;
int contador2 = 0;

void update_display(int modo, int n) {
   i = 0;
   while (n > 0) {
      shiftOutBuffer[i] = n%10;  // módulo del valor, siempre se queda con el último digito
      n = n/10;                  // voy quitando 1 digito x vez
      i++;                       // incremento el digito
  }
  if (modo == 1) {
      digitalWrite(pinLatch, LOW);
      for (i=NUM_OF_DISPLAY-1;i>-1;i--) {     
          shiftOut(pinDatos, pinReloj, MSBFIRST, segChar[shiftOutBuffer[i]]);             
      }
      digitalWrite(pinLatch, HIGH);      
  } else {
      digitalWrite(pinLatch2, LOW);
      for (i=NUM_OF_DISPLAY-1;i>-1;i--) {     
          shiftOut(pinDatos2, pinReloj2, MSBFIRST, segChar[shiftOutBuffer[i]]);             
      }
      digitalWrite(pinLatch2, HIGH);          
  }
}

void setup() {
  pinMode(pinLatch, OUTPUT);
  pinMode(pinReloj, OUTPUT);
  pinMode(pinDatos, OUTPUT);
  pinMode(pinLatch2, OUTPUT);
  pinMode(pinReloj2, OUTPUT);
  pinMode(pinDatos2, OUTPUT);
}

void loop() {
  estadoIzSube = digitalRead(PULIZSUBE);
  estadoIzBaja = digitalRead(PULIZBAJA);
  estadoDeSube = digitalRead(PULDESUBE);
  estadoDeBaja = digitalRead(PULDEBAJA);

  if (estadoIzSube && !estadoIzSubeAnt) {
      contador1++;
  }
  estadoIzSubeAnt = estadoIzSube;
  
  if (estadoIzBaja && !estadoIzBajaAnt) {
      contador1--;
  }
  estadoIzBajaAnt = estadoIzBaja;
  update_display(1, contador1);
  
  if (estadoDeSube && !estadoDeSubeAnt) {
      contador2++;
  }
  estadoDeSubeAnt = estadoDeSube;
  
  if (estadoDeBaja && !estadoDeBajaAnt) {
      contador2--;
  }
  estadoDeBajaAnt = estadoDeBaja;
  
  update_display(2, contador2);
}

Moderador:
Por favor, deja de editar tu post inicial. Llevas 5 ediciones, son demasiadas.
No quiero leer cosas que se te dicen y luego resulta que estan cambiadas por ajustes que vas haciendo, no pasa nada en poner un post donde indiques los cambios que vas realizando.
Es normal que todos nos equivoquemos.
Si editas coloca EDITO, pero mejor hacerlo en un nuevo posteo.

Unas mínimas correcciones, errores de tipeo supongo.

cont int PULIZSUBE   = 6;    // pusaldor izquierdo sube
cont int PULIZBAJA   = 5;    // Pulsador izquierdo baja
cont int PULDESUBE   = 4;    // Pulsador derecho sube
cont int PULDEBAJA   = 3;    // Pulsador derecho baja

Supongo que querías decir:

const int PULIZSUBE   = 6;    // pusaldor izquierdo sube
const int PULIZBAJA   = 5;    // Pulsador izquierdo baja
const int PULDESUBE   = 4;    // Pulsador derecho sube
const int PULDEBAJA   = 3;    // Pulsador derecho baja

Y en este trozo te falta el tipo de variable.

void update_display(int modo, int n) {
   i = 0;
   int i = 0;

Saludos

Si, es es la idea, pensé que como eran independientes, en lugar de multiplexar, como tenía los 595, hacerlos independientes.
Perdón por lo de la edición.
Estoy enganchado a esto. :joy::sweat_smile::sweat_smile: pero a veces me pierdo, creo que me he metido en algo complicado para mí para empezar.
Pensé que los init i=0 debían ser cada uno para cada grupo de 595, para que no interfiesen.

Os agradezco mucho el interés que estáis prestando.

Por cierto, creo que tienes mal hecho el pullup de los botones.

1 Like

llevas razón, estaban al revés. Respecto al contador manual con pulsadores, empiezan en las decenas. Cuando pulso Sube Izq, marca 10 en los dos displays (Parejas) sigo pulsando sube izqu. y siguen subiendo los dos.
Cuando pulso sube der. sube solo el derecho, pero cuando bajo, sólo baja hasta el último numero que esté marcado en izquierdo.

Coloca Serial.prints y mira como los imprime por monitor serie
Si empieza por la decena es porque el primer digito que imprime esta a la izquierda, no se te ocurrió?
Invierte el update en lugar de barrer de mayor a menor que lo haga de menor a mayor. Hay que analizar las cosas.

 if (modo == 1) {
      digitalWrite(pinLatch, LOW);
      for (i=0;  i < NUM_OF_DISPLAY; i++) {     
          shiftOut(pinDatos, pinReloj, MSBFIRST, segChar[shiftOutBuffer[i]]);             
      }
      digitalWrite(pinLatch, HIGH);      
  } else {
      digitalWrite(pinLatch2, LOW);
      for (i=0;  i < NUM_OF_DISPLAY; i++) {     
          shiftOut(pinDatos2, pinReloj2, MSBFIRST, segChar[shiftOutBuffer[i]]);             
      }
      digitalWrite(pinLatch2, HIGH);          
  }
1 Like

Por lo de los dígitos no tengo problema para cambiarlo de orden. Sólo es que cuando puse el primer código, el izquierdo si contaba bien de unidades a decenas.

Al poner este último código , muestra cero y sólo funciona el interruptor bajo izqu (en las dos unidades) pero mostrando un solo segmento. Sigo revisando.

primer código, refiriéndome al que tenía yo. perdón