¿Fallo de uC en demultiplexación?

Hola a toda la comunidad.

Estoy tratando de ampliar la cantidad de salidas posibles de un Arduino, para lo cual estoy usando latches de 8 bits (74HC373) para crear un bus de datos binarios. Por ahora solo estoy probando con dos, pero la idea sería poder ampliarlo más aún (si funciona lo que estoy intentando con 9 pines del ATMega podría tener 40 salidas :eek: ).

La idea sería la siguiente: en ocho pines del arduino estoy cargando una serie de estados altos o bajos, los cuales estan conectados en paralelo a las entradas de las latches. Las latches solo registraran y guardaran el dateo del bus al aplicar una subida y bajada al pin del cerrojo. Como son dos integrados debería accionar el cerrojo del primero para que carguen los datos del bus y guardarlos, limpiar el bus, escribir sus nuevos valores y accionar el cerrojo del segundo integrado. De este modo quedan 16 estados lógicos fijados hasta que se vuelva a accionar el cerrojo de alguno de ellos.

Para realizar la función de seleccionar que cerrojo se acciona he utilizado un CD4017 (contador decimal) que es accionado por un novenos pin del Arduino. Para evitar errores tome para los cerrojos solo las salidas impares, dejando el cero y las pares sin ir a ningún lado, solo para aprovechar os "silencios" entre los pares.

Todo muy bonito, pero... por algún motivo no me funciona :cry: . Imaginé que quizás el 4017 era muy "lento", así que intenté añadir un milisegundo de delay (deberíaser más que suficiente). Aún así no hubo mejoras. El código que estoy usando es el siguiente:

PHP:
int bus0 = 2;
int bus1 = 3;
int bus2 = 4;
int bus3 = 5;
int bus4 = 6;
int bus5 = 7;
int bus6 = 8;
int bus7 = 9;
int cd4017 = 10;
int led = 13;

void setup()
{
  pinMode (led, OUTPUT);
  digitalWrite(led, HIGH);
  pinMode (bus0, OUTPUT);
  pinMode (bus1, OUTPUT);
  pinMode (bus2, OUTPUT);
  pinMode (bus3, OUTPUT);
  pinMode (bus4, OUTPUT);
  pinMode (bus5, OUTPUT);
  pinMode (bus6, OUTPUT);
  pinMode (bus7, OUTPUT);
  pinMode (cd4017, OUTPUT);
  digitalWrite(bus0, LOW);
  digitalWrite(bus1, LOW);
  digitalWrite(bus2, LOW);
  digitalWrite(bus3, LOW);
  digitalWrite(bus4, LOW);
  digitalWrite(bus5, LOW);
  digitalWrite(bus6, LOW);
  digitalWrite(bus7, LOW);
  digitalWrite(cd4017, LOW);
  digitalWrite(led, LOW);
}

void loop()
{
  loadBus(1, 0, 1, 1, 0, 0, 1, 1); latchAndClearBus; loadBus(0, 1, 1, 0, 1, 1, 1, 0); latchAndClearBus;
}

void latchAndClearBus() //limpiar y prepararse para el proximo latcheo
{
  digitalWrite(cd4017, HIGH); digitalWrite(cd4017, LOW); digitalWrite(cd4017, HIGH); digitalWrite(cd4017, LOW);
  delay(1);
  digitalWrite(bus0, LOW); digitalWrite(bus1, LOW); digitalWrite(bus2, LOW); digitalWrite(bus3, LOW);
  digitalWrite(bus4, LOW); digitalWrite(bus5, LOW); digitalWrite(bus6, LOW); digitalWrite(bus7, LOW);
}

void loadBus (int a, int b, int c, int d, int e, int f, int g, int h)
{
  digitalWrite(bus0, h);
  digitalWrite(bus1, g);
  digitalWrite(bus2, f);
  digitalWrite(bus3, e);
  digitalWrite(bus4, d);
  digitalWrite(bus5, c);
  digitalWrite(bus6, b);
  digitalWrite(bus7, a);
  delay(1);
}

Si alguien tiene alguna sugerencia soy todo oídos. Muchas gracias desde ya! :D ...
 
yo usaria el CD4021

hay 2 formas de usarlo

emulacion SPI ó usando SPI por hardware.

la idea es leer el data y tener un pin de clock, se pueden poner en cascada y obtener de entrada 16 bits.
la idea es solo usar 3 pines ,LATCH, DATA Y CLOCK.

tienes la ventaja que en arduino tiene todo hecho asi que hacer funcionar esto es mas rapido que ser un precoz.

solo hay que leer en modo SPI asi de simple.
 
A ver chicos, contesto por partes:

1° (lo más importante): Si, Sr. Duberlin. Estuve mal en pasarlo por alto lo del esquema:
Demultiplexor.png

Los IC de 20 pines son los 74HC373 (no están formalmente en la librería del livewire). Cambié el pinout del 373 para hacer más legible el esquema. El pinout real está adjuntado. El pin 1 es el Enable Output (constantemente habilitadas). El pin 11 es la latch que mantendrá los datos guardados mientras este en estado bajo.

La idea original es: Se cargan datos al bus, se pasa al 4017 de 0 a 1 para que el 1 levante la latch A para que incorpore los datos, contamos de 1 a 2, con lo que dejamos la latch cerrada (nuestro 2 no va a ningún lado), cambiamos los datos del bus, contamos de 2 a 3 para abrir la latch B, contamos de 3 a 4 y por lo tanto caemos en el Reset del 4017 (volviendo a cero, listo para iniciar un nuevo ciclo)

La pregunta sería ¿en qué falló mi razonamiento? :confused: Eso es lo que más me interesa. :unsure:

Scooter y Trilo: les juro que me metí ean una odisea de buscar integrados que hubiese en las tres casas de componentes locales. Por ahora quería probar esta opción como algo experimental. Considero que el sistema podría ser útil si lo logro hacer funcionar como corresponde. Tendré en cuenta sus sugerencias y trataré de ver por el 4021. Scooter ¿qué shift register me recomiendas, brother ;)?

EDITO: Perdón, perdón, perdón... me comí las resistencias de las latches para que no se abran por estática y otras yerbas.
Demultiplexor2.png
 

Adjuntos

  • Pinout.png
    Pinout.png
    10.8 KB · Visitas: 9
Última edición:
el CD4021 es un integrado comun

convierte 8 bits en paralelo a 8 bits serie.

son comunes de ver en los controles del antiguo NES

220px-NES-controller.jpg


los puedes poner en cascada es decir no solo sera de 8 bits sino tambien 16 etc.

¿como usarlo?

es muy simple supongo que ya hay una libreria arduino para eso.

la idea principar es leer el CD4021 es un registro de corrimento

mas o menos funciona asi cuando a codigo me refiero:

unsigned char CD4021()
{
unsigned char lee=0;
unsigned char i=0,dat;

//for(i=8; i!=0 ; i--)

for(i=0; i!=8 ; i++)
{
dat=DATA_IN;

CLOCK=0;
CLOCK=1;
dat<<=i;
lee=lee|dat;
//lee=lee|(dat<<(i-1));
}
return lee;
}

como se me en el codigo envio un clock por cada dato leido, el dato lo roto las veces que sean necesarias, en este caso 8 veces y hago una MASCARA donde apilo el dato rotado en el byte que voy a interpretar.

aca un ejemplo de como usar la funcion de leer el 4021.

LATCH2=0; //habilito el chip
DATO2=CD4021();
LATCH2=1; // deshabilito el chip


tan facil que da risa.
 
Bueno, probé tu sugerencia, Trilo: desarme todo y armé de vuelta. Para reducir posibilidades de confusiones esta vez mandé el bus de datos por cable plano. (y)

DSCN6622.JPG

De todos modos no hubo mejoras. :unsure:
El problema persiste exactamente igual.

¿Alguien puede darle una ojeada al soft y al hard que dejé publicados y arriesgar una hipótesis de que está fallando? Así aunque sea voy probando por ensayo y error. El método científico. ;)
 
fijate que me equivoque desde el principio es que cuando conteste lo hise desvelado no habia dormido nada.

confundi tu pregunta pense que querias muchas entradas, pero quieres 40 salidas

es bien facil, es exactamente alrevez como te lo habia sugerido con los 74hc595.

es igualito a lo que habia comentado, pero en lugar de leer un byte escribiremos un byte.

¿cuantas salidas?

las que se te antojen.

la idea es minimisar lo mas que se pueda un bus de datos en este caso lo usaras 3 pines.

LATCH , DATA , CLOCK. que es identico al protocolo SPI.

para tener una salida de 40 pines debes usar 5 74HC595. que si te caen gordos lo 75HC595 puedes usar los 74HC164 solo que estos no tienen el pin LATCH.

un ejemplo de lo que te digo:

char _74HC595(char dato)
{
char i,dat;

TRIS_CLOCK=0; //CLOCK ES SALIDA
TRIS_DATA=0; //DATA ES SALIDA
TRIS_LATCH=0; //LATCH ES SALIDA





for(i=0; i!=8 ; i++)
{


dat=dato<<i;

dat=dat&0b10000000;

if(dat==0)
{
DATA=0;
}
else
{
DATA=1;
}

CLOCK=0;
CLOCK=1;


}


return dato;
dato=0;
dat=0;
}


como vez es parecido a lo que habia mencionado en mi confucion.

ahora como usar la funcion:

puerto=0xAA;

LATCH=0;

_74HC595(puerto);

LATCH=1;


en el ejemplo escribimos 1 byte

¿pero que pasa si queremos 2 bytes?

puerto=0xAA;
puerto2=0xF0;

LATCH=0;

_74HC595(puerto);
_74HC595(puerto2);

LATCH=1;

en el ejemplo escribimos 2 bytes es decir el LATCH juega un papel importante que es el desplazamiento del byte al otro registro, si yo hubiera limpiado el LATCH no se hubiera desplazado.

ahora un ejemplo con 4 bytes !

puerto=0xAA;
puerto2=0xF0;
puerto3=0xE1;
puerto4=0x34;


LATCH=0;

_74HC595(puerto);
_74HC595(puerto2);
_74HC595(puerto3);
_74HC595(puerto4);

LATCH=1;


asi de facil
 
Última edición:
Justamente estoy usando los 373 porque acá no hay 595.

A más de que me sugieran posibles opciones, lo cual les agradezco muchísimo, ¿alguien podría decirme porque lo que estoy probando no funciona? ¿dónde reside el error?

De todos modos tu sugerencia es muy buena. Desgraciadamente soy medio muy principiante y aún no he aprendido a usar los puertos. Ratmayor me explico algo de eso de 0xFF o 0xFE, etc. pero no la lógica de ese lenguaje todavía.

¿Qué significa el primer cero?¿Por qué después hay una x?¿Cómo los dos últimos dígitos (que encima veo que son alfanuméricos) determinan el sector de la memoria?¿Hay una tabla de esto? :confused:

Estoy usando un Arduino, se me nota lo hobbier :LOL:
 
Última edición:
Hola, viendo tu esquema, tiene un detalle. Resulta que el CD4017, no está sincronizado con el destino de datos. Pues cuando dichos datos deben ir al 1er. LATCH por ejem. al aparecer luego el pulso en pin 10, la salida de dicho CD4017, debe accionar esa salida correspondiente, pero nunca sabrás cual salida está activa.
Conclusión, Arduino debe gestionar el RESET de dicho CD4017. Así, cuando debas realizar la demultiplexación, lo 1ro. será resetear el 4017, y luego comenzar la transmisión de datos a los diferentes destinos. Terminado el proceso de demultiplex. reseteas nuevamente el CD4017, para comenzar un nuevo ciclo.
 
Última edición:
y usando el puerto 82C55 ?

es un puerto de 3 bytes

yo quitaria el 4017 y usaria otros 2 pines del micro es decir:


byte1=0x45;
byte2=0xFE;

para escribir haria yo lo siguiente:

//desactivo latch de los 2 micros

puertoB=byte1;
//activo el latch del primer micro


puertoB=byte2;
activo el latch del segundo micro


con ese algoritmo deberia funcionar con el hardware que tienes
 
A ver, a ver, a ver...

Vamos primero con la solución de Duberlin (muy ingenioso), porque la de Trilo... :confused:

No entiendo el lenguaje de programación que estás usando (o lo entiendo a medias) ¿Qué cuernos es el puerto 82C55?
 
el puerto 82c55 es un expansor de puerto de 8 bits hace exactamente lo que quieres hacer pero en un solo chip.

chap11_lect08_IO17.gif


no es dificil de usar.

en el 4017 por lo que veo haces un conteo de latch pero no das reset.

el algoritmo para hacer lo que quieres es el siguiente:

1.- limpiar latches "aplicar reset a todos los latches"
2.- escribir en el puerto
3.- pulso clock para retener el primer latch
4.- escribir nuevamente en el puerto
5.- pulso clock para retener el segundo latch

pero hay un detalle que creo que no has observado:

el 4017 es un contado en decimal y no binario

lo que activa el primer latch y cuano aplicas un clock se desactiva el primer latch y el segundo se activa
borrando lo que tenias en el primer latch.

asi de simple.

no me doy a entender pues es que hay que estudiar mas para seguir el paso
 
Bueno, controlar el Reset del 4017 tampoco funcionó.

Y Trilo tiene razón, evidentemente aún me falta pasta para esto.

Veré de encontrar alguna solución y publicaré mis resultados.
 
Por que va a gastar demasiados pines I/O???
Mejor usa un 74138 y manejas 8 latches con tres pines y listo.
Ahhh... los 373 son disparados por flancos (no recuerdo cual) y no por nivel, asi que no sirve eso de poner LE en 0 sino que hay que mandarle un pulso con la polaridad adecuada.
 
Última edición:
El 8255 no es que esté obsoleto, está lo siguiente. Hace tres lustros ya costaba de encontrar, aunque puede que quede un contenedor por algún sitio


Puedes cambiar los 373 por 374. Los 373 son "transparentes" por nivel mientras que los 374 son por flanco. Yo usaba 374 cuando era joven.
También puedes buscar los 574 que son exactamente lo mismo pero con un pinout ordenado en lugar del desastre que llevan los 373 y 374
 
Última edición:
fijate que en mi ciudad aun venden los 82C55, me hise de varios cuando no tenia idea de usar resgistros de corrimiento.

y lo hise por que estaba armando una computadora con un Z80 , hubiera sido mas practico usar un pic o un avr pero no sabia ni papa.

los 82C55 hacen lo que el colega quiere hacer pero de manera mas comoda y en un solo chip, hace poco un año o año y medio compre otros 2 82C55 solo como coleccion.


yo soy de la idea de los 74HC595 es mas facil digo en arduino debe haber una libreria perfecta y funcional para estos integrados tan comunes y practicos.

nadamas es conectar y mandar el byte si la libreria esta hecha.
 
Atrás
Arriba