Como expandir as Saídas do Arduino?
Olá tudo bem? Hoje vamos aprender a como expandir as saídas do Arduino. Um recurso muito utilizado em projetos que necessitam de muitos pinos de saída do Arduino e você não tem em mãos, um Arduino MEGA.
Tem casos também, que é necessário mais pinos que um Arduino MEGA pode fornecer (acredite, isso pode acontecer). Por este motivo, expandir as saídas do Arduino é importante.
Por isso vamos estudar elas hoje, vamos nessa?
Por que expandir as saídas do Arduino?
Então como já mencionei, a necessidade de expandir as saídas do Arduino vem em decorrência da grande necessidade de pinos para o seu projeto. Por exemplo, em aplicações que utilizem displays de LCD, de 7 Segmentos, matrizes de leds, teclados e etc. Nesse casos, a utilização dos pinos de saída para cada componente do projeto são grandes.
Então partindo deste problema, algumas pessoas diriam que uma forma de solucionar esse problema, seria comprar um Arduino com maior quantidade de pinos como o Arduino MEGA.
Porém, a compra dele, poderia aumentar muito o custo do projeto. Isso porque ele tem maior capacidade de memória e de recursos os quais não seriam utilizados, apenas iríamos utilizar seus pinos.
Devido a isso, a saída é realizar a expansão das saídas que o Arduino possui, seja ele: UNO, MEGA, NANO, etc. Sendo assim, hoje vou te mostrar sobre os shift registers, os quais realizam essa expansão no Arduino.
Eles são basicamente, CI’s que utilizam apenas 3 pinos do Arduino para controlar, de maneira rápida e precisa, o estado de até dezenas de pinos de outros componentes.
O que eu preciso saber para expandir as saídas?
Primeiro, você precisa entender o conceito. Dessa forma, vamos buscar entender então que essa expansão funciona através do deslocamento de bits, conhecido como, shift register. A ideia de “shift register” parte do circuito da imagem abaixo, onde temos quatros Flip-Flops do tipo D. Na imagem abaixo, o circuito vai funcionar da seguinte forma:
Fonte: AutoCore Robótica
- Primeiro colocamos um bit (0 ou 1) no Data (pino D) do FF0, mas esse bit só será levado ao próximo pino D do FF1, quando o clock (CLK) sofrer uma borda de descida.
- Mas, essa “borda de descida” do CLK só vai acontecer quando ele sair do estado HIGH -> LOW. Dessa forma, para realizar um shift, ou seja, deslocar esse bit colocado no Data Input, devemos sempre começar com o CLK em LOW.
- Contudo, como precisamos de uma “borda de descida” para o bit ser deslocado, sempre vamos precisar realizar a mudança de estado no pino do clock. Assim, sempre que fomos deslocar um bit, o clock precisa mudar de estado assim: LOW -> HIGH -> LOW.
Então, observe que com apenas três pinos: Data, Clock e Reset, a nossa possibilidade de saída pode ser para 4, 6, 8, infinitas saídas. Mas como nosso CI tem apenas 16 terminais, podemos ampliar de três pinos do Arduino, para oito pinos de saída. Mas esse número de saídas pode ser aumentado incrementando mais CI’s, é bem tranquilo.
Expandindo as Saídas do Arduino
Partiremos agora então, para o estudo de como realizar, na prática, todo esse conceito de deslocamento de bits. Mas antes, todos os dados técnicos informados a respeito do componente utilizado, foram retirados da sua própria folha de dados:
Então, sabendo agora como funciona o conceito de shift register, vamos iniciar o nosso estudo sobre os circuitos que podemos utilizar para expandir as saídas do nosso Arduino.
O CI que iremos utilizar será o 74HC595, um registrador de deslocamento de 8 bits. Neste CI os bits são inseridos um a um (como expliquei sobre o CLK) até completar o byte (que são 8 bits). Depois é enviado um comando para atualização das saídas (chamado de Latch).
Dessa forma, podemos utilizar ele para expandir os pinos do Arduino, para acionar relés, display LCDs, matriz de LED, etc. Mas para isso será utilizado, apenas 3 pinos do Arduino para controlar as 8 saídas.
Componentes Utilizados
Esquema de Ligação do 74HC595
O circuito que vamos desenvolver para testar essa configuração se encontra logo abaixo. Nele vamos controlar 8 leds apenas utilizando 3 pinos do nosso Arduino.
Fonte: AutoCore Robótica
Observe portanto, que será no pino 14 (SI – Sinal de Entrada) onde inserimos o bit a ser deslocado, já no pino 11 será o pulso de clock e, quando os 8 bits forem inseridos é dado um pulso no pino 12. Isso vai escrever na saídas e mostrar a sequência de bits nos leds. Vamos agora analisar o código que irá controlar essa saída dos bits.
Código do Projeto Comentado
/* ======================================================================================================== Projeto: Controle de Registrador de Deslocamento 74HC959 Autor: Danilo Nogueira Data: 06/10/2018 // ======================================================================================================== */ // --- Ligação dos Pinos --- #define clk 8 #define latch 7 #define data 9 // ======================================================================================================== // --- Variáveis Globais --- byte control_led = 0x00; // ======================================================================================================== // --- Iniciando o Setup --- // Como iremos escrever nos pinos do 74HC595, // Então eles deverão ser uma saída. void setup() { pinMode(clk, OUTPUT); pinMode(data, OUTPUT); pinMode(latch, OUTPUT); } // ======================================================================================================== // --- Loop Infinito --- void loop() { // Aqui estamos controlando os leds individualmente, // Basta colocar o valor em binário e ele será // Representado nos leds control_led ^= 0b10000010; // num = num xor 10000010 (Experimente mudar esse valor) // Esse comando interno do Arduino, faz todo aquele processo // Explicado sobre o CLK e Pino D lembra? // Assim, é ele que escreve na saída, o valor em binario que definimos shiftOut(data, clk, LSBFIRST, control_led); // 10000010 // Aqui, controlamos a latch para el permitir a escrita // Dos dados e o envio dele aos leds digitalWrite(latch, LOW); digitalWrite(latch, HIGH); digitalWrite(latch, LOW); delay(500); } // ========================================================================================================
Analisando o Código
Em nosso código de hoje, temos dois pontos que são muito importantes. Primeiro, observe que criamos uma variável global (ou seja, definimos ela antes do void setup).
byte control_led = 0x00;
Mas por que fazer isso? Eu te explico! No void loop() observe que eu utilizei ela da seguinte forma:
control_led ^= 0b10000010;
Porque fiz isso? Em muitos projetos, onde buscamos expandir as saídas do Arduino, queremos controlar tais saídas de forma independente e não sequencialmente. Assim, nesta linha de código, você pode controlar as saídas de forma independente. Sabia disso?
Então, basta você apenas escrever o byte completo, dizendo qual saída será acionada, e elas serão acionada individualmente ao mesmo tempo.
Contudo, temos também a opção de controlar as saídas sequencialmente. Utilizando para isso, um comando que já vem implementada na IDE da Arduino:
shiftOut(data, clk, LSBFIRST, control_led);
Esse comando vai facilitar sua vida e ainda, diminuir muito as linhas de seu código na hora de expandir as portas do Arduino. Isso porque, esse comando faz todo aquele “passo a passo” que eu expliquei sobre o funcionamento dos flip flop lembra?
Mas tudo isso, acontece em apenas uma linha de código. Então, o que ele vai fazer é transmitir um byte. Porém, ele faz isso enviando um bit por vez. Ou seja, faz o envio sequencialmente.
Então é assim, ela vai trabalhar da seguinte forma:
shiftOut(dataPin, clockPin, bitOrder, value)
Cada argumento que esse comando vai receber tem sua particularidade, veja:
- dataPin: Valor do pino no qual serão enviados cada bit;
- clockPin: Valor do pino a ser pulsado uma vez que o pino data estiver com o bit a ser transferido, como já explicamos;
- bitOrder: Aqui vamos dizer em que ordem será recebido os bits; pode ser MSBFIRST ou LSBFIRST. Respectivamente, será o primeiro o bit mais significativo (Most Significant Bit First), ou o primeiro bit menos significativo (Least Significant Bit First).
- value: o valor a ser transferido (em byte).
Então por fim, em nosso código estamos fazendo o controle das saídas independente. Uma vez que o argumento value utilizado no comando shiftOut, é a nossa variável global criada para controlar byte a byte.
Resultado do Projeto
Para finalizar, deixo para você um vídeo do canal da AutoCore no Youtube. Nele, estamos mostrando o resultado do código desenvolvido.
Mas e ai? Gostou? Caso tenha ficado algo incompleto para você, deixe seu comentário
Dicas? Dúvidas? Idéias de post? Críticas? Só comentar também
Forte abraço!
Puxa vida, muito obrigado por compartilhar tanto conteúdo de valor. Vou continuar seguindo o blog / site e compartilhando
Olá Flávio! Agradecemos o seu feedback, fique sempre de olho no nosso blog, estamos sempre criando conteúdo de qualidade para nossos seguidores.
Até a próxima!