Manual
do
Maker
.
com
Tirar I/O do Raspberry tem limites, exceto se esteja utilizando o barramento I²C com algo como o PCF8574 no Raspberry. Essa belezinha tem 8 bits para leitura e escrita, endereçável através de jumpers e com um baixíssimo consumo. Em contrapartida, ele empurra apenas 100uA nos pinos, o que é insuficiente para "draivar" relés, por exemplo (exceto o circuito tenha sido projetado para esse propósito). Em um próximo artigo vou exibir o procedimento para contornar essa situação, cuja solução aprendi com meu chefe recentemente.
Se você precisa configurar o I²C previamente, leia esse outro tutorial que escrevi exclusivamente para esse propósito, diminuindo assim o tamanho do texto para os próximos artigos relacionados ao assunto.
O artigo de hoje tem o propósito de estrelar apenas esse dispositivo, por isso, sigamos.
Tenho visto umas coisas meio absurdas em tutoriais, como por exemplo pessoas praticamente jurando a compatibilidade de alguns dispositivos com 5V sendo que o datasheet diz que o máximo permitido para um determinado dispositivo é 4.5. Po isso que mesmo deixando aqui algumas características, em quase todos os artigos eu deixo também o link do datasheet, que traz a informação essencial para manter vivo um dispositivo, além de que algumas vezes traz até um código de exemplo.
O datasheet do PCF8574 é esse.
Esse carinha não consome nada, 10uA apenas. Com isso, você poderá interligar até 8 deles sem se preocupar com a corrente. No meu caso específico, o alimento pelo 3.3V porque estou em um projeto que impera esse nível lógico e de tensão para alimentação, então, enquanto escrevo o artigo fico mais intimo do dispositivo.
Esse dispositivo possui um pino para interrupção open-drain. Se você utilizá-lo em um dispositivo que ofereça interrupção real (porque a do Raspberry não o é), prefira utilizá-la invés de fazer polling.
Diz o datasheet (e assim deve ser, afinal, é o documento oficial) que ele faz o letch com corrente suficiente para "draivar" um LED. Talvez por um mero acaso, no projeto que implementamos na empresa ele não tinha "sustância" nem para acionar um optocoupler, e com essa sorte acabei aprendendo um "pulo do gato" com meu chefe, mas isso ficará para outra ocasião.
Você pode utilizá-lo com tensões entre 2.5V e 6V. Ele tem tanto a capacidade de leitura com escrita (por isso que se chama "expansor de I/O", oras) e para utilizá-lo como output você certamente deverá casar o nível lógico para não queimar nada. Essa range de operação torna ideal o uso do PCF8574 no Raspberry.
Não é necessário utilizar direção de sinal; ler tem o mesmo efeito de escrever, por mais estranho que pareça. Ao ligá-lo, todos os pinos ficam em HIGH com corrente apenas no VCC.
O próprio datasheet exemplifica isso para ficar claro que o PCF8547 não deve ser utilizado para oferecer corrente alta, de modo que o LED vai ao VCC e ao iniciar o dispositivo, eles estarão apagados porque os pinos iniciam em HIGH. Ao baixar o pino, o LED se acende porque a corrente flui em direção ao pino.
Todas as Raspberry Pi tem o mesmo pinout, a diferença está no número de pinos. No desenho estou utilizando a RPi 2, mas serve para qualquer uma, já que os pinos estão logo no início.
Com isso, o nível lógico nos pinos de I/O são 3.3V. Se precisar de nível lógico em 5V, alimente o PCF8574 com o pino paralelo ao 3V3.
Após fazer a configuração descrita no post citado lá em cima, bem no começo, você deverá analisar se os dispositivos aparecem no sistema adequadamente. Como já citei, o I²C possibilita a "conexão à quente", de modo que não é necessário desligar o RPi para conectar ou desconectar mais dispositivos ao barramento. Tendo-os conectados, o primeiro passo é abrir o console e procurá-los no barramento:
Veja que utilzei o comando "i2cdetect -y 1", que faz a leitura do dispositivo I²C pelo arquivo descritor em /dev, para os RPi a partir do B. Se anterior a isso, utilize '-y 0' invés de 1.
Perceba também que enderecei os dispositivos sequencialmente pulando um endereço e scan do barramento tenho dispositivos no endereço 0x20, 0x22 e 0x24. Podemos ler todos os dados de um endereço específico só para testar. O 0x20 por exemplo:
Isso significa que a comunicação está ocorrendo sem problemas. Podemos fazer o acionamento de LEDs pela linha de comando.
Os módulos que estou utilizando são endereçáveis e interconectáveis, de modo que fiz uma fileira com 3 deles, mas não vou colocar 24 leds para acender. Invés disso, vou colocar 2 LEDs em cada um para mostrar alternadamente seus acionamentos.
Inicialmente, fiz por linha de comando e em um próximo post eu disponibilizo uma biblioteca que escrevi em python. Eu havia gravado o video e tudo o mais, mas a porcaria da câmera deu problema nela ou no cartão e perdi o video, então desisti de gravar para esse tutorial, mas vou deixar bem claro.
Primeiro, olhando para o dispositivo na posição que ele está na imagem, você vê os pinos de 1 a 8 e um pino de interrupção.
Pensando em binário, 8 bits lidos da forma correta (direita para a esquerda) representariam os seguintes valores:
128 - 64 - 32 - 16 - 8 - 4 - 2 - 1
Inicialmente todos os pinos estão em HIGH. Eu os conectei dessa maneira:
Mas invés de 5V, coloquei 3.3V e um resistor de 330ohms (tudo o que estava à mão).
Agora, manipulando por endereço.
Pela linha de comando, podemos facilmente testar os LEDs, seguindo a tabela de endereços:
Addr | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
0xF0 | 0x40 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 | |
0x20 | ||||||||
0x22 | ||||||||
0x24 | ||||||||
8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
Tendo os endereços em hexadecimal e decimal, basta escolher o valor do LED em qualquer uma das duas bases. Feita a escolha, utilize o comando a seguir para apagar um dos leds:
#acender todos
i2cset -y 1 0x24 0x00
#acender sequencialmente
for i in 1 2 4 8 16 32 64 128; do i2cset -y 1 0x24 $i && sleep 1;done
Com isso, todos os LEDs se acenderão e ao setar um bit específico, o respectivo LED se apagará. Se quiser apagar 2 de uma vez por exemplo o bit 4 e 5:
i2cset -y 1 0x24 $[(2**4)+(2**3)]
E se fosse ao contrário - acender os bits 4 e 5, mantendo o resto desligado:
i2cset -y 1 0x24 $[255-((2**4)+(2**3))]
Do mesmo modo, se quiser consultar o valor de um bit utiliza-se o 'i2cget', passando o endereço pretendido. O barramento I²C é incrível e esses dispositivos que possuem essa interface são muito divertidos de brincar, por isso vou extender artigos sobre I²C. Esse aqui é o mais básico, no próximo artigo relacionado vamos ver um dispositivo com uma interface bastante complexa mas que com certeza substitui um tradicional dispositivo utilizado pela galera de embarcados, espero que tenham gostado e que acompanhem os próximos artigos!
Inscreva-se no nosso newsletter, alí em cima à direita e receba novos posts por email.
Inscreva-se no nosso canal Manual do Maker Brasil no YouTube.
Próximo post a caminho!
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.