descodificar señales display 7 segmentos

hola:
esta noche lo miro el programa mas detalladamente.
sino te importa voy a documentarte lo que no llego a entender, yo normalmente trabajo con plc y mi pensar de programación es distinta por eso me cuesta entender las cosas, perdona mi ignorancia.
estoy empezando con esto de programación en C y elegí arduino porque me parece una plataforma muy interesante.

Quieres que mejore los comentarios?

hola:
he revisado el programa pero hay cosas que no entiendo, en el programa te he puesto lo que no entiendo.
gracias por tu dedicacion.

// incluimos la libreria LiquidCrystal
#include <LiquidCrystal.h> 

// inicializamos la librería con los numeros pins del interfaz
// cada LCD puede llevar sus propios numeros
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);

const int segmento_a = 30;    // segmento a pin 22
const int segmento_b = 31;    // segmento b pin 23
const int segmento_c = 32;    // segmento b pin 24
const int segmento_d = 33;    // segmento b pin 25
const int segmento_e = 34;    // segmento b pin 26
const int segmento_f = 35;    // segmento b pin 27
const int segmento_g = 36;    // segmento b pin 28
const int digito_1   = 37;    // izquierdo anodo pin 29
const int digito_2   = 38;    // derecho anodo pin 30

const char* E10 = ("hola jose        ");
const char* E11 = ("hola juan        ");
const char* E12 = ("hola pepe        ");
const char* E13 = ("hola luis        ");
const char* E14 = ("hola alejandro   ");
const char* E15 = ("hola manolo      ");
const char* E16 = ("hola david       ");
const char* E17 = ("hola ruben       ");
const char* E18 = ("hola fernando    ");
const char* E19 = ("hola ignacio     ");
const char* E1A = ("adios jose       ");
const char* E1b = ("adios juan       ");
const char* E1C = ("adios alberto    ");
const char* E1d = ("adios javi       ");
const char* E1E = ("adios pepe       ");
const char* E1F = ("adios manolo     ");

int marca_digito1 = 100;
int marca_digito_2 = 100;

byte digito1 = 0;
byte digito2 = 0;
byte segmentos1;
byte segmentos2;
byte Led1, Led2;
bool presentar1, presentar2;     //
                         // abcdefg
const byte matrix[16] = {
// bits     6543210                          entiendo que 0b es el puerto del pin 30 al 38
// digits   abcdefg
         0b1111110,//0
         0b0110000,//1
         0b1101101,//2
         0b1111001,//3
         0b0110011,//4
         0b1011011,//5
         0b1011111,//6
         0b1110000,//7
         0b1111111,//8
         0b1111011,//9
         0b1110111,//a
         0b0011111,//b
         0b1001110,//c
         0b0111101,//d
         0b1001111,//e
         0b1000111 //f
};

byte a,b,c,d,e,f,g;   //creo entender que las entradas de los segmentos las vas a tratar como byte

void setup() {
  Serial.begin(9600);
 
  pinMode(segmento_a, INPUT);
  pinMode(segmento_b, INPUT);
  pinMode(segmento_c, INPUT);
  pinMode(segmento_d, INPUT);
  pinMode(segmento_e, INPUT);
  pinMode(segmento_f, INPUT);
  pinMode(segmento_g, INPUT);
  pinMode(digito1, INPUT);
  pinMode(digito_2, INPUT);

  attachInterrupt(3, irq_digito1, HIGH );  // pin 20                  esta parte no la tengo clara hay que activar los pines 20 y 21 en algun momento?
  attachInterrupt(2, irq_digito2, HIGH );  // pin 21                  esta parte no la tengo clara
 // establecemos el numero de columnas y filas del display 
 lcd.begin(16, 2);
 // enviamos el mensaje a mostrar en el display
 lcd.setCursor(4, 0);
 lcd.print("hola mundo");
 
}

void irq_digito1(){
       a = digitalRead(segmento_a);
       b = digitalRead(segmento_b);
       c = digitalRead(segmento_c);
       d = digitalRead(segmento_d);
       e = digitalRead(segmento_e);
       f = digitalRead(segmento_f);
       g = digitalRead(segmento_g);

       segmentos1 = ~(a<<6 | b<<5 | c<<4 | d<<3 | e<<2 | f<<1 | g) & B01111111;   //entiendo que quieres desplazar datos a la izquierda pero no entiendo el porque
       presentar1 = true;
}

void irq_digito2(){
       segmentos2 = 0;
       a = digitalRead(segmento_a);
       b = digitalRead(segmento_b);
       c = digitalRead(segmento_c);
       d = digitalRead(segmento_d);
       e = digitalRead(segmento_e);
       f = digitalRead(segmento_f);
       g = digitalRead(segmento_g);

       segmentos2 = ~(a<<6 | b<<5 | c<<4 | d<<3 | e<<2 | f<<1 | g) & B01111111;   //entiendo que quieres desplazar datos a la izquierda pero no entiendo el porque
       presentar2 = true;
}
  

void loop() {
    char buffer[30];           //
    

    // digito1 = digitalRead(digito_1);
    // if (digito1) {
    //    segmentos1 = 0;
    //    segmentos1 = (digitalRead(segmento_a)<<6) | (digitalRead(segmento_b) <<5) | (digitalRead(segmento_c)<<4) | (digitalRead(segmento_d)<<3) | (digitalRead(segmento_e)<<2) |(digitalRead(segmento_f)<<1) |(digitalRead(segmento_g)<<0);   
    //    presentar1 = true;
    // }

    // digito2 = digitalRead(digito_2);
    // if (digito2) {
    //    segmentos2 = 0;
    //    segmentos2 = (digitalRead(segmento_a)<<6) | (digitalRead(segmento_b) <<5) | (digitalRead(segmento_c)<<4) | (digitalRead(segmento_d)<<3) | (digitalRead(segmento_e)<<2) |(digitalRead(segmento_f)<<1) |(digitalRead(segmento_g)<<1);   
    //    presentar2 = true;
    // }  
    // if (presentar1) {
    //   Serial.println();
    //   Serial.print("Led1 = ");
    //   Serial.print(segmentos1, BIN);
    // }
    // if (presentar2) {
    //    //sprintf(buffer, "Led2 = %X", segmentos2);                             ¿esta parte es comentada? 
    //    //Serial.println(buffer);
    //   Serial.print(" Led2 = ");
    //   Serial.print(segmentos2, BIN);
      
    // }
    
    if (presentar1 && presentar2) {
      for(int i=0; i<16; i++){
         if (matrix[i] == segmentos1)
            Led1 = i;
         if (matrix[i] == segmentos2)
            Led2 = i;
      }

      Serial.println();
      sprintf(buffer, " Led = %d%d", Led1, Led2);  //no lo tengo muy claro   
      Serial.print(buffer);
      presentar1 = false;
      presentar2 = false;  
    }
}

Si no lees las normas del foro y comienzas a usar los tags para insertar códigos, en lo personal no responderé mas preguntas. Esta es la ultima excepción.

Punto 7, normas del foro, dice como insertar tags.
Edita tu ultimo post e inserta bien el código, por favor!!

Pregunta:

// bits     6543210                          entiendo que 0b es el puerto del pin 30 al 38
// digits   abcdefg

Respueta:
No. He creado un vector de 16 elementos con todos los posibles estados de cada bit. Eso ahorra lo que tu haces en tu sketch donde vives preguntando.

if((segmento_a==HIGH)&&(segmento_b==HIGH)&&(segmento_c==HIGH)&&(segmento_d==HIGH)&&(segmento_e==HIGH)&&(segmento_f==HIGH)&&(segmento_g==LOW)) return cero;

Pregunta:

byte a,b,c,d,e,f,g;   //creo entender que las entradas de los segmentos las vas a tratar como byte

Respuesta
Excato. Como las entradas consumen 7 bits de 8, un byte es la variable mas apropiada para esta tarea. No hace falta definir un int (entero) de 16 bits de los cuales 9 no uso jamás.

Pregunta:

attachInterrupt(3, irq_digito1, HIGH );  // pin 20                  esta parte no la tengo clara hay que activar los pines 20 y 21 en algun momento?
   attachInterrupt(2, irq_digito2, HIGH );  // pin 21                  esta parte no la tengo clara

Respuesta
Ese es el comando para activar la interrupción por Nivel ALTO aunque creo que debo hacerlo por el flanco de subida cuando pasa de LOW a HIGH. De todas formas funciona.
La interrupción de hardware es un recurso que te permite sincronizar eventos cuando éstos ocurren.
Cuando se pone en HIGH el anodo del digito 1 o 2 se activa una u otra interrupción. Leo los segmentos y me aseguro que asi ocurre.
No se si te diste cuenta que tu display esta multiplexado y que todo ocurre con mucha velocidad.
EL Mega tiene 5 interrupcione la 2 esta en el pin 21, y la 3 esta en el pin 20. No hay que tocar mas nada.
Yo ya te di el programa funcional hasta este punto.

Pregunta:

segmentos1 = ~(a<<6 | b<<5 | c<<4 | d<<3 | e<<2 | f<<1 | g) & B01111111;   //entiendo que quieres desplazar datos a la izquierda pero no entiendo el porque

Respuesta
Lo que hago es que lo que leo de los segmentos tome la misma forma de lo que definí en matrix[16] para luego comparar lo que obtenga con esta matriz y saber que digito se ha iluminado.

Pregunta:

 sprintf(buffer, " Led = %d%d", Led1, Led2);  //no lo tengo muy claro   
       Serial.print(buffer);

Respuesta
No me gusta mucho usar tantos Serial.print("Led = "); bla bla bla
En cambio uso sprintf que es un recurso que te permite encapsular una cadena de caracteres en una variable char buffer[30] o sea buffer tiene una longitud de 30 caracteres posibles.

sprintf(buffer, " Led = %d%d", Led1, Led2);

donde lees %d será reemplazado por el valor de la variable que esta luego de la 1er coma, y el segundo %d por lo que esta en la segunda coma. Entonces si Led1 vale 2 y Led2 vale 3 obtienes esto en buffer
buffer = "Led = 23"
que es lo que imprimirá el Serial usando

Serial.print(buffer);

perdon no me di cuenta no volvera a pasar, copie y pegue sin darme cuenta.
gracias por las aclaraciones.

hola ya cambie el post que comentaste.
he probado el programa y cuando la salida de display da 14 por lo que he interpretado via serie la opcion led marca 11.
he conectado todo pero tengo una duda, las entradas de arduino solo interpretan tensión (5voltios) no cero ¿es asi?.
ya que comprobé con un osciloscopio las tensiones, los segmentos son cero cuando están activos.
he colocado dos 74ls04p intermedios para pasar de 0 a +5v todas las señales ¿puede ser posible que pierda señal alguna vez?
un saludo.

Veamos. Necesito saber si tu programa funcionaba o no?
Yo me basé en tu programa
Pero puedo hacerlo de tal modo que sea Anodo o Cátodo común. Ahora esta como ánodo común, o sea, cuando exitas el digito con HIGH (ANODO) se encienden los leds (cátodos)

hola:
siento la tardanza en responder.
mi programa no funcionaba, por eso pregunte y me gustaría saber la causa de que no funcionara.
los comunes son los ánodos y los segmentos son cero, ya que por lo que interpreto en arduino la activación de una entrada tiene que ser en positivo +5 v.
los segmentos al ser un cero los cambio a 5 v para que el arduino interprete esta entrada.
si probé el tuyo y provocando un 14 via serie me daba 1414 todo el rato pero poniendo otro numero se quedaba en 1414
ando un poco liado por el curro pero intento esta semana hacerte un esquema de todo como lo tengo montado.
un saludo.

Tu dime claramente que tipo de display es. Si es Anodo común como estas explicando veré que anda mal.
Creo que lo hice cátodo común.

Lo mas importante, no conectes ningun 74LS04 entre nada y nada porque yo no estoy considerándolo asi.
Para mi es, un display de ANODO COMUN como recién has dicho, con ánodos que obviamente se activan con HIGH y segmentos en LOW. Leo los LOW cada vez que tengo un HIGH en el Anodo.

hola te paso esquema de como lo tengo conectado en proteus
probé sin los 74ls04 como me indicaste y vi por vía serie que marcaba todo el rato 88
perdona vi el mensaje para conectarse via remota pero las placas son del trabajo y me resulta difícil llevármelas a casa y menos molestarte para hacer las pruebas de noche en casa.
la verdad es que me esta desesperando un poco ya que no se si la culpa es mía por si me falla algo en las conexiones, pero menos mal que soy bastante cabezón y sigo insistiendo.
la velocidad de oscilación de los ánodos tiene algo que ver? ya que claro los segmentos también oscilan a la misma velocidad.
si las salidas de la placa el display es ánodo común estoy seguro.

esquema descodificador display de 7 segmentos v1.zip (16.2 KB)

Bien. Acabo de ver tu mensaje. Veré ahora tu simulación y como corregir el programa para que funcione.
No te preocupes lo vamos a sacar adelante.
Corrijo y edito aca mismo asi que sigue atento.

No sabía nada de los 24V. Pregunto y que pasa en los segmentos, me preocupa ahora que le este llegando al mega 24V en los momentos de no lectura. Eso es dañino.
Puedes confirmar que no es asi?

La resistencia divisora de tensión debería estar mas cerca de 2.5K pero supongo que asi funciona bien.
si los segmentos tienen 24 Vas a tener que usar el mismo arreglo para cada uno.
O una alternativa con zener de 5.1V sería tambien una buena solución. Tal vez mas barato las resistencias.

Confirma el tema de los segmentos.

hola:
te confirmo que la activación de los segmentos es por 0v.
sino tiene salida no hay nada.
un saludo

Lo de los segmenos esta bien, me parece lógico que trabajen a 0 si como antes me has dicho el punto común trabaja a 24V, pero lo que me preocupa es si la tensión sube a 24 VDC en los segmentos durante su estado de HIGH?

Veré porque te da fallos en la lectura.

realice un circuito en una protoboard y en los anodos tiene puesto en serie una resistencia de unos 800 ohmios
en los segmentos va directo y el display doble de 7 segmentos funciona correctamente

No se arma asi.. pero bueno.
Va un resistor por segmento.

Bien enntonces tenemos 24V R + 800 anodo catodo gnd

y sigue fallando la detección?

No con el display funciona correctamente

que funcione no significa que este bien.
La corriente es X por segmento, y cuando todos los segmentos estan encendidos la R en el anodo común disipa la corriente x 7. Puede ser que no le haga nada pero no es lo que suele usar.
Se colocan siempre 7 resistores y no uno en el anodo o cátodo común.

hola:
quise empezar ha hacer esto para hacer la simulación de los displays con otro arduino pero no entiendo porque no me hace la intermitencia

int pausa=1000; // Variable que define el intervalo
                // de tiempo entre cada digito
int digito_1 = 0;
int velocidad_anodos=100;
int anodos=0;
 
void setup()
{
  pinMode(7, OUTPUT);  // Asignación de las salidas digitales
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(40, OUTPUT);
  pinMode(41, OUTPUT);   
}
 
void display (int a, int b, int c, int d, int e, int f, int g)
// Funcion del display
{
  digitalWrite (7,a);   //Se reciben 7 variables y se asignan
  digitalWrite (8,b);   //a cada una de las salidas
  digitalWrite (9,c);
  digitalWrite (10,d);
  digitalWrite (11,e);
  digitalWrite (12,f);
  digitalWrite (13,g);
  
}
 
void loop() //Funcion principal
// Dependiendo de cada dígito, se envía a la función display
// los estados (0 y 1) a cada uno de los segmentos
{
anodos = 0;

  display (1,1,1,1,1,1,0); //escribe 0
  delay(pausa);
  display (0,1,1,0,0,0,0); //escribe 1
  delay(pausa);
  display (1,1,0,1,1,0,1); //escribe 2
  delay(pausa);
  display (1,1,1,1,0,0,1); //escribe 3
  delay(pausa);
  display (0,1,1,0,0,1,1); //escribe 4
  delay(pausa);
  display (1,0,1,1,0,1,1); //escribe 5
  delay(pausa);
  display (1,0,1,1,1,1,1); //escribe 6
  delay(pausa);
  display (1,1,1,0,0,0,0); //escribe 7
  delay(pausa);
  display (1,1,1,1,1,1,1); //escribe 8
  delay(pausa);
  display (1,1,1,0,0,1,1); //escribe 9
  delay(pausa);
  display (1,1,1,0,1,1,1); //escribe A
  delay(pausa);
  display (0,0,1,1,1,1,1); //escribe b
  delay(pausa);
  display (1,0,0,1,1,1,0); //escribe C
  delay(pausa);
  display (0,1,1,1,1,0,1); //escribe d
  delay(pausa);
  display (1,0,0,1,1,1,1); //escribe E
  delay(pausa);
  display (1,0,0,0,1,1,1); //escribe F
  delay(pausa);

if (anodos==0){                     //intermitencia a la vez que da los segmentos
   digitalWrite(40,HIGH);           // porque no hace este bloque todo el rato?
   digitalWrite(41,LOW);
   delay(velocidad_anodos);
   digitalWrite(40,LOW);
   digitalWrite(41,HIGH);
   delay(velocidad_anodos);
  }  
 
}

mi idea es como ya te comente que no puedo disponer de las placas todo el rato simular en un arduino uno las salidas del display y con el mega descodificarlas para que me de los textos en el display y asi poder trabajar en casa tranquilo y ver los problemas,
una vez que funcione ya mirare como interactuar con la otra placa si te parece bien.
intento ir paso a paso ya que estoy empezando.

eso es lo que hago yo con mi simulación en proteus.