¿Hay alguna manera de tener más de 14 pines de salida en arduino?


52

¿Es posible tener más de 14 pines de salida en el Arduino? Estoy trabajando en un proyecto en el que necesito encender varios LED de forma individual. Solo tengo un Arduino Uno, y no quiero obtener un Mega.


En el espíritu de la capacidad de expansión, ¿es I2C incluso una opción con Arduino?
Chris O

@ChrisO ¿Qué quieres decir con I2C? Porque, por lo que entiendo, los registros de desplazamiento se considerarían I2C.
JVarhol

Oh, hazme responder mi pregunta entonces ;-) Aquí hay un artículo de Wikipedia sobre este estándar de bus. Y acabo de encontrar algo de soporte de Wire lib para I2C, para que pueda conectar una cadena I2C a su Uno.
Chris O

@JVarhol No del todo. I2C, también conocido como TWI, es una interfaz de 2 hilos, mientras que SPI puede considerarse una interfaz de 3 hilos.
Klaus-Dieter Warzecha

1
@JVarhol, ¿ya seleccionó una solución para su proyecto? En caso afirmativo, sería útil editar su pregunta y aceptar la respuesta que coincida (o sea la más cercana) con su solución.
jfpoilpret

Respuestas:


50

Una forma común de expandir el conjunto de pines de salida disponibles en el Arduino es usar registros de desplazamiento como el 74HC595 IC ( enlace a la hoja de datos ).

Necesita 3 pines para controlar estos chips:

  1. Reloj
  2. Pestillo
  3. Datos

En un programa, pasa los datos un bit a la vez al registro de desplazamiento utilizando el comando shiftOut () , así:

shiftOut(dataPin, clockPin, data); 

Con ese comando, establece cada una de las 8 salidas en el 595 IC con los 8 bits en la datavariable.

Con un 595, ganas 5 pines (8 en el IC, pero gastas 3 para hablar con él). Para obtener más salidas, puede conectar en serie una serie de 595, conectando su pin de salida en serie, al pin de datos del siguiente. También debe conectar juntos el reloj y los pines de cierre de todos los 595 IC.

El circuito resultante (usando un 595) se vería así:

Circuito con registro de desplazamiento 595

La figura anterior se tomó de esta página web codeproject.com :

El pin de enganche se usa para mantener estables las salidas 595 mientras se cambian los datos, así:

digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, data); 
digitalWrite(latchPin, HIGH);

1
Gracias, olvidé incluir cómo funciona un registro de desplazamiento. Había planeado hacerlo, pero tuve que alejarme de mi composición y cuando regresé se me había olvidado. :)
JVarhol

No hay problema, por eso somos una comunidad. Complementamos las respuestas de los demás. Pero es bueno que haya agregado algunos buenos consejos en su respuesta, especialmente sobre el escudo EZ-Expander. Permite a aquellos que no pueden fabricar fácilmente sus PCB expandir la cantidad de puertos disponibles para ellos.
Ricardo

2
También facilita la programación, no tiene que cambiar los datos y pulsar el reloj y luego activar el bloqueo. Conozco el escudo desde hace bastante tiempo y creo que es perfecto para principiantes. Lo mejor es que, debido a que el código es de código abierto, puede usar el código incluso si no está utilizando el escudo real, pero tiene su propia placa o está utilizando una placa de pruebas.
JVarhol

1
No olvide que puede vincularlos en línea (teóricamente) indefinidamente, por lo que 2 registros de 8 bits pueden convertirse en uno de 16 bits.
Scott M.

¡Gracias! He aquí un enlace de archivo de la descripción CodeProject increíble en caso de que el enlace nunca se cae archive.fo/1uvPE
Akhmed

27

Hay dos formas de obtener más pines de un arduino.

La primera forma es mediante el uso de los pines analógicos como pines de salida digital, lo cual es realmente fácil de hacer. Todo lo que necesita hacer es referirse a A0-A5 como pines 14,15,16,17,18,19. Por ejemplo, para escribir alto en el pin A0 solo use digitalWrite (14, HIGH).

La otra forma de obtener más pines del Arduino es mediante el uso de un registro de desplazamiento. Para hacer esto, recomiendo usar el EZ-Expander Shield , que le permite usar digitalWrite ([20-35], HIGH) cuando importe la Biblioteca EZ-Expander. Sin embargo, este escudo solo permite que los pines se usen solo como salidas y usa los pines 8,12 y 13 para controlar los registros de desplazamiento.

Lo mejor es que puedes usar los dos métodos anteriores juntos sin ningún problema.


3
Según la referencia de Arduino, en realidad puede usar los identificadores A0- A5directamente en lugar de usar los números 14-19. Por ejemplo, digitalWrite(A0, HIGH).
Peter Bloomfield

3
@ PeterR.Bloomfield Ambos son correctos, sin embargo, recomiendo A0-A5 por simplicidad y facilidad de lectura. No es un gran problema con un LED parpadeante, pero cuando tienes proyectos grandes, los pequeños hábitos se acumulan.
Anonymous Penguin

2
En realidad, si bien ambos harán el trabajo en UNO y placas compatibles, digitalWrite(A0)es más correcto que digitalWrite(14)ya que el primero siempre se asignará al pin físico (analógico) correcto. En una placa diferente, pin 14de hecho puede no serlo A0, por ejemplo, pin 14en el MEGA es Serial3 TXy no influirá en el pin analógico que está buscando. es decir, si se usa digitalWriteen un pin analógico, use la referencia A0- A5.
Madivad

18

Si desea controlar los LED, también puede usar un MAX7219 que puede controlar 64 LED, sin circuitos adicionales (no es necesario un transistor para amplificar la señal).

Conducir un MAX7219 requiere solo 3 pines de salida en Arduino. Además, puede encontrar algunas bibliotecas Arduino para ello.

También puede encadenar varios de ellos si necesita alimentar más de 64 LED.

Lo he usado con éxito para múltiples pantallas LED de 7 segmentos.

Desventaja: es caro (alrededor de $ 10).


Me olvidé del MAX7219, ¡Gracias por publicar!
JVarhol

384 LEDs ... ¡vaya! Más dos pines para inferencia USB. Me pregunto qué tipo de baratija molesta puedes crear (con una fuente de alimentación suficiente).
Anonymous Penguin

17

Puedes usar Charlieplexing . Con esta técnica, puede conducir directamente los n*(n-1)LED desde n pines. Entonces, con 3 pines puede manejar 6 LED, 4 pines - 12 LED, 5 pines - 20 LED y así sucesivamente.

Ejemplo:

Seis LED en 3 pines

PINS        LEDS
0 1 2   1 2 3 4 5 6
0 0 0   0 0 0 0 0 0
0 1 Z   1 0 0 0 0 0
1 0 Z   0 1 0 0 0 0
Z 0 1   0 0 1 0 0 0
Z 1 0   0 0 0 1 0 0
0 Z 1   0 0 0 0 1 0
1 Z 0   0 0 0 0 0 1
0 0 1   0 0 1 0 1 0
0 1 0   1 0 0 1 0 0
0 1 1   1 0 0 0 1 0
1 0 0   0 1 0 0 0 1
1 0 1   0 1 1 0 0 0
1 1 0   0 0 0 1 0 1
1 1 1   0 0 0 0 0 0

ingrese la descripción de la imagen aquí

Puedes ver un mejor tutorial aquí .


Una cosa a tener en cuenta es que esta técnica le permite controlar más leds, pero no necesariamente de manera simultánea.
kontur

1
@kontur sí, tienes razón. Pero en términos de persistencia de la visión, puede considerar que lo son. La pregunta no tiene esos detalles.
Daniel Grillo

Charlieplexing no es la ÚNICA forma de multiplexar LED sin usar registros de desplazamiento.
linhartr22

1
@ linhartr22 NUNCA dije que esa es la única manera. Charlieplexing es solo una solución común para este problema. Y mi respuesta fue la séptima. Así que otras posibilidades ya se habían mostrado antes.
Daniel Grillo

@DanielGrillo Debería haber sido más específico y explicar cómo la multiplexación de columnas y filas, que generalmente se usa en cubos LED, se puede hacer sin registro de desplazamiento y sin las limitaciones de Charlieplexing. Una matriz de columna de fila 4x4 puede controlar individualmente 16 leds con 8 líneas de E / S. Un cubo 4x4x4 puede controlar individualmente 64 leds con 12 líneas de E / S (posible incluso en un Uno usando Analog A0-A5 como líneas digitales).
linhartr22

13

I 2 C (cable)

Puede usar el protocolo I 2 C (biblioteca Wire) para conectarse a otros dispositivos, como los expansores de puertos. Por ejemplo, el MCP23017.

Usé uno de esos chips para conectarme a una placa LCD. El MCP23017 tiene 16 puertos, que se pueden configurar como entradas o salidas. Como entradas pueden generar interrupciones si lo desean.

Ejemplo de conectar 13 de esos 16 a la pantalla LCD:

MCP23017 conectado a la pantalla LCD

Ahora nos conectamos al Arduino usando solo 2 cables (SDA / SCL) más alimentación y tierra:

MCP23017 conectado a Arduino


Algunos fabricantes de terceros han creado placas con 4 x MCP23017, esto le proporciona 64 entradas / salidas:

Tablero de ciempiés


Multiplexores

Puede usar multiplexores analógicos como el 74HC4051 (8 puertos) o el 74HC4067 (16 puertos) para conectar un pin a uno de los puertos 8/16 (pero solo uno en un momento dado), de esta manera:

Multiplexor 74HC4051

Estos son bidireccionales, por lo que se pueden usar como expansores de entrada o salida.


SPI con 74HC595

Con SPI puede enviar datos seriales rápidos a un registro de desplazamiento, como el 74HC595. Estos pueden ser encadenados juntos. En este ejemplo, estoy controlando 32 LED con solo 3 pines de E / S (MOSI / MISO / SCK) más alimentación y tierra.

74HC595 manejando 32 LEDs


Encontré dentro de un letrero LED comercial que los 72 LEDs estaban controlados por chips 74HC595.

Señal LED de desplazamiento

Esto tenía 9 chips manejando las columnas (9 x 8 = 72 LEDs) y un chip manejando las filas, en una configuración multiplexada.


SPI con MAX7219

Si solo desea controlar los LED, generalmente puede multiplexarlos. El MAX7219 simplifica eso al estar diseñado para controlar matrices LED, por ejemplo, pantallas de 7 segmentos:

MAX7219 con pantalla de 7 segmentos

O matrices de 64 LED:

MAX7219 con matriz de 64 LED

En ambos casos, estos se pueden conectar en cadena, por ejemplo:

Cadena de margaritas MAX7219

Todos esos ejemplos solo usan 3 pines del Arduino (MOSI / MISO / SCK) más potencia y tierra.


SPI con MCP23S17

El expansor de puerto de 16 puertos mencionado anteriormente (MCP23017) también viene en una variante SPI (MCP23S17), que hace cosas prácticamente idénticas. Utiliza un cable más, pero sería más rápido.


Otros protocolos

Las tiras de LED (como las NeoPixel) tienen sus propios protocolos. ¡Hubo una publicación en Youtube de Josh Levine donde el autor manejó más de 1000 píxeles con un Duemilanove!


Referencias


12

Los registros de desplazamiento se han mencionado en otras respuestas, y definitivamente son una excelente opción para muchos proyectos. Son baratos, simples, moderadamente rápidos y, por lo general, se pueden encadenar para agregar más salidas. Sin embargo, tienen el inconveniente de que generalmente necesitan el uso exclusivo de varios pines (entre 2 y 4, dependiendo de cómo los configure).

Una alternativa es utilizar expansores de puertos más avanzados, como el MCP23017 de 16 bits y el MCP23S17 . Estos admiten I2C y SPI respectivamente, lo que significa que puede colocarlos en un bus con varios otros dispositivos (potencialmente de diferentes tipos). Cada dispositivo en el bus se puede direccionar individualmente, lo que significa que solo necesita 2 o 3 pines para hablar con todos ellos. Las velocidades de actualización suelen ser extremadamente rápidas, por lo que es poco probable que experimente una latencia significativa (es decir, retrasos en la transmisión) en un proyecto Arduino.

En un nivel bajo, usar I2C o SPI es sustancialmente más complicado que un simple registro de desplazamiento. Sin embargo, hay un código de biblioteca para que Arduino se encargue de eso por usted. Vea esta pregunta, por ejemplo: ¿Cómo uso los dispositivos I2C con Arduino?


Wow, nunca supe de eso, gracias, ¡los miraré!
JVarhol

¿Se puede usar I2C para controlar los LED?
Pro Q

1
@ProQ No puede controlar los LED estándar directamente con I2C. Sin embargo, es posible obtener algunos productos LED que tienen un controlador I2C incorporado. Esto suele ser para productos con muchos LED, como tiras o matrices.
Peter Bloomfield

8

Además de la respuesta de Ricardo , lo que Wikipedia dice en los registros de desplazamiento :

Uno de los usos más comunes de un registro de desplazamiento es convertir entre interfaces seriales y paralelas. [...] Los registros SIPO se conectan comúnmente a la salida de microprocesadores cuando se requieren más pines de Entrada / Salida de Propósito General de los que están disponibles. Esto permite controlar varios dispositivos binarios utilizando solo dos o tres pines, pero más lento que la E / S paralela.

En el artículo que Ricardo vincula puede ver el diagrama del registro de desplazamiento.

Diagrama de registro de desplazamiento

Lo que sucede aquí es que coloca los datos de los 8 pines en una secuencia y para cada marca de reloj, el registro de desplazamiento cambiará (moverá los datos binarios de cada pestillo al siguiente) hasta que "haga un círculo", es decir, el primer bit llega al último pin. Los registros de desplazamiento también tienen una entrada donde puede activar / desactivar el desplazamiento para que el estado se pueda mantener después de que los datos se hayan desplazado a la posición. Para una demostración simple, vea la siguiente animación.

Animación de registro de desplazamiento

Aquí la luz roja es la entrada en serie y las verdes muestran el estado de los pestillos en este registro de desplazamiento SIPO simplificado . Después de que los datos se hayan desplazado a un lugar, se pueden desactivar los cambios y puede leer los pines. En este ejemplo, me mudé 10101011.

A partir de estos ejemplos, puede darse cuenta de que la transferencia en serie será más lenta que en paralelo, ya que debe esperar a que el registro de desplazamiento desplace los bits a su lugar. Tendrá que esperar la misma cantidad de tics de reloj tantos bits que desee cargar. Esta es una de las muchas razones por las que no se pueden encadenar indefinidamente, porque la carga llevaría una eternidad.


1
¡+1 por la información adicional Y por el bonito GIF animado y su efecto didáctico! ¿Dónde encontraste el GIF? ¿O lo hiciste?
Ricardo

1
@Ricardo Creé el circuito con Digital Works, luego imprimí pantalla, edité, gif animador.
totymedli

6

Como ya escribió, puede usar todos los pines, incluidos TX y RX como salida digital. Lo hice hace un tiempo para un demostrador y grabé un video, 20 LEDS en 20 pines , de este proyecto bastante absurdo.

Como lo describe Peter R. Bloomfield aquí , debe desconectar TX y RX para cargar. Además, no tiene pines para leer sensores para una posible interactividad y debe asegurarse de que no se alcance el límite de corriente total. Sin olvidar que está limitado a leds de 5V si los conduce directamente con su Arduino.

Por lo tanto, se recomienda encarecidamente el uso de registros de desplazamiento en general y el 595, descrito por Ricardo .

  • Son baratos!
  • Es bastante fácil ponerlos en cascada.
  • Se puede ganar mucha velocidad cuando usa hardware-SPI.

Los usé hace un tiempo cuando me di cuenta de la parte de soldadura y programación de Kawaii me (el texto del enlace está en alemán) del artista de reciclaje Dominik Jais .

Aquí, solo un grupo de 595 fueron utilizados para manejar una pantalla de 8x11 leds. Dado que los leds se cortaron de una banda de leds SMD de 12V, fue necesaria una fuente de alimentación adicional y algunos arreglos Darlington UDN2803A , conectados a los pines de salida de los registros de desplazamiento.

Otros métodos generales incluirían el uso de expansores de puerto PCF8574 (A) de 8 bits, que se controlan a través del bus I2C.

De todos modos, probaría primero los registros de turno 595.

Sin embargo, si necesita controlar un par de leds RGB, es posible que desee buscar soluciones más especializadas. Algunos leds RGB vienen con su propio WS2812 . Estas piezas finas se pueden conectar en cascada (bus de 1 cable) y se abordan a través de su posición en la cadena.


3

Si se trata de LED, ¿qué pasa con las tiras de LED WS2812B, o solo los chips del controlador? ¡Puedes controlar un número virtualmente ilimitado de LED con solo un pin!

Aunque las personas están acostumbradas a esto en tiras, están disponibles como LED independientes (conocidos como neo píxeles en Adafruit). O si solo está manejando un solo color, cada chip WS2811 podría controlar 3 LED usando cada una de las salidas RGB para un solo LED cada uno.

Recientemente, acabo de crear un proyecto que utiliza 5 de estos LED: Puerta1 abierta / cerrada, Puerta2 abierta / cerrada, motor1 activo, motor2 activo y encendido. Los LED "activos" tienen un doble propósito, ya que el rojo es la entrada del motor activo y el verde el indicador activo dentro del Arduino.

Punto que, con 1 pin y la biblioteca instalada, puede controlar cualquier número de LED


2

No reclamo este método por mi cuenta, pero encontré este buen truco en la página web MUX-DEMUX: CD4051 Trucos de salón

Cualquiera que sea el método que elija para manejar salidas o leer entradas (registros de desplazamiento, multiplexores o el uso directo directo de los pines Arduino), puede DOBLAR el número de salidas o entradas mediante un uso inteligente de pares de circuitos paralelos (para formar un doble banco de entrada o salida ), empleando diodos en sentidos opuestos en cada rama paralela, y cambiando las entradas / salidas a alto y bajo.

Para ilustrar el método para las salidas (LED en este caso, tenga en cuenta que no se requieren diodos adicionales):

Banco LED

Si considera que el par de LED en este ejemplo es un "banco" y desea encender LED_0, debe configurar el PIN 17 en ALTO y el PIN 18 en BAJO. (Los números de pin son confusos, pero coinciden con el ejemplo posterior tan desnudo conmigo). Para encender el LED_1, simplemente invierte los PINS. La naturaleza del diodo de los LED evita que la corriente fluya en la dirección opuesta, manteniendo el otro apagado.

Para ilustrar el método para las entradas (CdS en este caso, tenga en cuenta que se requieren diodos adicionales):

Banco CdS

Esto se vuelve un poco más complicado si desea hacer una lectura analógica en un sensor de luz CdS. Primero, debe agregar un diodo a cada sensor para controlar el flujo. En segundo lugar, dado que está leyendo valores, debe subir o bajar las entradas para evitar que floten. Siendo una persona perezosa, voy a sacarlos usando las resistencias pull-up internas. Para leer CdS_0, establezca el modo PIN 17 en SALIDA y configúrelo en BAJO. Esto lo convierte en el suelo. Luego configura el modo PIN 18 en INPUT y lo configura en HIGH para activar la resistencia pull-up. Ahora está configurado para leer el PIN 18 (también conocido como pin analógico 4). Para acceder al otro sensor, simplemente cambie los modos y las salidas.

Por lo tanto, si tiene un multiplexor CD4051 de 8 puertos, que utiliza 5 pines en el Arduino (en lugar de los 3 habituales), puede obtener 16 entradas o salidas, o una combinación de los dos.

16 salidas / entradas usando un CD4051

Del mismo modo, si tiene un multiplexor 4067 de 16 puertos, puede obtener 32 entradas o salidas, o una combinación de las dos.

Un boceto de ejemplo sería:

/*
 * Example of getting 16 i/o from 5 pins using a CD4051
 *
 * Based on tutorial and code by david c. and tomek n.* for k3 / malmö högskola
 * http://www.arduino.cc/playground/Learning/4051?action=sourceblock&ref=1
 */ 


int selPin[] = { 14, 15, 16 }; // select pins on 4051 (analog A0, A1, A2)
int commonPin[] = { 17, 18};   // common in/out pins (analog A3, A4)
int led[] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW };  // stores eight LED states
int CdSVal[] = { 0, 0, 0, 0 }; // store last CdS readings
int cnt = 0;  // main loop counter
int persistDelay = 100; // LED ontime in microseconds


void setup(){
  Serial.begin(9600);  // serial comms for troubleshooting (always)
  for(int pin = 0; pin < 3; pin++){ // setup select pins
    pinMode(selPin[pin], OUTPUT);
  } 
}


void loop(){
  flashLEDs();
  if (cnt == 0){
    for(int x; x < 8; x++){
      led[x] = random(2);
    }
  }
  cnt++;
  if (cnt > 100) { cnt = 0; }
}


void flashLEDs() {
  for(int pin = 0; pin < 2; pin++) {  // set common pins low
    pinMode(commonPin[pin], OUTPUT);
    digitalWrite(commonPin[pin], LOW);
  } 
  for (int bank = 0; bank < 4; bank++) {
    for(int pin = 0; pin < 3; pin++) { // parse out select pin bits
      int signal = (bank >> pin) & 1;  // shift  & bitwise compare
      digitalWrite(selPin[pin], signal);
    }
    if (led[bank * 2]){        // first LED
      digitalWrite(commonPin[0], HIGH);  // turn common on
      delayMicroseconds(persistDelay);   // leave led lit
      digitalWrite(commonPin[0], LOW);   // turn common off
    } 
    if (led[bank * 2 + 1]){     // repeat for second LED
      digitalWrite(commonPin[1], HIGH);
      delayMicroseconds(persistDelay);
      digitalWrite(commonPin[1], LOW); 
    }
  } 
}

Como dije en la primera línea, la explicación completa se puede encontrar en MUX-DEMUX: CD4051 Parlor Tricks


1

Para un proyecto de clase utilicé un CD4024 y dos pines Arduino para manejar una pantalla de 7 segmentos.

Hay algunas advertencias a este enfoque. Por ejemplo, para escribir un highvalor en la primera salida de un contador de ondulación solo se requiere resetay alternar el pin del reloj dos veces. Pero si desea escribir highen todos los n pines, debe activar el pin del reloj 2 n veces, y durante ese tiempo, todos los demás pines se activan y desactivan constantemente.

Si su aplicación puede manejar estas limitaciones y le faltan pines, es otra opción.

Bono de respuesta: hay una gran cantidad de ejemplos de entradas de multiplexación aquí , muchos de los cuales también se aplican a las salidas de multiplexación.


Usar un contador de 7 etapas para manejar una pantalla de 7 segmentos parece un enfoque subóptimo, por las razones que usted mismo ha indicado.
jfpoilpret

1

Con un poco de trabajo (instalar un gestor de arranque diferente), hay disponibles siete líneas de E / S adicionales en Uno, en los encabezados ICSP1 y JP2. El gestor de arranque de reemplazo se llama HoodLoader2 . Le permite instalar bocetos tanto en Atmega328 como en Atmega16U2 en Uno. Tratar con múltiples procesadores sería la principal complicación del uso de este método.

En un Uno, los encabezados ICSP1 y JP2 se conectan a los pines PB1 ... PB7 del Atmega16U2. Además, el Atmega16U2 tiene aproximadamente 9 pines de E / S sin conexión a la placa de circuito. Una persona que trabaja bajo un microscopio podría conectar cables a un total de 18 pines de E / S en el 16U2, mientras deja otros tres pines de E / S conectados a sus conexiones normales.

HoodLoader2 también funciona en placas Mega.


0

Aquí hay una gran cantidad de buenas respuestas, pero si le costara su tiempo le resultaría más barato comprar un Mega.

Mi valor de 3/2-d.