Decodificador BCD a Decimal (Especial)

La tabla de verdad qeu has publicado hasta ahroa tiene entradas irrelevantes. Eso es básico en lógica booleana.
Se simplfican 4 de tus entradas en una sola por ahora.
hasta que presentes una tabla de verdad mas compleja, lo que veo hasta ahora esta resuelto con lo el código que te puse.
Si buscas en GOOGLE: Arduino Band decoder encontraras soluciones terminadas muy bien hechas.

surbyte:
La tabla de verdad qeu has publicado hasta ahroa tiene entradas irrelevantes. Eso es básico en lógica booleana.
Se simplfican 4 de tus entradas en una sola por ahora.
hasta que presentes una tabla de verdad mas compleja, lo que veo hasta ahora esta resuelto con lo el código que te puse.

Si es asi, no me doy cuenta.

surbyte:
Si buscas en GOOGLE: Arduino Band decoder encontraras soluciones terminadas muy bien hechas.

Eso es justamente lo que no queria, copiar algo ya hecho, tambien podria comprar uno y no romperme la cabeza jaja :slight_smile:

Cuando estudias lógica digital te enseñan a simplificar tablas.
Tu tabla tiene 4 entradas que se simplifican en 1 sola, las otras 4 entradas BCD no admiten simplificación. Eso es sabido.

Por ahora
BAND
WARC = BAND
3_W=!BAND
3_B=!BAND
Aca te muestro las simplificaciones pero cualquiera de estas supuestas entradas puede servir para expresar las otras.

Asi que si no le encuentras cambios a las salidas respecto de estas 4 entradas, con tener a BAND y las 4 entradas BCD tendras la salida que buscas.
AUTO funcionará como expuse en el código que te presenté y MANUAL tu dirás.
Prueba a ver si satisface tu necesidad.

Hola Surbyte!

Acabo de probar el codigo, responde al bcd de entrada sin problemas, el unico detalle que le veo, es que cuando la entrada es 0000, las salidas deben estar todas apagadas, por lo tanto la salida 160 corresponde a la entrada 0001.

Aqui hice un video, se ve un poco mal porque lo grabe a baja calidad.

Gracias.

Esta corrida la tabla que definí entonces?

//                        160m 80m 40m 30m 20m 17m 15m 12m 10m  6m
const byte Salidas[10] = { A5, A4,  A3, A2, 2,  3,  4,  5,  6,  7};
const byte matrix[11][10] = {
                     {  0,  0,   0,  0,  0,  0,  0,  0,  0,  0},   // 0                    
                     {  1,  0,   0,  0,  0,  0,  0,  0,  0,  0},   // 1
                     {  0,  1,   0,  0,  0,  0,  0,  0,  0,  0},   // 2
                     {  0,  0,   1,  0,  0,  0,  0,  0,  0,  0},   // 3
                     {  0,  0,   0,  1,  0,  0,  0,  0,  0,  0},   // 4
                     {  0,  0,   0,  0,  1,  0,  0,  0,  0,  0},   // 5
                     {  0,  0,   0,  0,  0,  1,  0,  0,  0,  0},   // 6
                     {  0,  0,   0,  0,  0,  0,  1,  0,  0,  0},   // 7
                     {  0,  0,   0,  0,  0,  0,  0,  1,  0,  0},   // 8
                     {  0,  0,   0,  0,  0,  0,  0,  0,  1,  0},   // 9
                     {  0,  0,   0,  0,  0,  0,  0,  0,  0,  1}};  // 10

Mira a ver si asi funciona correctamente.

Hola Surbyte, como estas?

Probe la nueva matriz, en 11x10 el resultado es el mismo, probe de hacerla de 11x11 agregando un pin mas de salida, y ahi si funciona, ahora estoy probando de cambiar ese pin que agregue por alguna variable interna, para no desperdiciarlo.

Gracias.

No necesitas ninguna variable interna. Te estoy diciendo que de las 4 variables que pusiste en la tabla 3 estan de mas y quieres agregar otra?
Con BCD y una variable por ahora estas bien.

surbyte:
No necesitas ninguna variable interna. Te estoy diciendo que de las 4 variables que pusiste en la tabla 3 estan de mas y quieres agregar otra?
Con BCD y una variable por ahora estas bien.

Hola! Creo que no me he sabido explicar, o tu no me has entendido :slight_smile:

La matriz que tu me propusiste al principio, era de 10x10, luego fue de 11x10, con lo cual obtuve el mismo resultado, por lo cual, agregue una salida mas, para confeccionar una matriz de 11x11, y alli SI funciono, el tema es que ese pin (salida) es innecesario.

Gracias.

No se que decirte.
No veo la matriz. No entiendo a que salida te refieres.
Yo el programa lo simulé y funcionaba pero claro tu eres quien sabe como debe responder.
Dijiste que cuando ponías BCD 0000 encendía la respuesta 160m o sea salida 1
Al agregar una fila mas con todas las salidas en 0 hice que con entrada BCD 0000 tuvieras salida 0000000000 10 0s
Asi que no veo porque necesitas otra salida?

Porque no pones tu matriz modificada y hablamos el mismo idioma?

//                        160m 80m 40m 30m 20m 17m 15m 12m 10m  6m
const byte Salidas[11] = {A1,  A5, A4,  A3, A2, 2,  3,  4,  5,  6,  7};
const byte matrix[11][11] = {
                     {  0,  0,   0,  0,  0,  0,  0,  0,  0,  0},   // 0                    
                     {  1,  0,   0,  0,  0,  0,  0,  0,  0,  0},   // 1
                     {  0,  1,   0,  0,  0,  0,  0,  0,  0,  0},   // 2
                     {  0,  0,   1,  0,  0,  0,  0,  0,  0,  0},   // 3
                     {  0,  0,   0,  1,  0,  0,  0,  0,  0,  0},   // 4
                     {  0,  0,   0,  0,  1,  0,  0,  0,  0,  0},   // 5
                     {  0,  0,   0,  0,  0,  1,  0,  0,  0,  0},   // 6
                     {  0,  0,   0,  0,  0,  0,  1,  0,  0,  0},   // 7
                     {  0,  0,   0,  0,  0,  0,  0,  1,  0,  0},   // 8
                     {  0,  0,   0,  0,  0,  0,  0,  0,  1,  0},   // 9
                     {  0,  0,   0,  0,  0,  0,  0,  0,  0,  1}};  // 10

Hola Surbyte, buenos dias, esa fue la modificación que funciono correctamente.

Ya veo el error. El error no esta en la matriz y en la definición de salidas.
sino acá

  valorBCDAnt = valorBCD;
  for (int i=0; i<=10; i++) {
      if (i== valorBCD) 
        digitalWrite(Salidas[i], HIGH);
      else 
        digitalWrite(Salidas[i], LOW);
  }

cuando valorBCD = 0 intenta poner en 1 la salida 0 y eso no esta bien
Tu agregaste una salida que no sirve.
Luego lo miro y corrijo el problema

Bueno no se para que hice la matriz y luego no la usé.. algo me pasó al momento de programarlo y olvidé el elemento clave.
esta modificación contempla la matrix que acabo de postear sin la salida extra que tu pones
Usa esta matriz.. no confundas con la tuya.

//                     BCDA BCDB BCDC BCDD WARC  BAND
const byte Entradas[6] = {   8,   9,  10,  11,  12,   13};
//-----------------------------
//                          160m 80m 40m 30m  20m 17m 15m 12m 10m  6m
const byte Salidas[10]    = { A5, A4, A3, A2,  2,  3,  4,  5,  6,  7};
const byte matrix[11][10] = {
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0},   // 0                    
                            {  1,  0,  0,  0,  0,  0,  0,  0,  0,  0},   // 1
                            {  0,  1,  0,  0,  0,  0,  0,  0,  0,  0},   // 2
                            {  0,  0,  1,  0,  0,  0,  0,  0,  0,  0},   // 3
                            {  0,  0,  0,  1,  0,  0,  0,  0,  0,  0},   // 4
                            {  0,  0,  0,  0,  1,  0,  0,  0,  0,  0},   // 5
                            {  0,  0,  0,  0,  0,  1,  0,  0,  0,  0},   // 6
                            {  0,  0,  0,  0,  0,  0,  1,  0,  0,  0},   // 7
                            {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0},   // 8
                            {  0,  0,  0,  0,  0,  0,  0,  0,  1,  0},   // 9
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  1}};  // 10
                     

//-------------------------------
int valorBCD, valorBCDAnt=0;
//----------------------------
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  for (int i=0; i<6; i++) {
      pinMode(Entradas[i], INPUT);
  }
//-------------------------------
  for (int i=0; i<10; i++) {
      pinMode(Salidas[i], OUTPUT);
  }  
}


void loop(){
 
  valorBCD = LeerBCDDecimal();
  if (valorBCD != valorBCDAnt)
      Serial.println(valorBCD);
  valorBCDAnt = valorBCD;
  for (int i=0; i<=10; i++) {
      digitalWrite(Salidas[i], matrix[valorBCD][i]);
  }
         
}

int LeerBCDDecimal(){
  
   int ValorDecimal;

   byte datA = digitalRead(Entradas[0]);
   byte datB = digitalRead(Entradas[1]);
   byte datC = digitalRead(Entradas[2]);
   byte datD = digitalRead(Entradas[3]);

   ValorDecimal = (datD << 3) + (datC <<2) + (datB << 1) + datA;
   byte WARC = digitalRead(Entradas[4]);
   byte BAND = digitalRead(Entradas[5]);


   if (WARC && BAND) {
     switch (ValorDecimal) {
         case 4:
         case 6:
         case 8:
                 ValorDecimal = 7;   // revisar
                 break;
         case 5:
         case 7:
         case 9:
                 ValorDecimal = 8;
                 break;
         default: 
                 break;
     }
   }

   return ValorDecimal;
}

Hola Surbyte, como estas?

Acabo de probar el nuevo codigo, y tiene un pequeño bug a partir del bcd de entrada = 1011 hasta 1111.

Con 1011, quedan activas todas las salidas.
Con 1100, quedan activas 160, 80, 40, 30, 20 y 17.
Con 1101, quedan activas todas las salidas.
Con 1110, 160, 40, 20, 15 y 12.
Con 1111, quedan activas 160 y 10.

Lo que hice, fue poner la matriz de 17x10 de esta manera:

//                          160m 80m 40m 30m  20m 17m 15m 12m 10m  6m
const byte Salidas[10]    = { A5, A4, A3, A2,  2,  3,  4,  5,  6,  7};
const byte matrix[17][10] = {
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0},   // 0                    
                            {  1,  0,  0,  0,  0,  0,  0,  0,  0,  0},   // 1
                            {  0,  1,  0,  0,  0,  0,  0,  0,  0,  0},   // 2
                            {  0,  0,  1,  0,  0,  0,  0,  0,  0,  0},   // 3
                            {  0,  0,  0,  1,  0,  0,  0,  0,  0,  0},   // 4
                            {  0,  0,  0,  0,  1,  0,  0,  0,  0,  0},   // 5
                            {  0,  0,  0,  0,  0,  1,  0,  0,  0,  0},   // 6
                            {  0,  0,  0,  0,  0,  0,  1,  0,  0,  0},   // 7
                            {  0,  0,  0,  0,  0,  0,  0,  1,  0,  0},   // 8
                            {  0,  0,  0,  0,  0,  0,  0,  0,  1,  0},   // 9
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  1},   //10
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0},
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0},
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0},
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0},
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0},
                            {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}};

Quizas no sea lo correcto, pero "funciona" jaja.

Y aqui:

if (WARC && BAND) {
     switch (ValorDecimal) {
         case 4:
         case 6:
         case 8:
                 ValorDecimal = 7;   // revisar
                 break;
         case 5:
         case 7:
         case 9:
                 ValorDecimal = 8;
                 break;
         default: 
                 break;
     }

WARC y BAND, son independientes entre si, tanto puede estar una activa, la otra, las dos juntas, o ninguna. Lo que SIEMPRE, WARC maneja sus salidas y BAND las propias, NUNCA deberian intercambiarse entre si.

Gracias por tu tiempo.

A ver.. tu pusiste una tabla hasta 1010 si mal recuerdo. Bloquea el resto.
no hace falta ampliar la matriz. Un poco de analisis y un if en la función LeerBCDDecimal(){
hubiera controlado todo lo que supere 1010
recordemos tu tabla

tomas en cuenta los casos que no dijiste que ocurrirían por eso cuando se pone una tabla hay que pensar en todo.

usa esto que es mas correcto que lo que has hecho. Aunque soluciones hay muchas

if (WARC && BAND) {
     switch (ValorDecimal) {
         case 4:
         case 6:
         case 8:
                 ValorDecimal = 7;   // revisar
                 break;
         case 5:
         case 7:
         case 9:
                 ValorDecimal = 8;
                 break;
         case 11:
         case 12:
         case 13: 
         case 14:
         case 15: ValorDecimal = 0; // esta simple instrucción resuelve todo
                  break;
         default: 
                 break;
     }

Bueno Surbyte, muchas gracias nuevamente.

Como tu dices, el error fue mio al no contemplar los casos "no deseados" en la tabla de verdad. Hice una pequeña modificacion el codigo que me propusiste, y "saque" los casos no deseados del "IF", para que no dependa de este, me diras tu si lo que hice es correcto.

if (WARC && BAND) {
     switch (ValorDecimal) {
         case 4:
         case 6:
         case 8:
                 ValorDecimal = 7;   // revisar
                 break;
         case 5:
         case 7:
         case 9:
                 ValorDecimal = 8;
                 break;
         default: 
                 break;
         
     }
   }
     switch (ValorDecimal) {
         case 11:
         case 12:
         case 13:
         case 14:
         case 15:
                 ValorDecimal = 0;
                 break;
         default: 
                 break;
     }

   return ValorDecimal;
}
     }

Trabajare ahora, en independizar WARC de BAND. Les comento.

Gracias.
[/quote]

Aclaro que ambas soluciones funcionan pero: mi solución es mucho mas elegante. Todo resuelto en un paso no en dos como vos proponés.
No entiendo porque desdoblaste lo que te propuse?

surbyte:
Aclaro que ambas soluciones funcionan pero: mi solución es mucho mas elegante. Todo resuelto en un paso no en dos como vos proponés.
No entiendo porque desdoblaste lo que te propuse?

Hola, probe tu solución claro que si, y aunque no lo creas, el resultado era el mismo.

Luego me di cuenta que quedaba atado al If + &&, por eso lo puse por fuera de este.

Gracias.

ahhh ahora te comprendo y tienes razón.
Entonces bloqueemos antes para ser mas correctos
Bloquea cuando formamos ValorBCD

ValorDecimal = (datD << 3) + (datC <<2) + (datB << 1) + datA;[color=#222222][/color]
if (ValorDecimal > 10) ValorDecimal = 0;

y elimina lo que yo sugerí antes dentro del switch y tu switch extra.
Ahora si todo valor por encima de 10 no existe, asi que devuelve 0.