Texto iniciado por Carlyn Maw e Tom Igoe, Nov 2006
Haverá vezes em que você sentirá falta de mais pinos na sua placa Arduino e precisará de uma expansão, com registradores de deslocamento. Este exemplo baseia-se no 74HC595. Sua folha de dados explica que se trata de "um registrador de deslocamento de 8 bits com entrada serial e saída serial ou paralela, com latches de saída; com três estados". Em outras palavras, pode-se usá-lo para controlar 8 saídas de uma vez e para tal usa-se apenas alguns poucos pinos de seu microcontrolador. Pode-se encadear vários registradores de deslocamento, de forma a expandir ainda mais o número de saídas possíveis. (Caso deseje, procure por outros chips com 595 ou 596 contidos no código do modelo, há vários deles. O STP16C596, por exemplo, pode acionar 16 LEDs e substitui os resistores de pull-up por fontes de corrente constante, integrados a eles).
Isto tudo funciona graças à chamada comunicação serial síncrona. Aplica-se uma sequência de pulsos, cada um a representar um bit, de forma que ao final teremos comunicado um byte inteiro de dados ao registrador. É pela aplicação de pulsos ao pino 2, que é o pino de clock, que você delineia os bits. Esse tipo de comunicação contrasta com a comunicação serial assíncrona usada pela função Serial.begin(), que baseia-se na negociação de uma velocidade de transmissão específica entre o emissor e o receptor. Uma vez transmitido todo o byte ao registrador, as mensagens HIGH e LOW atribuídas a cada bit são entregues a cada pino respectivo de saída. Esta é a parte chamada de saída paralela - todos os pinos apresentam o byte todo de uma só vez.
A parte chamada de saída serial é atribuída a um pino extra do registrador, que passa a informação ipsis litteris vinda do microcontrolador. Isso quer dizer que pode-se transmitir 16 bits (2 bytes) de uma tacada só, sendo que os primeiros 8 bits vão atravessar o registrador e atingirão um segundo registrador, por exemplo, onde serão disponibilizados. Isso será visto no segundo exemplo abaixo.
A parte do "três estados" refere-se ao fato de podermos configurar os pinos de saída como HIGH, LOW e alta impedância. Ao contrário dos estados HIGH e LOW, o de alta impedância não pode ser concedido aos pinos individualmente, mas apenas a todos os pinos juntos. Isso é uma situação bastante especial - imagine um vetor de LEDs controlados por mais de um microcontrolador, dependendo de modos de configuração no seu projeto. Nenhum exemplo abaixo utiliza-se dessa característica do registrador de deslocamento e você provavelmente não precisará de um chip que apresente saídas de três estados.
Aqui está uma tabela que explica a pinagem (adaptada da folha de dados da Phillips)
Pinos 1-7, 15 | Q0-Q7 | Pinos de saída | |
Pino 8 | GND | Terra | |
Pino 9 | Q7' | Saída serial | |
Pino 10 | MR | Master Reclear, ativo em LOW | |
Pino 11 | SH_CP | Pino de clock do registrador de deslocamento | |
Pino 12 | ST_CP | Storage Register Clock Pin (pino de latch) | |
Pino 13 | OE | Output Enable, ativo em LOW | |
Pino 14 | DS | Entrada de dados seriais | |
Pino 16 | VCC | Pino de alimentação positiva |
O primeiro passo é estender o Arduino com o uso de um registrador de deslocamento.
1) Ligar
Faça as seguintes conexões:
Essa montagem torna ativos todos os pinos de saída e sempre endereçáveis. Um porém dessa configuração é que acaba-se com as luzes ligadas de forma arbitrária toda vez que o circuito for acionado pela primeira vez e antes que o programa comece a rodar. Pode-se resolver isso com o controle dos pinos OE e MR, mas aí teríamos que usar pinos adicionais da placa Arduino.
2) Conectar ao Arduino
A partir daqui, chamaremo-nos, respectivamente, de dataPin, clockPin e latchPin. Repare no capacitor de 0,1 uF no latchPin, se ocorrerem irregularidades ao pulsar o latchPin, utilize o capacitor para filtrar o ruído.
3) Adicionar 8 LEDs
Neste caso, conecte o catodo (terminal curto) de cada LED a um terra comum e o ânodo (terminal longo), à saída respectiva do registrador de deslocamento. Chama-se o registrador de deslocamento de fonte de corrente quando se alimenta os LEDs da maneira explicada. Alguns registradores de deslocamento não podem fazê-lo, mas sim drenar corrente; nesse caso, basta inverter os terminais dos LEDs. Verifique se a folha de dados de seu componente eletrônico diz que ele pertence à série 595. Não se esqueça dos resistores de 220 ohms em série, para proteger os LEDs contra sobrecarga.
Diagrama esquemático do circuito
O código
Aqui estão três códigos-exemplos. O primeiro é apenas um código de "olá mundo", que exibe o valor de um byte de 0 a 255. O segundo programa acende um LED por vez, e o terceiro circula através de um vetor.
Tabela-verdade do registrador 74HC595 | Diagrama de tempo
Os códigos baseiam-se em duas porções de informação presentes na folha de dados: o diagrama de tempo e a tabela-verdade. A tabela-verdade nos diz que, basicamente, tudo o que é de importante ocorre na borda de subida do clock. Quando o clockPin vai de LOW para HIGH, o registrador de deslocamento lê o estado do dataPin. Conforme os dados são deslocados através do chip, eles são salvos em uma memória interna. Quando o latchPin vai de LOW para HIGH, os dados saem dessa memória interna e vão realmente para os pinos de saída, acendendo os LEDs.
Exemplo 1.1 Olá mundo
Exemplo 1.2 Um por um
Exemplo 1.3 Vetor
Neste exemplo, adiciona-se mais um registrador de deslocamento e, assim, dobra-se a quantidade de pinos de saída sem alterar a quantidade de pinos usados no Arduino.
1) Adicionar um segundo registrador de deslocamento
A partir do exemplo anterior, instale um segundo registrador de deslocamento na protoboard e puxe os fios de alimentação e terra.
'''2) Conectar os dois registradores Duas conexões simplesmente estendem os mesmos sinais de clock e de latch, vindos do Arduino, ao segundo registrador de deslocamento (fios amarelo e verde). O novo fio azul vai do pino saída serial (pino 9) do primeiro registrador à entrada serial de dados (pino 14) do segundo registrador.
3) Incluir um segundo conjunto de LEDs Neste caso, adicionei LEDs verdes para que, quando se fizer a leitura do código, fique claro qual byte foi para qual conjunto de LEDs.
Diagrama esquemático do circuito
O código
De novo, temos três exemplos. Se você for curioso, pode testar os programas do exemplo anterior com a nova montagem do circuito, para ver o que acontece.
Exemplo 2.1 Contador binário duplo Há apenas um linha extra de código em relação ao Exemplo 1.1. Ele envia um segundo byte. Isto força o primeiro registrador, o que conecta-se diretamente ao Arduino, a deixar passar o primeiro byte, levando-o ao segundo registrador, acendendo os LEDs verdes. O segundo byte acende nos LEDs vermelhos.
Exemplo 2.2 2 bytes, um por um Se compararmos este código com o código similar do Examplo 1, veremos que um pouco mais deve ser mudado aqui. A função blinkAll() mudou para blinkAll_2Bytes(), para refletir o fato de que agora há 16 LEDs a serem controlados. Além disso, na versão 1 os pulsos do latchPin foram colocados dentro das subfunções lightShiftPinA() e lightShiftPinB(). Aqui, elas precisam ser recolocadas no loop(), para que cada subfunção rode duas vezes em uma tacada só, uma vez para os LEDs verdes e outra para os vermelhos.
Exemplo 2.3 Dois vetores
Tal como em 2.2, o Exemplo 2.3 também aproveita-se da nova função blinkAll_2bytes(). A grande diferença com relação ao Exemplo 1.3 é que, em vez de termos uma única variável "data" e um único vetor "dataArray", agora há também dataRED, dataGREEN, dataArrayRED, dataArrayGREEN. Isto significa que a linha
data = dataArray[j];
torna-se
dataRED = dataArrayRED[j]; dataGREEN = dataArrayGREEN[j];
e
shiftOut(dataPin, clockPin, data);
torna-se
shiftOut(dataPin, clockPin, dataGREEN); shiftOut(dataPin, clockPin, dataRED);