¿Fallo de uC en demultiplexación?

Pues ya te digo que por aquí eran difíciles de encontrar hace más de quince años. No era exageración, era dato real:
Acabé diseñando un circuito con una pila de 74374, 74244 y un 74138 para ampliar entradas y salidas en lugar de usar dos 8255, eso fue allá por el año 95 o 96 ya que el producto salió al mercado en el 97 si no me equivoco.

Aunque sean difíciles de encontrar yo buscaría los registros de desplazamiento. También hay unos circuitos I²C que dan mucha corriente de salida gastando muy pocos pines.
 
ahi serian tambien 3 patitas SDA, SCL y enable.

en SPI tememos Latch, data , clock. que el enable seria el latch.

me gusta la idea del expansor de bus, pero con un 74hc595 se puede expandir el bus de salida nada mas.

el 82C55 si es bien obsoletote no se por que lo mencione pero si es valido en este algoritmo que el colega presento.

los 74HC595 hoy en dia estan resurgiendo en los letreros LED bueno aca en la ciudad de mexico se volvio obligatorio el letrero led en los taxis.

lo que hiso que el 74HC595 se volviera popular pues casi todos los letreros led de los taxis traen un pic 16f886, 74HC595 y uno que otro transistorsillo.


DATO:

efectivamente muchos 74HC595 en cascada forman un puertotote paralelo
 
Había visto la posibilidad de los 595 (de hecho es lo primero que te muestran en la página de Arduino), pero donde yo vivo es difícil conseguir algunos componentes, y como buen argentino suelo terminar atando las cosas con alambre porque no tienen el integrado que necesito o el transistor o el switch :eek:

Voy a hacer pruebas por bloques más compactos. A medida que vayan funcionando voy a ir incorporando otras partes hasta que esta cosa funcione. Conmigo no va a poder :devilish:

He hecho un par de intentos de multi y demulti plexación, por lo que tengo ya los 74HC373, los CD4021 que sugirió Trilo (los compré y los probaré si todo me falla, gracias Trilo por presentarme un componente nuevo :D ) y los 74HC165.

Algo útil tengo que sacar de todo esto. ;)
 
pues el 74HC165 nunca lo he usado no sabia que existia.

y los CD4021 fue error mio de no leer bien pero bueno asi puedes tener un monton de entradas con los CD4021

para las salidas puedes usar los 74hc164 o los 74hc595

¿por que no intentas usar proteus?

asi simulas software y hardware, es decir dibujas el esquematico, y al micro le cargas el .hex y lo deberias simular para ver si funciona o no.

yo raravez lo uso pero si ayuda bastante
 
Solo como alternativa a lo que ya se mencionó.

Tal vez sea más práctico usar un expansor de puerto I2C, los Atmega más chicos como el 8 tienen esa interfaz (se llama two wire serial).

Tenés varios modelos de expansores según el fabricante:

- MCP23017 (microchip): salida 16 bits.
- TCA9534 (TI): salida 8 bits.
- Nxp tiene toda una linea smd.

Hay que ver si podés conseguirlos, pero es otra opción un poco más sencilla de llevar a cabo.
 
No, en I²C son dos para todos.
En spi son dos si es unidireccional o tres si es fullduplex más un CE por chip.
A cambio el spi es más rápido
 
No, en I²C son dos para todos.

No entiendo a que te referís. Con un solo i2c, podés agregar los expansores de puertos que quieras, en el caso de microchip, solo hace falta fijar una determinada dirección.

A cambio el spi es más rápido

En realidad tampoco estamos seguros a que velocidad quiere trabajar, pero SPI también puede ser una alternativa a tener en cuenta, los atmega también traen esa interfaz.
 
hola
Ha sido un lío, antes alguien comentó que I²C eran tres lineas
Aca te aporto un esquema ., tambien las librerias que estoy usando para practicar y que pienso usar(hasta que resuelva mis errores)​
I²C y SPI (tambien) ., esta implementado en casi todos los micros de la linea atmel​
basicI2C.jpg
LIBRERIA I²C MASTER
PHP:
// i2cmaster.c
#include <util/twi.h>
#define SET(x,y) (x|=(1<<y))
#define CLR(x,y) (x&=(~(1<<y)))
#define CHK(x,y) (x&(1<<y)) 
#define TOG(x,y) (x^=(1<<y))
 
//global variables
#define BUFLEN_RECV 3
uint8_t r_index =0;
uint8_t recv[BUFLEN_RECV]; //buffer to store received bytes
 
#define BUFLEN_TRAN 12
uint8_t t_index=0;
uint8_t tran[BUFLEN_TRAN]= {1,2,3,4,5,6,7,8,9,10,11,12};
//variable to indicate if something went horribly wrong
uint8_t reset=0 
 
//prototypes
void handleI2C_master();
 
 
//---------------MAIN---------------------------------------------
int main(){
  //set bitrate for I2C
 TWBR = 10  
 //enable I2C hardware
 TWCR = (1<<TWEN)|(1<<TWEA)|(1<<TWSTA);
 
 while(1){
  handleI2C_master();
 }
}
//-----------END MAIN---------------------------------------------
 
//setup the I2C hardware to ACK the next transmission
//and indicate that we've handled the last one.
#define TWACK (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA))
//setup the I2C hardware to NACK the next transmission
#define TWNACK (TWCR=(1<<TWINT)|(1<<TWEN))
//reset the I2C hardware (used when the bus is in a illegal state)
#define TWRESET (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO)|(1<<TWEA))
//Send a start signal on the I2C bus
#define TWSTART (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA))
//slave address and SLA signals
#define I2C_SLAVE_ADDRESS 0x01
#define SLA_W ((I2C_SLAVE_ADDRESS<<1) | TW_WRITE)
#define SLA_R ((I2C_SLAVE_ADDRESS<<1) | TW_READ)
 
void handleI2C_master(){
  //keep track of the modus (receiver or transmitter)
	static uint8_t mode; 
 
 if(CHK(TWCR,TWINT)){
    switch(TW_STATUS){
   //start or rep start send, determine mode and send SLA R or W
    case 0x10:
    case 0x08: 
   //reset buffer indices
   t_index =0;
   r_index =0;
   //send SLA W or R depending on what mode we want.
   if(mode == TW_WRITE) TWDR = SLA_W;
   else TWDR = SLA_R;
   TWACK;
   break;
//--------------- Master transmitter mode-------------------------
  case 0x18: // SLA_W acked
   //load first data
   TWDR = tran[0];
   t_index=1;
   TWACK;
   break;
 
    //SLA_W not acked for some reason (disconnected?), keep trying
    case 0x20: 
    TWCR =0;
    TWSTART;
    break;
  case 0x28: //data acked by addressed receiver
   //load next byte if we're not at the end of the buffer
   if(t_index < BUFLEN_TRAN){
    TWDR =  tran[t_index];
    t_index++;
    TWACK;
    break;
   }
   //otherwise, switch mode and send a start signal
   else {
    mode = TW_READ;
    TWSTART;
    break;
   }
  case 0x38: //arbitration lost, do not want
  //data nacked, could be faulty buffer, could be dc, start over
  case 0x30: 
      TWCR = 0;
      TWSTART;
      break;
//-------------------------Master receiver mode-------------------
 //SLA_R acked, nothing to do for master, just wait for data
  case 0x40:
   TWACK;
   break;
  //SLA_R not acked, something went wrong, start over
	case 0x48:
      TWSTART;
      break;
  //non-last data acked (the last data byte has to be nacked)
	case 0x50:
   //store it
   recv[r_index] = TWDR;
   r_index++;
   //if the next byte is not the last, ack the next received byte
   if(r_index < BUFLEN_RECV){
    TWACK;
   }
   //otherwise NACK the next byte
   else {
    TWNACK;
    r_index =BUFLEN_RECV;
   }
   break;
  case 0x58: //last data nacked, as it should be
   //switch to other mode, and send start signal
   mode = TW_WRITE;
   TWSTART;
   break;
 
//--------------------- bus error---------------------------------
    case 0x00:
      TWRESET;
      ;
      TWSTART;
      break;
    }
  }
}
LIBRERIA I²C SLAVE
PHP:
#i2cslave.c
#include <util/twi.h>
#define SET(x,y) (x|=(1<<y))
#define CLR(x,y) (x&=(~(1<<y)))
#define CHK(x,y) (x&(1<<y)) 
#define TOG(x,y) (x^=(1<<y))
 
//global variables
#define BUFLEN_RECV 12
uint8_t r_index =0;
uint8_t recv[BUFLEN_RECV]; //buffer to store received bytes
 
#define BUFLEN_TRAN 3
uint8_t t_index=0;
//test bytes to transmit
uint8_t tran[BUFLEN_TRAN] = {0x12, 0x34, 0x56}; 
 
//variable to indicate if something went horribly wrong
 uint8_t reset=0 
 
 //prototypes
void handleI2C();
 
//---------------MAIN---------------------------------------------
int main(){
  //load slave address
 TWAR = (0x01<<1); //we're using address 0x01 
 //enable I2C hardware
  TWCR = (1<<TWEN)|(1<<TWEA);
 
 while(1){
  handleI2C();
 }
}
//-----------END MAIN---------------------------------------------
 
//setup the I2C hardware to ACK the next transmission
//and indicate that we've handled the last one.
#define TWACK (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA))
//setup the I2C hardware to NACK the next transmission
#define TWNACK (TWCR=(1<<TWINT)|(1<<TWEN))
//reset the I2C hardware (used when the bus is in a illegal state)
#define TWRESET (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO)|(1<<TWEA))
void handleI2C(){
  //check if we need to do any software actions
  if(CHK(TWCR,TWINT)){
    switch(TW_STATUS){
//--------------Slave receiver------------------------------------
    //SLA_W received and acked, prepare for data receiving
		case 0x60:  
      TWACK;
      r_index =0;
      break;
    case 0x80:  //a byte was received, store it and 
                //setup the buffer to recieve another
      recv[r_index] = TWDR;
      r_index++;
      //don't ack next data if buffer is full
      if(r_index >= BUFLEN_RECV){
        TWNACK;
      }else {
    TWACK;
   }
   break;
    case 0x68://adressed as slave while in master mode.
              //should never happen, better reset;
      reset=1;
    case 0xA0: //Stop or rep start, reset state machine
      TWACK;
      break;
//-------------- error recovery ----------------------------------
    case 0x88: //data received  but not acked
      //should not happen if the master is behaving as expected
      //switch to not adressed mode
      TWACK;
      break;
//---------------Slave Transmitter--------------------------------
    case 0xA8:  //SLA R received, prep for transmission
		            //and load first data
      t_index=1;
      TWDR = tran[0];
      TWACK;
      break;
    case 0xB8:  //data transmitted and acked by master, load next
      TWDR = tran[t_index];
      t_index++;
      //designate last byte if we're at the end of the buffer
      if(t_index >= BUFLEN_ACC_DATA) TWNACK;
      else TWACK;
      break;
    case 0xC8: //last byte send and acked by master
    //last bytes should not be acked, ignore till start/stop
      //reset=1;
    case 0xC0: //last byte send and nacked by master 
		//(as should be)
      TWACK;
      break;
//--------------------- bus error---------------------------------
    //illegal start or stop received, reset the I2C hardware
		case 0x00: 
      TWRESET;
      break;
    }
  }
}
 
Eso mismo que se ve en el esquema: Dos líneas.
La alimentación se da por supuesto.

Spi son mínimo 3, lo normal 4 para 1 dispositivo. Luego has de agregar una más por cada dispositivo. Y la alimentación, claro.
 
el colega pregunto sobre un hardware de dudosa funcionalidad.

por que los componentes eran dificiles de encontrar, no dudo que funcione , necesita arreglos para poder funcionar.

se le sugirio una alternativa funcional, barata y facil de encontrar.

lo que proponen es mejor pero! , creo que el colega tiene dudas con programacion, yo opino que hay que resolver dudas antes de lanzar informacion dificil de digerir.
 
Bueno, como dije me dediqué a hacer pruebas pequeñas e ir armando por partes el dmux Frankenstein. Con respecto a la velocidad de trabajo no se preocupen, no requiero una aplicación de picosegundos.
Estas fueron las pruebas que realicé hasta el momento:

1. Partimos desde cero:
DSCN6626.JPG

2. Disponemos un 74HC373 cerquita del Arduino para cuando lo vayamos a probar con éste:
DSCN6627.JPG

3. Nuestro primer ensayo será ver si el 373 funciona y ver su comportamiento ante los cambios de datos en un bus simulado en los distintos estadios del pin Latch Enable. Para ello dispondremos de un 555 en cofiguración Flip Flop como se ve en el siguiente esquema, con la correción de que no habilitaremos un transistor sino un LED azul (para que ustedes lo vean):
FlipFlop.png

Usaremos este 555 para dar estado alto o bajo al Latch Enable, tomando dicha señal desde el pin 3 del mismo. En el estado bajo las latch se mantienen cerradas: no importa lo que haya en el bus de datos, las salidas no cambian. Cuando se encuentra en estado alto las latch se vuelven transparentes: lo que haya en el bus sale del 373. Disponemos este sistema en un lateral:
DSCN6633.JPG

4. Alimentamos nuestro 373:
DSCN6637.JPG

5. Como estamos con el método científico demos revisar solo una variable y mantener las otras constantes, por lo que dejaremos las salidas constantemente habilitadas conectando un resistor de 10KΩ desde el pin 1 del 373 (Output Enable, inversor) a GND:
DSCN6639.JPG

6. A fin de que las latch no se disparen por estática u otras yerbas les pondremos también un resistor de 10KΩ a GND:
DSCN6640.JPG

7. Disponemos cuatro resistores de 1KΩ junto al 373 (haremos nuestro ensayo solo con cuatro entradas, un bus de 4 bits):
DSCN6642.JPG

8. Conectamos nuestras resistencias al riel de alimentación para simular el bus de datos (cables naranjas):
DSCN6643.JPG

9. Como bien mencionó alguién en el hilo, el pinout de este integrado no es lo más hermoso de este mundo, pero se deja conectar las resistencias a las entradas en los pines 3, 4, 7 y 8 (en orden de D0 a D3, cables amarillos):
DSCN6644.JPG

10. Junto a las entradas están las salidas (en este sentido el pinout zafa un poco más). Conectémoslas a un costado siguiendo el orden de lectura (Q0 está a la izquierda, Q3 a la derecha, cables negros):
DSCN6648.JPG

11. Dispongamos cuatro resistores de 470Ω para limitar corriente a los LED que utilizaremos como actuadores para enterarnos que pasa en nuestro integrado:
DSCN6649.JPG

12. En cuanto conectamos los LED estos ya se encuentran prendidos. Esto lo atribuyo a estar armando el circuito mientras está alimentado ( :facepalm: No, pibe, no... La alimentación va al final):
DSCN6653.JPG

13. Incorporamos entonces un resistor de 1KΩ al pin Latch Enable. Al colocarla el integrado descarga la estática sobre mí a través del resitor y nuestros LED se apagan:
DSCN6654.JPG

14. Conectamos la otra pata del resistor al pin 3 del 555 que habíamos armado al principio:
DSCN6655.JPG

;) Hasta acá por ahora. Sigue en otro.
 
Última edición:
Aprovecho el interin para contestarle, Mr. Duberlin: si es por mí con hacer funcionar dos latches estoy hecho... pero ya que estoy en el ruedo me interesa armar algo más ambicioso pensando que quizás le pueda servir a alguien en un futuro.

Continuo pues:
15. Armado ya nuestro sistema de ensayos comenzamos con las primeras pruebas. Para ello extendemos la alimentación a los rieles de abajo:
DSCN6657.JPG

16. Armamos alguna secuencia de bits para probar. En este caso hemos elegido 1, 0, 0, 1:
DSCN6662.JPG

17. La latch cumple su función en el sentido de que no ha habido cambios al cambiar los bits del bus de datos. Ahora llevaremos el pin Latch Enable a estado alto:
DSCN6663.JPG
Solo con llevar al pin a su estado alto los datos dados en el bus aparecen a la salida. Modificar las en este momento tiene como resultado la inmediata modificación en las salidas.

18. Al devolver al estado bajo la latch la misma se cierra y los datos a las salidas permanecen inalterados, aún cuando cambien en el bus:
DSCN6665.JPG

19. Hagamos un segundo ensayo con otros datos en el bus. En este caso escribiremos la secuencia 0, 0, 1, 1:
DSCN6667.JPG

20. Podemos apreciar que pese al cambio de bits en el bus de datos las salidas han permanecido inalteradas:
DSCN6669.JPG

21. Vamos a volver a levantar el estado del pin Latch Enable. Nuevamente la modificación de las salidas es instantánea al nivel alto en dicho pin:
DSCN6670.JPG

22. Devolvemos al estado bajo, sin observar cambios en las salidas:
DSCN6673.JPG

Hasta aquí el primer ensayo. Conclusiones: las latch funcionan. Están bien conectadas, por lo que se entiende el pinout. Las resistencias de 10kΩ cumplen ambas con su cometido. Estamos un pasito más adelante. ;) Sigue en otro.
 
Luego de nuestro primer ensayo vamos a retirar el Flip Flop del 555, los cables naranjas que simulaban el bus de datos y vamos a la posta del asunto.
Segundo ensayo ¿Cómo funciona esta cosa con el Arduino? ¿Se mezclan entre ellos los buses y las latch? ¿Todas las empanadas de carne chorrean aceite como auto con cárter pinchado? :eek:

1. Ahora conectamos el trasto (que sabemos que funka ;) ) al Arduino. Primero el Latch Enable con su resistor de 1KΩ al pin 6 del Arduino (cable negro):
DSCN6676.JPG

2. Conectamos ahora los resistores de 1KΩ que van a las entradas del 373 con los pines 2, 3, 4 y 5 del Arduino correspondiendo a D0 (rojo), D1 (azul), D2 (amarillo) y D3 (blanco) respectivamente:
DSCN6678.JPG

3. Cargamos el siguiente programa en el Arduino, el cuál básicamente carga el bus de datos con 4 bits, acciona la Latch y espera (pa´que podamos sacar la foto ;) ):
PHP:
const int dPin[] = {2, 3, 4, 5};
const int latchPin = 6;

void setup()
{
  for (int i = 0; i < 3; i++)
  {
    pinMode (dPin[i], OUTPUT);
  }
  pinMode (latchPin, OUTPUT);
  for (int i = 0; i < 3; i++)
  {
    digitalWrite (dPin[i], LOW);
  }
  digitalWrite (latchPin, LOW);
}

void loop()
{
  bus(1, 0, 0, 1);
  latch();
  delay(5000);
  bus(0, 1, 1, 0);
  latch();
  delay(5000);
  bus(1, 1, 0, 1);
  latch();
  delay(5000);
}

void bus(int a, int b, int c, int d)
{
  digitalWrite (dPin[0], a);
  digitalWrite (dPin[1], b);
  digitalWrite (dPin[2], c);
  digitalWrite (dPin[3], d);
}

void latch ()
{
  digitalWrite (latchPin, HIGH);
  digitalWrite (latchPin, LOW);
}

Como verán estaremos escribiendo 3 conjuntos de datos: 1001, 0110 y 1101.

4. Luego de cargado el programa desconectamos de la computadora y compartimos la alimentación:
DSCN6683.JPG

5. Alimentamos todo y estos son nuestros resultados:
DSCN6684.JPG
DSCN6685.JPG
DSCN6686.JPG

En conclusiones: yo le doy 3 quintines :eek: El programa funciona, Duberlin tiene razón y el Arduino puede gestionar perfectamente las latch, por lo menos mientras le demos delay. Tranquilos, ya lo vamos a sacar ;). Continua en otro.
 
Ahora vamos a hacer que sirva para algo, porque hasta ahora estoy gastando 5 pines de un µC para prender 4 LED (n)

1. Así que vamos a incluir una segunda latch, replicando el circuito que ya tenemos. Conectaremos el pin Latch Enable de esta segunda latch al pin 7 del Arduino (cable amarillo):
DSCN6687.JPG

2. Nos colgaremos del bus de datos poniendo las entradas en paralelo con las del primer 373 (cables azules):
DSCN6688.JPG

3. Ahora cargamos el siguiente programa:
PHP:
const int dPin[] = {2, 3, 4, 5};
const int latchVerdePin = 6;
const int latchAmarilloPin = 7;

void setup()
{
  for (int i = 0; i < 3; i++)
  {
    pinMode (dPin[i], OUTPUT);
  }
  pinMode (latchVerdePin, OUTPUT);
  pinMode (latchAmarilloPin, OUTPUT);
  for (int i = 0; i < 3; i++)
  {
    digitalWrite (dPin[i], LOW);
  }
  digitalWrite (latchVerdePin, LOW);
  digitalWrite (latchAmarilloPin, LOW);
}

void loop()
{
  bus(1, 0, 0, 1);
  latchVerde();
  bus(0, 1, 0, 1);
  latchAmarillo();
  delay(5000);
  bus(0, 1, 1, 0);
  latchVerde();
  bus(0, 0, 1, 0);
  latchAmarillo();
  delay(5000);
  bus(1, 1, 0, 1);
  latchVerde();
  bus(0, 0, 0, 1);
  latchAmarillo();
  delay(5000);
}

void bus(int a, int b, int c, int d)
{
  digitalWrite (dPin[0], a);
  digitalWrite (dPin[1], b);
  digitalWrite (dPin[2], c);
  digitalWrite (dPin[3], d);
}

void latchVerde ()
{
  digitalWrite (latchVerdePin, HIGH);
  digitalWrite (latchVerdePin, LOW);
}
void latchAmarillo ()
{
  digitalWrite (latchAmarilloPin, HIGH);
  digitalWrite (latchAmarilloPin, LOW);
}
Un programa sencillo que pone datos en el bus, dispara la primera latch (LEDs verdes), cambia los datos del bus, dispara la segunda latch (LEDs amarillos) y espera.
Las tres secuencias de datos deberían resultar como sigue:
LEDs Amarillos LEDs verdes
0101 1001
0010 0110
0001 1101

4. Ejecutamos y vemos los resultados:
DSCN6690.JPG
DSCN6692.JPG
DSCN6694.JPG

Vemos que surge el primer error :eek:
En la segunda secuencia el cuarto bit es 0 para ambas latch, pero a nosotros nos aparece 1 en ambos casos.
LEDs Amarillos LEDs verdes
0101 1001
0010 0110
0001 1101

Fuera de eso todo lo demás funciona perfecto. :confused:

Comienzo a hacer el primer desbichaje a ver que puede estar pasando.
Continuará.

EDITO: Acabo de darme cuenta de que estoy arrastrando este error desde el ensayo con la primero latch y lo había pasado por alto :facepalm: . Hay que desbichar: primero hard, despues soft.



Solucionado.

El desbichaje comenzó por el hardware: :confused:¿Alguna pata de resistencia tocando otra? = NO, ¿cables mal conectado? = NO, ¿Cables defectuosos? Extraigo el cable blanco del cuarto bit desde el Arduino y lo mando a GND, el LED se apaga = NO. Listo, no es hardware.(y)

Software: :unsure: estoy usando arrays y la función for... seguro que me la he mandado en alguna de esos dos, sino todo lo demás no funcionaría. Es más, solo ocurre con el cuarto bit, por lo que lo más probable es que el error este en el for.

Efectivamente la condición era i<3 donde debía ser i<4. (n) Fé de erratas. Código corregido.

Ahora todo va sobre rieles:
DSCN6696.JPG
Nuestra secuencia de datos va impecable completa. Hasta ahora he trabajado con 4 bits, pero no cabe ninguna duda que con 8 debería funcionar igual.

Sigue entonces acoplarle el 4017. Eso más tarde. :eek:
 
Última edición:
Vamos con la parte del contador.

1. Comprimimos el circuito que ya tenemos para disponer de espacio para trabajar con el 4017:
DSCN6698.JPG

2. Disponemos el 4017 previendo dejar un espacio libre junto a él:
DSCN6701.JPG

3. Le damos alimentación:
DSCN6703.JPG

4. En primera medida no queremos que el Reset salte cuando se le dé la gana, por lo que lo tiramos a GND con un resistor de 10KΩ:
DSCN6705.JPG

5. Cuando el Clock Inhibit se encuentra en estado alto la entrada Clock es ignorada. Para evitarnos este problema también lo tiraremos a GND mediante un resistor de 10KΩ:
DSCN6706.JPG

6. Vamos a entrar al pin Clock mediante una resistencia de 1KΩ:
DSCN6707.JPG

7. Tomamos las primeras cinco salidas (empieza en 0 por lo que termina en 4) y las disponemos en orden en el espacio previsto:
DSCN6708.JPG

8. Incorporamos 5 resistores de 470Ω para limitar la corriente:
DSCN6709.JPG

9. Incluimos 5 LEDs como indicadores:
DSCN6711.JPG

10. Ya al dar alimentación comprobamos que la cuenta no empieza siempre en 0, e incluso pueden haber dos salidas activas juntas :eek: . Esto se verificó alimentando y quitándole la alimentación varias veces al circuito. Evidentemente deberemos manejar el Reset a través del Arduino, como sugirió Duberlin. Ya veremos más adelante cómo lo solucionamos. Por lo pronto incorporemos un resistor de 1KΩ a dicho pin. También nos percatamos de que la cuenta ocurre sola: el integrado capta estática. La solución es otro resistor de 10KΩ a GND para no dejar las cosas libradas al azar:
DSCN6714.JPG

11. Cargamos el siguiente programa:
PHP:
const int c4017Pin = 8;
const int r4017Pin = 9;

void setup()
{
  pinMode(c4017Pin, OUTPUT);
  pinMode(r4017Pin, OUTPUT);
  digitalWrite(c4017Pin, LOW);
  digitalWrite(r4017Pin, HIGH);
  digitalWrite(r4017Pin, LOW);
  delay(1000);
}

void loop()
{
  for (int i = 0; i < 4; i++)
  {
    digitalWrite(c4017Pin, HIGH);
    digitalWrite(c4017Pin, LOW);
    delay(1000);
  }
  digitalWrite(r4017Pin, HIGH);
  digitalWrite(r4017Pin, LOW);
  delay(1000);
}

12. Conectamos el Clock y el Reset a los pines 8 (cable azul) y 9 (cable verde) del Arduino respectivamente. Alimentamos y vemos que la cuenta no va cómo debiese :confused: . Empezamos a desbichar y sale a la luz que me comí la salida 3 :facepalm: había hecho 0, 1, 2, 4, 5 (n) . Reacomodamos las salidas:
DSCN6717.JPG

13. Ahora si todo va como debe. En la foto vemos activa la salida 2 (el tercer LED, rojo; el circuito de las latches esta separado, por lo que se ven encendidas):
DSCN6718.JPG

Ojo, fue necesario otro desbichaje en el medio, ya que yo veía que (aparentemente) que la cuenta arrancaba en 1 y no en 0. Luego la secuencia ocurría como debía :confused:

:unsure: Si me ocurre solo una vez y encima al iniciar el programa el problema lo tengo en el setup y obvio: me colgué de ponerle un primer delay antes de salir del setup para poder apreciar el reinicio del 4017.

Comprobado y bajo control el 4017. Vamo´ a juntar las piezas. (y)
 
Momento de la verdad ¿Puede el CD4017 gestionar las latch? Para ello procedemos de la siguiente forma:

1. Conectamos los pines Latch Enable de la primer y segunda latch a los pines 2 y 7 del 4017 respectivamente. Estos serían los pulsos 1 y 3 (recordar que empieza en 0). Conectamos además nuevamente el bus de datos, Clock y Reset del 4017, todo igual que antes:
DSCN6723.JPG

2. Hacemos una pequeña trampa e incluimos un resistor de 470Ω más un LED en serie a GND desde el pulso 5 del 4017, ya explicaré pa´que:
DSCN6725.JPG

3. Cargamos el siguiente código:
PHP:
const int dPin[] = {2, 3, 4, 5};
const int c4017 = 8;
const int r4017 = 9;

void setup()
{
  for (int i = 0; i < 4; i++)
  {
    pinMode(dPin[i], OUTPUT);
  }
  pinMode(c4017, OUTPUT);
  pinMode(r4017, OUTPUT);
  for (int i = 0; i < 4; i++)
  {
    digitalWrite(dPin[i], LOW);
  }
  digitalWrite(c4017, LOW);
  digitalWrite(r4017, HIGH);
  digitalWrite(r4017, LOW);
}

void loop()
{
  bus(1, 0, 0, 1);
  latch4017();
  bus(0, 1, 0, 0);
  latch4017();
  reset4017();
}

void bus(int a, int b, int c, int d)
{
  digitalWrite (dPin[0], a);
  digitalWrite (dPin[1], b);
  digitalWrite (dPin[2], c);
  digitalWrite (dPin[3], d);
}

void latch4017 ()
{
  digitalWrite(c4017, HIGH);
  digitalWrite(c4017, LOW);
  digitalWrite(c4017, HIGH);
  digitalWrite(c4017, LOW);
}

void reset4017 ()
{
  digitalWrite(r4017, HIGH);
  digitalWrite(r4017, LOW);
}

La idea es la siguiente: el programa comienza poniendo en estado bajo todos los pines, excepto el de Reset del 4017 que recibirá un pulso, así nos aseguramos de empezar en 0.
Arranca el programa: lo primero que hacemos es cargar el bus de datos con 1001 (LED´s verdes), disparamos dos pulsos al Clock del 4017, el primero para abrir la latch y que los datos entren (pulso 1), el segundo para dejar la latch en estado bajo (pulso 2). Esto no afecta a la segunda latch que está conectada al pulso 3.

Ahora cambiamos los datos del bus, volvemos a darle al Clock (pulso 3), la latch se abre y los datos entran, otro Clock (pulso 4) y la latch quedó cerrada con los datos guardados. Reseteamos el 4017 y volvemos a empezar.

¿Qué onda con el LED trampa? Como el proceso va a ocurrir a velocidad del µC los LED´s de las salidas del 4017 deberían verse tenues como PWM, mientras que este último LED debería permanecer apagado todo el tiempo, ya que su pulso esta justo despues del pulso en que es resetado el 4017.

:unsure:¿Funcionará esta locura?:unsure:

3. Pues buenas noticias:
DSCN6728.JPG

A esta altura del partido ya podría decir: Misión cumplida, doña (y)

Pero, no... :eek:

Dije que procuraría armar algo que pudiese ser útil para otros así que continuaré intentando mejorar este sistema de demultiplexación... pero mañana, ahora estoy cansado y ya son como las dos.

PD: gracias por el halago, Duberlin. De todos modos se nota que soy un principiante que va yendo de a pasos cortos, pero firmes. ;)
 
Última edición:
Mejor usa un registro de desplazamiento, gastas menos pines.

Desde que empezó este tema ya Scooter al principio y varios de ustedes me recomendaros los registros de desplazamiento y fue algo que me quedo picando. Efectivamente la idea de un demultiplexador BUENO es que justamente con la menor cantidad de pines del µC pueda controlar la mayor cantidad posible de salidas.

Así que me dediqué a revisar el catálogo de la casa de componentes local y a donde encontraba algo que pudiese mejorar este sistema revisaba datasheet. Vi como 40 :facepalm: , pero mis esfuerzos fueron fructíferos porque creo haber encontrado lo que estaba buscando. :D

1. Vamos a hacer algunos ensayos con otro integradito simpático, morocho y cuadradito que se llama HEF4094:
DSCN6730.JPG
Éste es un registro de desplazamiento SIPO (Serial In-Parallel Out), posee cuatro entradas: DATA, CLOCK, OUTPUT ENABLE y STROBE. Además hay 8 salidas paralelas (QP0 a QP7) y 2 salidas seriales que por el momento ignoraremos (QS1 y QS2, son para ponerlos en cascada).

2. Alimentemos al chiquitín:
DSCN6731.JPG

3. Colocamos a un lateral las salidas en orden desde QP0 (a la izquierda) hasta QP7 (derecha):
DSCN6733.JPG

4. Incorporamos 8 resistores de 470Ω:
DSCN6734.JPG

5. Agregamos 8 LED para saber que pasa adentro del aparato: :p
DSCN6735.JPG

6. Por el momento vamos a dejar las salidas constantemente habilitadas, para lo cuál tiramos el pin 15 a V+ (en este caso 5V) mediante un resistor de 10KΩ:
DSCN6736.JPG

7. El pin de STROBE al estar en estado alto transfiere los datos desde cada registro de desplazamiento a la memoria interna. En este caso vamos a dejarlo constantemente habilitado, de modo que los datos solo pasen:
DSCN6737.JPG

8. Por lo tanto solo vamos a pilotear dos pines de control: el CLOCK y el DATA (y si, lo mínimo :D ). Accedamos a ellos mediante dos resistores de 1KΩ:
DSCN6738.JPG

9. Para controlar nuestro engendrillo necesitamos generar señales lógicas, por lo que volveré a repetir el flip-flop del 555 que use antes para manejar que DATA mando. Para el clock voy a usar otro injerto quinientoscincuentesco, el sensor táctil:
Tactil.png
Mucho más cómodo y elegante para darle pulsos al engendrillo :D

DSCN6741.JPG
A la derecha he dispuesto el flip-flop de DATA (LED amarillo) y a la izquierda tengo el sensor táctil, del cual cuelga el cable verde que usaré para activar el CLOCK.

10. Conectamos las salidas de los 555 a los resitores de 1KΩ que nos están esperando en el 4094 (DATA cable azul, CLOCK cable amarillo):
DSCN6743.JPG

11. Bueno, el ensayo es simple. Dejé en estado alto DATA y dí tres pulsos de CLOCK:
DSCN6746.JPG

12. Cambié el estado de DATA y dí tres pulsos más de CLOCK:
DSCN6750.JPG

13. Volví a cambiar DATA y dos pulsilios más ;) :
DSCN6752.JPG

:aplauso: Y me armé mi bus de 8 bit :aplauso:

El razonamiento de esto es que al incorporarlo a lo que tenemos (ojo, aún quiero probarlo con el Arduino) podríamos generar con 4 pines del µC 40 salidas. Más aún si conseguimos un contador de 16, que sé que los hay. :eek:

Ventajas: ahorramos pines, tenemos constante control de las salidas.

Desventajas: perdemos velocidad ya que no solo hay que comerse el escribir dato por dato :facepalm: y dar el reloj para cada dato :facepalm: sino que además tenemos que comernos contar dos veces :facepalm: y resetear ese contador :facepalm: (cuatro palmazos).

Lo que sigue es un ensayo del conjunto completo.

Y capaz que después me copo en ir para el otro lado y vemos de hacer un multiplexador piola ;)
 
Última edición:
Atrás
Arriba