Cómo funciona el registro de turnos 74HC595 y su interfaz con Arduino
¿Qué es el 74HC595?
¿Alguna vez te has encontrado queriendo controlar muchos LEDs? ¿O sólo necesitabas más pines de E/S para controlar botones, sensores, servos, todo a la vez? Bueno, podrías conectar unos cuantos sensores a los pines de Arduino, pero rápidamente te quedarías sin pines en tu placa.
La solución para esto es usar un «Registro de turnos». Un registro de desplazamiento te permite ampliar el número de pines de E/S que puedes utilizar de tu Arduino (o cualquier microcontrolador para el caso). Y el registro de desplazamiento 74HC595 (apodado ‘595’) es uno de los más famosos entre todos.
El 595 controla esencialmente ocho pines de salida separados, usando sólo tres pines de entrada. Y si necesitas más de 8 líneas de E/S adicionales, puedes encadenar fácilmente tantos registros de desplazamiento como quieras y crear toneladas de líneas de E/S. Todo esto se logra mediante lo que se conoce como «bit-shifting». Si quieres saber más sobre el cambio de bits, en esta entrada de la Wikipedia te lo explican perfectamente.
¿Cuándo usar el Registro de turnos?
Los registros de turnos se utilizan a menudo con el fin de guardar los pines del microcontrolador, ya que cada microcontrolador tiene un número limitado de pines de E/S (GPIO).
Si tu proyecto necesita controlar 16 LEDs individuales, eso normalmente requeriría 16 pines de un Arduino. En el caso de que no tengas 16 pines de E/S disponibles, aquí es donde el registro de desplazamiento es útil y entra en juego. Con dos registros de cambio conectados en serie, podemos realizar la tarea de controlar los 16 LEDs con sólo 3 pines de E/S. Y no sólo esto; puedes guardar más pines cuanto más registros de desplazamiento tengas encadenados.
Un ejemplo del mundo real que utiliza el registro de desplazamiento es el «Mando Original de Nintendo». El mando principal de la Nintendo Entertainment System necesitaba que se pulsaran todos los botones en serie, y utilizaba un registro de desplazamiento para realizar esa tarea.
SIPO contra los registros de turno PISO
Los registros de desplazamiento vienen en dos tipos básicos, o bien SIPO (Serial-In-Parallel-Out) o PISO (Parallel-In-Serial-Out). El popular chip SIPO es 74HC595, y el chip PISO es 74HC165.
El primer tipo, SIPO, es útil para controlar un gran número de salidas, como los LEDs. Mientras que el segundo tipo, PISO, es bueno para reunir un gran número de entradas, como botones; como el que se utiliza en el mando original de Nintendo como se ha mencionado anteriormente.
¿Cómo funciona el registro de turnos 74HC595?
El 595 tiene dos registros (que se pueden considerar como «contenedores de memoria»), cada uno con sólo 8 bits de datos. El primero se llama Registro de Turno. El Registro de Turno se encuentra en lo profundo de los circuitos IC, aceptando silenciosamente la entrada.
Cada vez que aplicamos un pulso de reloj a un 595, ocurren dos cosas:
Los bits del Registro de Turnos se mueven un paso a la izquierda. Por ejemplo, el bit 7 acepta el valor que antes estaba en el bit 6, el bit 6 obtiene el valor del bit 5, etc.
El bit 0 del Registro de Turnos acepta el valor actual en el pin DATA. En el borde ascendente del pulso, si el pin de datos es alto, entonces un 1 se empuja en el registro de desplazamiento. De lo contrario, es un 0.
Al activar la clavija Latch, el contenido del Registro de Desplazamientos se copia en el segundo registro, llamado Registro de Almacenamiento/Latch. Cada bit del Registro de almacenamiento está conectado a uno de los pines de salida QA-QH del IC, así que en general, cuando el valor del Registro de almacenamiento cambia, también lo hacen las salidas.
74HC595 Pinout
El 595 viene en una variedad de marcas y modelos; aquí hablaremos del omnipresente Texas Instruments SN74HC595N. Si tienes uno diferente, estudia su hoja de datos cuidadosamente y toma nota de cualquier diferencia.
Echemos un vistazo a su Pinout. Fíjate que dos pines tienen una línea sobre su nombre; esto significa que operan en «lógica negativa». Lo sabrás un poco más tarde.
- GND debería estar conectado a la tierra de Arduino.
- VCC es la fuente de alimentación para el registro de cambio 74HC595 que conectamos al pin 5V de Arduino.
- El pin SER (Serial Input) se utiliza para alimentar los datos en el registro de cambio de un bit a la vez.
- SRCLK (Shift Register Clock) es el reloj del registro de cambio. El 595 es impulsado por el reloj en el borde ascendente. Esto significa que para desplazar bits en el registro de desplazamiento, el reloj debe estar ALTO (HIGH). Y los bits se transfieren en el borde ascendente del reloj.
- RCLK (Register Clock / Latch) es un pin muy importante. Cuando se maneja en ALTO (HIGH), el contenido del Registro de Desplazamiento se copia en el Registro de Almacenamiento / Reloj; que finalmente se muestra en la salida. Así que la clavija del pestillo puede ser vista como el paso final en el proceso de ver nuestros resultados en la salida, que en este caso son los LEDs.
- La clavija SRCLR (Shift Register Clear) nos permite reiniciar todo el Registro de Desplazamiento, haciendo que todos sus bits sean 0, a la vez. Este es un pin de lógica negativa, así que para realizar este restablecimiento, necesitamos poner el pin SRCLR en LOW. Cuando no se requiere un restablecimiento, este pin debe ser ALTO (HIGH).
- OE (Output Enable) también es de lógica negativa: Cuando el voltaje en él es ALTO (HIGH), los pines de salida se deshabilitan/se ajustan a un estado de alta impedancia y no permiten que la corriente fluya. Cuando OE tiene bajo voltaje, los pines de salida funcionan normalmente.
- QA-QH (Output Enable) son los pines de salida y deben ser conectados a algún tipo de salida como LEDs, 7 segmentos, etc.
- El Pin ‘QH’ da salida al bit 7 del ShiftRegister. Está ahí para que podamos encadenar 595s: si conectas este QH’ al pin SER de otro 595, y das a ambos ICs la misma señal de reloj, se comportarán como un solo IC con 16 salidas. Por supuesto, esta técnica no está limitada a dos ICs, puedes encadenar tantos como quieras, si tienes suficiente potencia para todos ellos.
Cableado y Conexión del registro de turnos 74HC595 a Arduino UNO
Ahora que tenemos un conocimiento básico de cómo funciona 74HC595, podemos empezar a conectarlo a nuestro Arduino.
Empieza colocando el registro de cambio en tu tablero, asegurándote de que cada lado del CI esté en un lado separado del tablero. Con la pequeña muesca en forma de U mirando hacia arriba, los pines están 1-8 abajo del lado izquierdo de arriba a abajo y 16 – 9 abajo del lado derecho de arriba a abajo como se puede ver en la ilustración de abajo.
Para empezar, conectemos las clavijas 16 (VCC) y 10 (SRCLR) a la clavija 5v del Arduino y conectemos las clavijas 8 (GND) y 13 (OE) a la clavija Gnd del Arduino. Esto debería mantener el CI en el modo de trabajo normal.
A continuación tenemos que conectar los tres pines con los que controlaremos el registro de cambio:
- El pin 11 (SRCLK) del registro de cambio al pin 6 del Arduino
- El pin 12 (RCLK) del registro de cambio al pin 5 en el Arduino
- El pin 14 (SER) del registro de cambio al pin 4 en el Arduino
Ahora, sólo tenemos que conectar todos los pines de salida a nuestros LEDs, asegurándonos de que una resistencia 220Ω se coloca antes de los LEDs para reducir la corriente y que los cátodos de los LEDs vuelven a tierra.
Cuando coloques los LEDs asegúrate de que estén conectados en orden, de modo que QA esté conectado al primer LED, y QH esté conectado al último LED, ya que de lo contrario nuestro código no va a encender los LEDs en el orden correcto!
Cuando termines deberías tener algo que se vea similar a la ilustración que se muestra a continuación.
Código de Arduino
Ahora estamos listos para escribir el código. Enchufa tu Arduino en tu ordenador y prueba el sketch; y luego lo diseccionaremos con algún detalle.
int latchPin = 5; // Latch pin of 74HC595 is connected to Digital pin 5 int clockPin = 6; // Clock pin of 74HC595 is connected to Digital pin 6 int dataPin = 4; // Data pin of 74HC595 is connected to Digital pin 4 byte leds = 0; // Variable to hold the pattern of which LEDs are currently turned on or off /* * setup() - this function runs once when you turn your Arduino on * We initialize the serial connection with the computer */ void setup() { // Set all the pins of 74HC595 as OUTPUT pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); } /* * loop() - this function runs over and over again */ void loop() { leds = 0; // Initially turns all the LEDs off, by giving the variable 'leds' the value 0 updateShiftRegister(); delay(500); for (int i = 0; i < 8; i++) // Turn all the LEDs ON one by one. { bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds' updateShiftRegister(); delay(500); } } /* * updateShiftRegister() - This function sets the latchPin to low, then calls the Arduino function 'shiftOut' to shift out contents of variable 'leds' in the shift register before putting the 'latchPin' high again. */ void updateShiftRegister() { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, leds); digitalWrite(latchPin, HIGH); }
Una vez que cargues el código al Arduino, deberías ver que los leds se van encendiendo uno a uno.
Si quisieras apagar uno de los LEDs en vez de encenderlo, llamarías a una función similar de Arduino, bitClear() en la variable ‘leds’. Esto pondrá ese bit particular de ‘leds’ a 0 y entonces sólo necesitarías llamar a updateShiftRegister() para actualizar los LEDs reales.
Explicación del código:
Lo primero que hacemos es definir los 3 pines de control, es decir, el pin del reloj y el pin de datos del 74HC595, vamos a conectarnos a los pines digitales #5, #6 y #4 de Arduino respectivamente.
int latchPin = 5; int clockPin = 6; int dataPin = 4;
A continuación, se define una variable llamada ‘leds’. Esto se usará para mantener el patrón de qué LEDs están actualmente encendidos o apagados. Los datos del tipo ‘byte’ representan números que usan ocho bits. Cada bit puede estar encendido o apagado, así que esto es perfecto para llevar la cuenta de cuál de nuestros ocho LEDs están encendidos o apagados.
// Variable to hold the pattern of which LEDs are currently turned on or off byte leds = 0;
En la función de «configuración»: simplemente inicializamos los tres pines para que sean salidas digitales.
void setup() { pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); }
La función de bucle: inicialmente apaga todos los LEDs, poniendo todos los bits de la variable ‘leds’ a 0. Luego llama a la función personalizada llamada updateShiftRegister() que enviará el patrón de ‘leds’ al registro de cambio para que todos los LEDs se apaguen. Más adelante veremos cómo funciona updateShiftRegister().
El programa se detiene durante medio segundo y luego comienza a contar de 0 a 7 usando el bucle ‘for’ y la variable ‘i’. Cada vez, utiliza la función de Arduino bitSet() para establecer el bit que controla el LED particular en la variable ‘leds’. Luego también llama a updateShiftRegister() para que el estado de los LEDs cambie de acuerdo a lo que hay en la variable ‘leds’.
Entonces hay un retraso de medio segundo antes de que la «i» se incremente y se encienda el siguiente LED.
void loop() { leds = 0; updateShiftRegister(); delay(500); for (int i = 0; i < 8; i++) { bitSet(leds, i); updateShiftRegister(); delay(500); } }
La función updateShiftRegister() , en primer lugar pone el pasador del pestillo en LOW, y luego llama a la función de Arduino shiftOut() antes de poner el pasador del pestillo en HIGH de nuevo.
Afortunadamente Arduino proporciona una función de ayuda específica para los registros de cambio llamada shiftOut() , que nos permite simplemente cambiar los bits en una llamada. Puedes explorar más sobre la biblioteca en la página web oficial de Arduino.
La función shiftOut() toma cuatro parámetros; los dos primeros son los pines a utilizar para Data y Clock respectivamente. El tercer parámetro especifica en qué extremo de los datos quieres empezar. Vamos a empezar con el bit más correcto, que se denomina «Bit menos significativo» (LSB).
El último parámetro es el dato real que se desplazará en el registro de desplazamiento, que en este caso es ‘leds’.
void updateShiftRegister() { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, leds); digitalWrite(latchPin, HIGH); }
Control del brillo mediante PWM
Como suplemento, aquí hay otro proyecto, basado en la misma configuración pero con una pequeña diferencia, donde manipulamos otra clavija de control en el IC, es decir, el OE – y al hacer eso, podemos controlar el brillo de los LEDs de salida!
Ya hemos aprendido que la clavija OE (Output Enable) actúa como un interruptor. Cuando esta clavija está en HIGH, las clavijas de salida se desactivan (funciona con lógica negativa, ¿recuerdas?). Y cuando OE recibe bajo voltaje, los pines de salida funcionan normalmente.
En nuestro ejemplo anterior, habíamos conectado esta clavija permanentemente a Tierra, habilitando las salidas todo el tiempo. Si conectamos esta clavija a cualquiera de los pines digitales de Arduino y programamos para conmutar su estado.
Pero, en lugar de hacer eso, podemos usar esta clavija junto con la función analogWrite(), para controlar el brillo de los LEDs usando PWM.
Actually the HIGH parts of the PWM signal will still cause the OE pin to temporarily disable all the IC outputs. But, this will happen, of course, faster than our eyes can perceive directly, but we will definitely sense a variation in the overall brightness.
En realidad, las partes HIGH de la señal PWM todavía causarán que el pin OE desactive temporalmente todas las salidas IC. Pero, esto sucederá, por supuesto, más rápido de lo que nuestros ojos pueden percibir directamente, pero definitivamente sentiremos una variación en el brillo general.
Para hacer esto, todo lo que necesitas hacer, es cambiar la conexión al pin 13 del 74HC595. Así que en lugar de conectarlo a la tierra, lo conectas al pin 3 del Arduino.
El siguiente código hace que una vez que todos los LEDs han sido encendidos se apaguen gradualmente.
int latchPin = 5; // Latch pin of 74HC595 is connected to Digital pin 5 int clockPin = 6; // Clock pin of 74HC595 is connected to Digital pin 6 int dataPin = 4; // Data pin of 74HC595 is connected to Digital pin 4 int outputEnablePin = 3; // OE pin of 74HC595 is connected to PWM pin 3 byte leds = 0; // Variable to hold the pattern of which LEDs are currently turned on or off /* * setup() - this function runs once when you turn your Arduino on * We initialize the serial connection with the computer */ void setup() { // Set all the pins of 74HC595 as OUTPUT pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(outputEnablePin, OUTPUT); } /* * loop() - this function runs over and over again */ void loop() { setBrightness(255); leds = 0; // Initially turns all the LEDs off, by giving the variable 'leds' the value 0 updateShiftRegister(); delay(500); for (int i = 0; i < 8; i++) // Turn all the LEDs ON one by one. { bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds' updateShiftRegister(); delay(500); } for (byte b = 255; b > 0; b--) // Gradually fade all the LEDs back to off { setBrightness(b); delay(50); } } /* * updateShiftRegister() - This function sets the latchPin to low, then calls the Arduino function 'shiftOut' to shift out contents of variable 'leds' in the shift register before putting the 'latchPin' high again. */ void updateShiftRegister() { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, leds); digitalWrite(latchPin, HIGH); } /* * setBrightness() - Generates PWM signal and writes it to OE pin. */ void setBrightness(byte brightness) // 0 to 255 { analogWrite(outputEnablePin, 255-brightness); }
Y entonces los LEDS después de encenderse se apaguen gradualmente.
https://youtu.be/mduMtkadoM4
Debe estar conectado para enviar un comentario.