Hardware
A conexão do display é bastante simples. Uma preocupação foi quanto ao fato do processador do Rasp Pi trabalhar com 3.3V. Inicialmente eu estava pensando em alimentar o display também com 3.3V (o que requer dois capacitores), mas eu lembrei que no I2C os dispositivos nunca colocam uma tensão alta na via; eles conectam o sinal ao terra ou o deixam desconectado. A tensão alta é gerada por resistores de pull-up. Portanto, basta alimentar o display com 5V e ligar os resistores de pull-up ao 3.3V. Melhor ainda, o Raspberry já tem os resistores internamente, o que reduz o circuito a umas poucas conexões:
Software - SO
É aqui onde as coisas se complicam um pouco. Por default, o Raspbian (que é o OS que usei) não habilita o I2C, liberando os pinos correspondentes para GPIO. Existe muita documentação a respeito da habilitação do I2C na web, mas esta parte sofreu várias mudanças desde o lançamento do Rasp Pi e muita coisa está desatualizada.
Para começar, ocorreu uma mudança de hardware. O Raspberry Pi original (com 256M de Ram) usava o port I2C0 do processador, as versões seguintes usam o I2C1. Vou usar aqui sempre I2C1, lembre-se de mudar se estiver usando um Rasp Pi antigo.
Para o I2C funcionar nas versões mais recentes do Raspbian é necessário que o Linux carregue dois módulos (i2c-bcm2708 e i2c-dev). Isto é comandado listando estes módulos em /etc/modules e habilitando os dispositivos i2c no Device Tree através do arquivo /boot/config.txt.
Em teoria, o raspi-config faz isto para nós. Basta executá-lo (com sudo), escolher Advanced Options, I2C, Yes e Yes. Para mim faltaram o i2c-dev em /etc/modules e o dtparam=i2c1=on no config.txt. A Adafruit tem um bom tutorial a respeito.
Para facilitar o uso do I2C, instale dois pacotes:
sudo apt-get install python-smbus i2c-tools
Agora é só rebootar
sudo reboot
Após o boot podemos fazer um teste:
sudo i2cdetect -y 1
Isto irá listar os endereços dos dispositivos ligados ao I2C; no caso do display será apresentado o endereço 0x3e.
pi@raspberrypi ~ $ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3e -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
Como isto funciona? Sempre que um dispositivo é endereçado ele deve confirmar através de um NAK (transmitir um 0). O i2cdetect testa um a um os 127 endereços possíveis e verifica quais foram respondidos.
Neste ponto é necessário usar o sudo para ter acesso ao i2c. Podemos simplificar isto colocando usuário pi no grupo i2c e dando permissão de acesso a este grupo:
sudo adduser pi i2c sudo echo "SUBSYSTEM==\"i2c-dev\", GROUP=\"i2c\", MODE=\"0666\"" >> /etc/udev/rules.d/99-i2c.rules sudo reboot
Software - Aplicação
Para um exemplo rápido vamos usar Python e a biblioteca SMBus (SMBus é uma variante do I2C). O que nos interessa são dois métodos:
write_byte_data(int addr, char cmd, char val)
Envia para o dispositivo de endereço addr cmd seguido de val.
write_i2c_block_data(int addr, char cmd, long vals[])
Envia para o dispositivo de endereço addr cmd seguido dos valores na lista val.
No nosso caso o "cmd" será a seleção entre registrador ou dado.
O código abaixo faz apenas a iniciação do LCD e a apresentação de um texto curto.
#!/usr/bin/python from time import sleep import smbus # Endereço do display e os comandos para selecionar registrador ou dado DEVICE_ADDRESS = 0x3E SEL_REG = 0x00 SEL_DADO = 0x40 # Objeto para acesso ao I2C1 bus = smbus.SMBus(1) # Iniciação do display # O último comando é um Clear que demora um pouco mais de 1ms bus.write_byte_data(DEVICE_ADDRESS, SEL_REG, 0x38) bus.write_byte_data(DEVICE_ADDRESS, SEL_REG, 0x39) bus.write_byte_data(DEVICE_ADDRESS, SEL_REG, 0x14) bus.write_byte_data(DEVICE_ADDRESS, SEL_REG, 0x79) bus.write_byte_data(DEVICE_ADDRESS, SEL_REG, 0x50) bus.write_byte_data(DEVICE_ADDRESS, SEL_REG, 0x6C) bus.write_byte_data(DEVICE_ADDRESS, SEL_REG, 0x0C) bus.write_byte_data(DEVICE_ADDRESS, SEL_REG, 0x01) sleep (0.002) # Escreve a mensagem bus.write_i2c_block_data(DEVICE_ADDRESS, SEL_DADO, list(bytearray("DQSoft")))
Links
Os links abaixo são as origens das informações que coloquei acima.
Habilitação do i2c, de forma sucinta.
O tutorial da Adafruit
Descrição dos métodos do SMBus
Problemas causados com a introdução do Device Tree
Um comentário:
Nice! Geralmente quando preciso utilizar o i2c em algo para testes eu costumo carregar utilizando a tool da wiring pi "gpio load i2c"
Postar um comentário