Entendiendo distribución de pines del circuito integrado
El IC 74HC595 tiene 16 pines en total. Los que nos importan en este momento son los ocho que sirven como salida, los del suministro de energía y los que se encargan del latch, data y clock.
Distribución de pines
La distribución es así:
Aquí hay otra imagen de la distribución de pines:
Podemos identificar el orden de los pines guiándonos de la pequeña muesca que tiene. Si vemos la muesca arriba, los pines comienzan a la izquierda y terminan a la derecha de ella.
- Con verde marqué las salidas. Tenemos ocho en total, comenzando con el pin 15 (la salida 0) y luego yendo del pin 1 al 7.
- Con azul resalté los tres pines que irán conectados al Arduino. En este caso el pin 11 es el Clock, el 12 es el Latch y el 14 Data.
- Finalmente, remarqué la tierra y el voltaje individualmente. Es de gran importancia mencionar que debemos alimentar al circuito por sus dos pines: tanto por el 16 como por el 10. Y conectar a tierra el 13 y el 8.
Los demás, ni yo sé para qué funcionan, y tampoco importan por el momento.
¿Qué vamos a hacer?
Vamos a controlar 8 leds usando sólo 3 salidas usando el CI del título. Los materiales son:
- Tarjeta Arduino, no importa el modelo
- Circuito integrado 74HC595
- 8 leds (o diodos emisores de luz) de cualquier color
- 8 resistencias de 220 Ohms
- Cables para conectar todo
Montando circuito
Hice el circuito en la maravillosa herramienta de Tinkercad. Los cables amarillos son de la salida, recordemos que los leds deben llevar una resistencia de 220 ?.
Puse todo ordenado para que se vea cómo funciona, pero en la práctica podemos conectar como sea.
¿Cómo funciona?
Una vez definidos nuestros pines de latch, clock y data, simplemente tenemos que llamar a la función ShiftOut de Arduino. Es una función nativa, así que no necesitamos ninguna librería. También cabe mencionar que no importa el modelo de la tarjeta que tengamos, la función se comportará de la misma manera, y podemos definir los pines como lo deseemos.
Al llamar a dicha función, le pasamos como primer argumento el pin de data, como segundo el pin de clock, después, como tercero, el orden de salida (Primero el bit más significativo o primero el bit menos significativo; es decir, comenzar de izquierda a derecha o de derecha a izquierda) y finalmente una variable de tipo byte que será casteada internamente en caso de que no la definamos como tal.
Ejemplo de llamada a función
shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, 1);
En ese caso le indicamos que escriba el número 1. Entonces pondrá la salida número 8 a HIGH
y las demás a LOW
; ya que si recordamos, el 1 en binario es 00000001
.
Si ahora le decimos que represente el número 20, pondrá solamente la salida número 4 y 6 a HIGH
, porque el 20 en binario es 00010100
.
Escribir un número arbitrario
Para comenzar con esto vamos a mostrar un número definido por nosotros mismos. Será el número 20. El código es muy simple. Definimos nuestros pines, los establecemos como salida y escribimos el valor.
/*
Escribir un número decimal a binario usando leds
@autor parzibyte
@web parzibyte.me
*/
#define PIN_CLOCK 2
#define PIN_LATCH 3
#define PIN_DATA 4
void setup() {
/*
Al final de todo, son pines de salida,
y debemos establecerlos como tal
*/
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_LATCH, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
/*
Simplemente vamos a escribir un valor
*/
digitalWrite(PIN_LATCH, LOW); //Le decimos que vamos a escribir algo...
shiftOut(PIN_DATA, PIN_CLOCK, LSBFIRST, 20); //Lo escribimos
digitalWrite(PIN_LATCH, HIGH) ; //Y le indicamos que lo guarde
}
void loop() {}
Al subir y cargar nuestro código, el resultado será el siguiente:
Podemos observar que se encendieron los leds en la posición que representa al 16 y al 4 (16 + 4 = 20)
Puedes ver la simulación aquí (necesitarás registrarte).
Escribir los números del 0 al 255
Vamos a hacer esto un poco más divertido, ahora vamos a representar los números que se pueden representar con ocho bits, esto es, del 0 al 255. El código ahora sería:
/*
Escribir los números del 0 al 255 en su representación binaria usando leds
@autor parzibyte
@web parzibyte.me
*/
#define PIN_CLOCK 2
#define PIN_LATCH 3
#define PIN_DATA 4
void setup() {
/*
Al final de todo, son pines de salida,
y debemos establecerlos como tal
*/
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_LATCH, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
}
void loop() {
/*
Vamos a hacer lo mismo pero ahora en un ciclo, y dentro de loop, para que cuando llegue a 255 inicie de nuevo
*/
for (int m = 0; m < 256; m++) {
digitalWrite(PIN_LATCH, LOW); //Le decimos que vamos a escribir algo...
shiftOut(PIN_DATA, PIN_CLOCK, LSBFIRST, m); //Escribimos el número en el que ahora está el ciclo
digitalWrite(PIN_LATCH, HIGH) ; //Y le indicamos que lo guarde
delay(500); //Esperamos un poco (medio segundo), para que se vea la animación. De otro modo, no veríamos correctamente cómo va "contando"
}
}
Si ejecutamos el código, veremos cómo va contando. Primero enciende el led que representa al 1, luego al 2, luego al 2 y 1, y así sucesivamente. Puedes ver la simulación aquí (necesitarás registrarte).
Escribir un número definido por el usuario
Seguimos jugando. Ahora vamos a pedir un número por comunicación Serial, y ese número será escrito en los leds.
Veamos ahora el código:
/*
Escribir un número proporcionado por el usuario a través de la comunicación Serial
@autor parzibyte
@web parzibyte.me
*/
#define PIN_CLOCK 2
#define PIN_LATCH 3
#define PIN_DATA 4
void setup() {
/*
Al final de todo, son pines de salida,
y debemos establecerlos como tal
*/
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_LATCH, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
Serial.begin(9600); //Comenzar comunicación serial
}
void loop() {
/*
Vamos a hacer lo mismo pero ahora en un ciclo, y dentro de loop, para que cuando llegue a 255 inicie de nuevo
*/
if (Serial.available()) { //¿Hay algo que leer en el serial?
int numero = Serial.parseInt(); //Si es que sí, lo leemos y lo convertimos a entero
if (numero >= 0 && numero < 256) { //Recordemos que sólo tenemos 1 byte, por lo que no podemos representar números más grandes que 255
digitalWrite(PIN_LATCH, LOW); //Le decimos que vamos a escribir algo...
shiftOut(PIN_DATA, PIN_CLOCK, LSBFIRST, numero); //Escribimos el número que el usuario proporcionó
digitalWrite(PIN_LATCH, HIGH) ; //Y le indicamos que lo guarde
}
}
}
Hacemos el mismo proceso, sólo que ahora leemos el número por comunicación Serial. También comparamos si el número cabe en un byte (si está entre 0 y 255) para no tener resultados inesperados. Al ejecutarlo e ingresar un número, este es el resultado:
Puedes ver la simulación aquí (necesitarás registrarte).
Escribir el código ASCII de un carácter
Para terminar con esto, vamos a escribir la representación de un carácter en binario. Por ejemplo, en ASCII, el arroba (@) es representado por el número 64. Y el 64 en binario es 01000000. Así que pediremos un carácter por comunicación Serial y pondremos su representación binaria con los leds.
/*
Escribir la representación binaria de un carácter proporcionado por el usuario a través de la comunicación Serial
@autor parzibyte
@web parzibyte.me
*/
#define PIN_CLOCK 2
#define PIN_LATCH 3
#define PIN_DATA 4
void setup() {
/*
Al final de todo, son pines de salida,
y debemos establecerlos como tal
*/
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_LATCH, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
Serial.begin(9600); //Comenzar comunicación serial
}
void loop() {
/*
Vamos a hacer lo mismo pero ahora en un ciclo, y dentro de loop, para que cuando llegue a 255 inicie de nuevo
*/
if (Serial.available()) { //¿Hay algo que leer en el serial?
char caracter = Serial.read(); //Si es que sí, lo leemos. En este caso la variable será de tipo char
if (caracter >= 0 && caracter < 256) { //Recordemos que sólo tenemos 1 byte, por lo que no podemos representar carácteres cuyo código no esté entre 0 y 255
digitalWrite(PIN_LATCH, LOW); //Le decimos que vamos a escribir algo...
shiftOut(PIN_DATA, PIN_CLOCK, LSBFIRST, caracter); //Escribimos el carácter que el usuario proporcionó
digitalWrite(PIN_LATCH, HIGH) ; //Y le indicamos que lo guarde
}
}
}
Ahora en lugar de leer un entero leemos un carácter. Y lo escribimos. Por ejemplo, si yo pongo el @ se encenderá el led que representa al 64:
Nuevamente, se puede simular aquí, y se necesita registro.
Conclusión
Este circuito integrado es una maravilla, pues nos ahorra muchos pines. Ya que sólo usamos 3 y con ellos controlamos 8. Me parece que también existen de más salidas. Por otro lado, existen aquellos que son lo contrario. Es decir, que nos permiten leer muchos valores con pocas entradas.
Todo esto lo hice en el simulador porque es una manera fácil y rápida de que la gente pueda probar, sin necesidad de tener que armar el circuito, ni comprar los componentes. De todas maneras, lo he probado yo con un Arduino en la vida real, y una vez que lo logré y funcionó, lo simulé.
Espero que haya servido.
Hola que tal me gusto tu post pero me surgió una duda ¿Se puede conectar 4 leds en paralelo en un solo pin del microcontrolador 74HC595? pude ser que no se enciendan del todo bien pero si funciona como haría para añadir una fuente externa (para que funcione bien) para luego conectarlo al pin de ese microcontrolador. Agradeceria mucho tu respuesta Saludos
Hola, claro que sí. Si mandas la corriente normal, no creo que enciendan todos o será de manera baja. Tus opciones son usar un Transistor o un relevador/relé y una fuente externa, como lo mencionas.
En resumen, claro que puedes conectar muchos leds a una sola salida, y no solamente leds, sino cualquier otra cosa.
Estimado. Tengo que resolver un problema con un vu meter. Este usa un ATtyni24.
Yo estoy a penas aprendiendo, comenzando a aprender a programar. Me gustaria su puedes apoyarme en dicho proyecto.
saludos
Hola, lo siento, no he trabajado con eso que mencionas, únicamente con Arduino. Espero que encuentres la solución pronto, saludos.