Existe uma maneira de ter mais de 14 pinos de saída no arduino?

52

É possível ter mais de 14 pinos de saída no Arduino? Estou trabalhando em um projeto no qual preciso acender vários LEDs individualmente. Eu só tenho um Arduino Uno e não quero um Mega.

JVarhol
fonte
No espírito da expansibilidade, o I2C é uma opção do Arduino?
Chris O
@ChrisO O que você quer dizer com I2C? Porque pelo que entendi, os registros Shift seriam considerados I2C.
JVarhol
Oh, faça-me responder à minha pergunta ;-) Aqui está um artigo da Wikipedia sobre este padrão de ônibus. Acabei de encontrar algum suporte da Wire lib para I2C, para que você possa conectar uma cadeia I2C ao seu Uno.
Chris O
@JVarhol Não é bem assim. I2C, também conhecido como TWI, é uma interface de 2 fios, enquanto o SPI pode ser considerado uma interface de 3 fios.
Klaus-Dieter Warzecha
11
@JVarhol você já selecionou uma solução para o seu projeto? Se sim, seria útil editar sua pergunta e aceitar a resposta que corresponde (ou é a mais próxima) à sua solução.
Jfpoilpret

Respostas:

50

Uma maneira comum de expandir o conjunto de pinos de saída disponíveis no Arduino é usar registros de deslocamento como o IC 74HC595 ( link para a folha de dados ).

Você precisa de 3 pinos para controlar esses chips:

  1. Relógio
  2. Robusto
  3. Dados

Em um programa, você passa os dados um bit de cada vez para o shift shift usando o comando shiftOut () , da seguinte maneira:

shiftOut(dataPin, clockPin, data); 

Com esse comando, você define cada uma das 8 saídas no 595 IC com os 8 bits na datavariável.

Com um 595, você ganha 5 pinos (8 no IC, mas gasta 3 para conversar com ele). Para obter mais saídas, você pode conectar uma série de 595 em série, conectando seu pino de saída serial ao pino de dados do próximo. Você também deve conectar os pinos do relógio e da trava de todos os 595 ICs.

O circuito resultante (usando um 595) ficaria assim:

Circuito usando o registro de 595 turnos

A figura acima foi retirada desta página da codeproject.com :

O pino de trava é usado para manter as saídas 595 estáveis ​​enquanto você transfere dados para ele, da seguinte forma:

digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, data); 
digitalWrite(latchPin, HIGH);
Ricardo
fonte
11
Thx, esqueceu de incluir como um registro de turno funciona. Eu tinha planejado, mas tive que me afastar do meu comp e, quando voltei, ele me escapou. :)
JVarhol
Não tem problema, é por isso que somos uma comunidade. Nós complementamos as respostas um do outro. Mas é bom que você tenha adicionado também algumas boas dicas em sua resposta, especialmente sobre o escudo EZ-Expander. Ele permite que aqueles que não podem fabricar seus PCBs facilmente expandam o número de portas disponíveis para eles.
Ricardo
2
Além disso, facilita a programação, você não precisa mudar os dados e pressionar o relógio e ativar a trava. Conheço o escudo há algum tempo e acho que é perfeito para iniciantes. O melhor é que, como o código é de código aberto, você pode usá-lo mesmo que não esteja usando o escudo de verdade, mas tenha sua própria placa ou usando uma placa de ensaio.
JVarhol
11
Não esqueça que você pode vinculá-los em linha (teoricamente) indefinidamente, para que 2 registros de 8 bits possam se tornar um de 16 bits.
Scott M.
Obrigado! Aqui está um link de arquivo para a descrição incrível codeproject no caso da ligação nunca vai para baixo archive.fo/1uvPE
Akhmed
27

Existem duas maneiras de obter mais pinos de um arduino.

A primeira maneira é usar os pinos analógicos como pinos de saída digital, o que é realmente fácil de fazer. Tudo o que você precisa fazer é consultar A0-A5 como pinos 14,15,16,17,18,19. Por exemplo, para gravar alto no pino A0, basta usar digitalWrite (14, HIGH).

A outra maneira de obter mais pinos do Arduino é usando um Shift Register. Para fazer isso, recomendo usar o EZ-Expander Shield , que permite usar o digitalWrite ([20-35], HIGH) ao importar a Biblioteca do EZ-Expander. Essa blindagem, no entanto, permite apenas que os pinos sejam usados ​​apenas como saídas e usa os pinos 8,12 e 13 para controlar os registros de deslocamento.

O melhor é que você pode usar os dois métodos acima juntos, sem problemas.

JVarhol
fonte
3
De acordo com a referência do Arduino, você pode realmente usar os A0- A5identificadores diretamente, em vez de usar os números 14-19. Por exemplo digitalWrite(A0, HIGH),.
Peter Bloomfield
3
@ PeterR.Bloomfield Ambos estão corretos, no entanto, recomendo o A0-A5 por simplicidade e facilidade de leitura. Não é grande coisa com um LED piscando, mas quando você tem grandes projetos, pouco se acrescenta hábitos.
Anonymous Penguin
2
Na verdade, embora ambos façam o trabalho nas placas UNO e compatíveis, digitalWrite(A0)é mais correto do que digitalWrite(14)porque o primeiro sempre será mapeado para o pino físico (analógico) correto. Em uma placa diferente, pin 14pode de fato não estar A0, por exemplo, pin 14no MEGA é Serial3 TXe não influenciará o pino analógico que você procura . ou seja, se estiver usando digitalWriteum pino analógico, use a referência A0- A5.
Madivad
18

Se você deseja acionar LEDs, também pode usar um MAX7219 que pode acionar 64 LEDs, sem circuitos extras (não é necessário que o transistor amplifique o sinal).

A condução de um MAX7219 requer apenas 3 pinos de saída no Arduino. Além disso, você pode encontrar algumas bibliotecas do Arduino para isso.

Você também pode encadear vários deles, se precisar alimentar mais de 64 LEDs.

Usei-o com sucesso para vários displays de LED de 7 segmentos.

Desvantagem: é caro (cerca de US $ 10).

jfpoilpret
fonte
Esqueci o MAX7219, Obrigado por postar!
JVarhol
384 LEDs ... uau! Mais dois pinos para inferência USB. Você quer saber que tipo de bugiganga irritante você pode criar (com uma fonte de alimentação suficiente).
Anonymous Penguin
17

Você pode usar o Charlieplexing . Com esta técnica, você pode direcionar diretamente os n*(n-1)LEDs de n pinos. Assim, com 3 pinos, você pode acionar 6 LEDs, 4 pinos - 12 LEDs, 5 pinos - 20 LEDs e assim por diante.

Exemplo:

Seis LEDs em 3 Pins

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

insira a descrição da imagem aqui

Você pode ver um tutorial melhor aqui .

Daniel Grillo
fonte
Uma coisa a notar é que essa técnica permite controlar mais leds, mas não simultaneamente.
21815 kontur
11
@ kontur sim, você está certo. Mas em termos de persistência da visão, você pode considerar que são. A pergunta não tem esses detalhes.
Daniel Grillo
Charlieplexing não é a única maneira de multiplexar LEDs sem usar registros de turno.
linhartr22
11
@ linhartr22 NUNCA disse que é o único caminho. Charlieplexing é apenas uma solução comum para esse problema. E minha resposta foi a sétima. Então, outras possibilidades já haviam se mostrado antes.
Daniel Grillo
@DanielGrillo Eu deveria ter sido mais específico e explicado como a multiplexação de colunas e linhas, normalmente usada em cubos de LED, pode ser feita sem o registro de turnos e sem as limitações do Charlieplexing. Uma matriz de coluna de 4x4 linhas pode controlar individualmente 16 leds com 8 linhas de E / S. Um cubo 4x4x4 pode controlar individualmente 64 leds com 12 linhas de E / S (possível mesmo em um Uno usando o Analog A0-A5 como linhas digitais).
Linhartr22
13

I 2 C (fio)

Você pode usar o protocolo I 2 C (biblioteca de fios) para conectar-se a outros dispositivos, como expansores de porta. Por exemplo, o MCP23017.

Eu usei um desses chips para conectar a uma placa de LCD. O MCP23017 possui 16 portas, que podem ser configuradas como entradas ou saídas. Como entradas, eles podem gerar interrupções, se desejado.

Exemplo de conexão de 13 desses 16 ao LCD:

MCP23017 conectado à tela LCD

Agora nos conectamos ao Arduino usando apenas 2 fios (SDA / SCL), além de potência e terra:

MCP23017 conectado ao Arduino


Alguns fabricantes terceirizados criaram placas com 4 x MCP23017, o que fornece 64 entradas / saídas:

Placa de centopéia


Multiplexadores

Você pode usar multiplexadores analógicos como o 74HC4051 (8 portas) ou o 74HC4067 (16 portas) para conectar um pino a uma das portas 8/16 (mas apenas uma por vez), desta forma:

Multiplexador 74HC4051

Eles são bidirecionais e podem ser usados ​​como expansores de entrada ou saída.


SPI com 74HC595

Usando o SPI, você pode enviar dados seriais rápidos para um registro de turno, como o 74HC595. Estes podem ser encadeados juntos. Neste exemplo, estou controlando 32 LEDs com apenas 3 pinos de E / S (MOSI / MISO / SCK), além de potência e terra.

74HC595 dirigindo 32 LEDs


Encontrei dentro de um sinal comercial de LED que os 72 LEDs eram acionados por chips 74HC595.

Rolagem sinal de LED

Isso tinha 9 chips dirigindo as colunas (9 x 8 = 72 LEDs) e um chip dirigindo as linhas, em uma configuração multiplexada.


SPI com MAX7219

Se você quiser apenas conduzir LEDs, geralmente pode multiplexá-los. O MAX7219 simplifica isso ao ser projetado para acionar matrizes de LED, por exemplo, displays de 7 segmentos:

MAX7219 com display de 7 segmentos

Ou matrizes de 64 LEDs:

MAX7219 com matriz de 64 LEDs

Nos dois casos, eles podem ser encadeados juntos, por exemplo:

Cadeia em série MAX7219

Todos esses exemplos usam apenas 3 pinos do Arduino (MOSI / MISO / SCK), além de potência e terra.


SPI com MCP23S17

O expansor de portas de 16 portas mencionado anteriormente (MCP23017) também vem em uma variante SPI (MCP23S17), que faz coisas praticamente idênticas. Ele usa mais um fio, mas seria mais rápido.


Outros protocolos

As tiras de LED (como as NeoPixel) têm seus próprios protocolos. Houve um post no Youtube de Josh Levine, onde o autor dirigiu mais de 1000 pixels com um Duemilanove!


Referências

Nick Gammon
fonte
12

Os registros de turnos foram mencionados em outras respostas e são definitivamente uma excelente opção para muitos projetos. Eles são baratos, simples, moderadamente rápidos e geralmente podem ser encadeados para adicionar mais saídas. No entanto, eles têm a desvantagem de que geralmente precisam de uso exclusivo de vários pinos (entre 2 e 4, dependendo de como você os configura).

Uma alternativa é usar expansores de porta mais avançados, como o MCP23017 e o MCP23S17 de 16 bits . Eles suportam I2C e SPI, respectivamente, o que significa que você pode colocá-los em um barramento com vários outros dispositivos (potencialmente de tipos diferentes). Cada dispositivo no barramento pode ser endereçado individualmente, o que significa que você só precisa de 2 ou 3 pinos para conversar com todos eles. As velocidades de atualização são geralmente extremamente rápidas, portanto, é improvável que você experimente uma latência significativa (ou seja, atrasos na transmissão) em um projeto do Arduino.

Em um nível baixo, o uso de I2C ou SPI é substancialmente mais complicado do que um simples registro de turno. No entanto, existe um código de biblioteca para o Arduino cuidar disso para você. Veja esta pergunta, por exemplo: Como uso dispositivos I2C com o Arduino?

Peter Bloomfield
fonte
Uau, eu nunca soube disso, thx, vou olhar neles!
JVarhol
Você pode usar o I2C para controlar os LEDs?
Pro Q
11
@ProQ Você não pode controlar os LEDs padrão diretamente usando o I2C. No entanto, é possível obter alguns produtos de LED que possuem um driver I2C embutido. Isso geralmente é para produtos com muitos LEDs, como tiras ou matrizes.
Peter Bloomfield
8

Além da resposta de Ricardo , o que a Wikipedia afirma no turno registra :

Um dos usos mais comuns de um registrador de deslocamento é converter entre interfaces seriais e paralelas. [...] os registradores SIPO geralmente são anexados à saída dos microprocessadores quando são necessários mais pinos de entrada / saída de uso geral do que os disponíveis. Isso permite que vários dispositivos binários sejam controlados usando apenas dois ou três pinos, mas mais lento que a E / S paralela.

No artigo Ricardo vinculado, você pode ver o diagrama do registro de turnos.

Diagrama do registro de turnos

O que acontece aqui é que você coloca os dados dos 8 pinos em uma sequência e, para cada relógio, o registro de deslocamento muda (mova os dados binários de cada trava para a próxima) até que "faça um círculo", ou seja, o primeiro bit chega ao último pino. Os registros de mudança também têm uma entrada na qual é possível ativar / desativar a mudança, para que o status possa ser mantido depois que os dados forem deslocados para a posição. Para uma demonstração simples, veja a seguinte animação.

Animação de registro de turno

Aqui, a luz vermelha é a entrada serial e as verdes estão mostrando o estado das travas neste registro de turno SIPO simplificado . Depois que os dados mudam para o local, a mudança pode ser desativada e você pode ler os pinos. Neste exemplo, mudei para fora 10101011.

A partir desses exemplos, você pode perceber que a transferência serial será mais lenta que a paralela, porque é necessário aguardar que o registrador de deslocamento mude os bits para o seu lugar. Você terá que esperar a mesma quantidade de tiques do relógio quantos bits você deseja carregar. Essa é uma das muitas razões pelas quais você não pode encadear indefinidamente, porque o carregamento levaria uma eternidade.

totymedli
fonte
11
+1 para informações adicionais E para o GIF animado e seu efeito didático! Onde você encontrou o GIF? Ou você conseguiu?
Ricardo
11
@ Ricardo Criei o circuito com a Digital Works, depois imprimo a tela, edite, animador de gif.
totymedli
6

Como você já escreveu, você pode usar todos os pinos, incluindo TX e RX como saída digital. Eu fiz isso há um tempo atrás para um demonstrador e gravei um vídeo - 20 LEDS em 20 pinos - desse projeto absurdo.

Conforme descrito por Peter R. Bloomfield aqui , é necessário desconectar o TX e o RX para fazer o upload. Além disso, você está sem pinos para ler os sensores para uma possível interatividade e precisa garantir que o limite total de corrente não seja atingido. Para não esquecer que você está limitado a leds de 5V se você os direcionar diretamente com o seu Arduino.

O uso de registros de turno em geral e o 595, descrito por Ricardo, é altamente recomendável.

  • Eles são baratos!
  • É bastante fácil fazer cascata com eles.
  • Muita velocidade pode ser obtida quando você usa o hardware-SPI.

Eu os usei há um tempo atrás quando percebi a parte de solda e programação do Kawaii me (o texto do link está em alemão) do artista de reciclagem Dominik Jais .

Aqui, apenas um monte de 595 foram usados ​​para exibir um display de 8x11 leds. Como os leds foram cortados a partir de uma faixa de 12V SMD, era necessária uma fonte de alimentação adicional e algumas matrizes UDN2803A Darlington, conectadas aos pinos de saída dos registros de mudança.

Outros métodos gerais incluem o uso de expansores de porta PCF8574 (A) de 8 bits, que são controlados através do barramento I2C.

Enfim, eu daria uma chance aos registradores de turno 595.

Se você precisar controlar alguns leds RGB, no entanto, convém procurar soluções mais especializadas. Alguns leds RGB vêm com seu próprio WS2812 . Essas peças finas podem ser conectadas em cascata (barramento de 1 fio) e são endereçadas através de sua posição na corrente.

Klaus-Dieter Warzecha
fonte
3

Se é tudo sobre LEDs, o que dizer das tiras de LED WS2812B, ou apenas dos próprios chips de driver? Você pode controlar um número praticamente ilimitado de LEDs usando apenas um pino!

Embora as pessoas estejam acostumadas a isso em tiras, elas estão disponíveis como LEDs independentes (conhecidos como pixels neo no Adafruit). Ou, se você estiver dirigindo apenas uma cor, cada chip WS2811 poderá controlar 3 LEDs usando cada uma das saídas RGB para um único LED cada.

Recentemente, criei um projeto que utiliza 5 desses LEDs: Porta1 aberta / fechada, Porta2 aberta / fechada, motor1 ativo, motor2 ativo e potência. Os LEDs "ativos" são de dupla finalidade, pois eu tenho o vermelho sendo a entrada do motor ativo e o verde sendo a bandeira ativa dentro do Arduino.

Sendo que, com 1 pino e a biblioteca instalada, você pode controlar qualquer número de LEDs

Madivad
fonte
2

Não reivindico esse método sozinho, mas encontrei esse truque na página da web MUX-DEMUX: CD4051 Parlour Tricks

Qualquer que seja o método escolhido para acionar saídas ou ler entradas (registradores de deslocamento, multiplexadores ou o uso direto direto dos próprios pinos do Arduino), você pode DOBRAR o número de saídas ou entradas por meio do uso inteligente de pares de circuitos paralelos (para formar um duplo banco de entrada ou saída ), empregando diodos em sentidos opostos em cada ramo paralelo e alternando as entradas / saídas para alta e baixa.

Para ilustrar o método para saídas (neste caso, LEDs, observe que os diodos extras não são necessários):

Banco LED

Se você considerar o par de LEDs neste exemplo um "banco" e deseja acender o LED_0, precisará definir o PIN 17 como ALTO e o PIN 18 como BAIXO. (Os números dos pinos são confusos, mas coincidem com o exemplo mais recente comigo). Para acender o LED_1, basta reverter os PINS. A natureza do diodo dos LEDs impede que a corrente flua na direção oposta, mantendo o outro desligado.

Para ilustrar o método para entradas (CdSs, neste caso, observe que os diodos extras são necessários):

Banco CdS

Isso fica um pouco mais complicado se você deseja fazer uma leitura analógica em um sensor de luz CdS. Primeiro, você precisa adicionar um diodo a cada sensor para controlar o fluxo. Segundo, como você está lendo valores, precisa puxar as entradas para cima ou para baixo para impedir que elas flutuem. Sendo uma pessoa preguiçosa, vou puxá-los para o alto usando os resistores de pull-up internos. Para ler CdS_0, você define o modo PIN 17 como OUTPUT e o valor para LOW. Isso torna o terreno. Em seguida, defina o modo PIN 18 como ENTRADA e ALTO para ativar o resistor de pull-up. Agora você está pronto para ler o PIN 18 (também conhecido como pino analógico 4). Para acessar o outro sensor, basta alternar entre os modos e saídas.

Portanto, se você tiver um multiplexador de 8 portas CD4051, usando 5 pinos no Arduino (em vez dos 3 habituais), poderá obter 16 entradas ou saídas, ou uma mistura dos dois.

16 saídas / entradas usando um CD4051

Da mesma forma, se você possui um multiplexador 4067 de 16 portas, pode obter 32 entradas ou saídas ou uma mistura dos dois.

Um esboço de exemplo seria:

/*
 * 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 eu disse na primeira linha, a explicação completa pode ser encontrada em MUX-DEMUX: CD4051 Parlour Tricks

Greenonline
fonte
1

Para um projeto de classe, usei um CD4024 e dois pinos Arduino para direcionar uma tela de 7 segmentos.

Existem algumas ressalvas nessa abordagem. Por exemplo, para escrever um highvalor na primeira saída de um contador de ondulações, é necessário a resete alternar o pino do relógio duas vezes. Mas se você deseja gravar highem todos os n pinos, é necessário alternar o pino do relógio 2 n vezes e, durante esse período, todos os outros pinos são ativados e desativados constantemente.

Se seu aplicativo pode lidar com essas limitações e você não tem pinos, é outra opção.

Resposta bônus: existem muitos exemplos de entradas de multiplexação aqui , muitos dos quais também se aplicam a saídas de multiplexação.

hoosierEE
fonte
Usar um contador de 7 estágios para direcionar uma exibição de 7 segmentos parece uma abordagem abaixo do ideal, pelos motivos que você indicou.
Jfpoilpret
1

Com um pouco de trabalho (instalando um gerenciador de inicialização diferente), outras sete linhas de E / S estão disponíveis em um Uno, nos cabeçalhos ICSP1 e JP2. O carregador de inicialização de substituição é chamado HoodLoader2 . Ele permite que você instale esboços no Atmega328 e no Atmega16U2 em um Uno. Lidar com múltiplos processadores seria a principal complicação do uso desse método.

Em um Uno, os cabeçalhos ICSP1 e JP2 se conectam aos pinos PB1 ... PB7 do Atmega16U2. Além disso, o Atmega16U2 possui cerca de 9 pinos de E / S, sem conexão com a placa de circuito. Uma pessoa que trabalha sob um microscópio pode conectar cabos a um total de 18 pinos de E / S na 16U2, deixando três outros pinos de E / S conectados às suas conexões comuns.

HoodLoader2 também funciona em Mega boards.

James Waldby - jwpat7
fonte
0

Há muitas boas respostas aqui, mas se você custasse seu tempo, seria mais barato comprar um Mega.

Meu valor de 2/2 d.

Jim
fonte