- Falta de ADC (Conversor Analógico para Digital)
- Limitações na latência (tempo de resposta a um evento externo)
- Limitações em gerar sinais com temporizações precisas
Vamos examinar aqui uma outra forma de interconectar um Raspberry Pi a um Arduino: a comunicação serial I2C.
Revisão rápida do padrão I2C
Já falei várias vezes no blog sobre I2C. Resumindo, esta comunicação utiliza dois sinais: SCL (clock) e SDA (dados) e permite a ligação de vários dispositivos slave (escravo) a um master (mestre) através de um barramento (ou "varal").
O sinal SCL é sempre gerado pelo mestre. Já o sinal SDA é bi-direcional, podendo ser controlado pelo mestre ou pelo escravo. Do ponto de vista elétrico são usadas saídas open-colector, que podem ser colocadas em "zero" (terra) pelos dispositivos. Resistores de pull-up são necessários para manter os sinais em "um" quando nenhuma saída está ativada. Normalmente o sinal SDA só muda quando o sinal SCL está em zero. Duas violações desta regra caracterizam o início (start) e o fim (stop) de uma comunicação.
O primeiro byte enviado pelo mestre contém o endereço do escravo (7 bits) mais a seleção entre leitura e escrita (1 bit). O escravo confirma o endereçamento forçando um bit zero (ACK).
No caso de escrita, o mestre envia em seguida os bytes de dados, o escravo confirma cada um com ACK; ao final o mestre sinaliza o stop. Na leitura, os bits de dados são enviados pelo escravo e o mestre confirma com um NOACK (não aciona SDA).
A figura abaixo mostra uma leitura de EEProm I2C, onde uma escrita (endereço) é seguida de uma leitura (dados); neste caso o Stop da primeira transação pode ser omitido.
Cuidados devem ser tomados ao conectar dispositivos de 3.3 e 5V na mesma rede I2C, o que comentei aqui. Resumindo, se você ligar direto provavelmente vai funcionar mas você está se arriscando.
I2C no Raspberry Pi, em modo Mestre
Já falei sobre isto no passado. O primeiro passo é habilitar o I2C, o que deve ser feito através do raspi-config. Em seguida garanta que os pacotes i2c-tools e python-smbus estão instalados:
sudo apt-get install python-smbus i2c-tools
Feito isto, podemos criar um objeto no nosso programa python para ler e escrever via I2C:
import smbus
bus = smbus.SMBus(1)
Se você estiver usando um Pi original com 256M de Ram, troque o 1 por 0 na segunda linha. Os métodos disponíveis podem ser vistos aqui.
I2C no Arduino, em modo Escravo
A maioria dos exemplos de uso de I2C no Arduino são com ele operando em modo mestre. A biblioteca padrão (Wire) também permite a operação em modo escravo, de uma forma bem simples:
- Para iniciar o modo escravo, use Wire.begin(endereço)
- Use Wire.onReceive para registrar uma rotina que será chamada sempre que dados forem recebidos pelo I2C para o endereço informado. Os dados são lidos usando Wire.read
- Use Wire.onRequest para registrar uma rotina que será chamada quando o mestre requisitar dados. User Wire.Write para enviar os dados.
Exemplo Prático
Neste exemplo vou usar um Raspberry Pi Zero W ligado a um Arduino Pro Mini (um modelo bem em conta, porém sem conexão USB para a Serial. Ao Arduino serão ligados um potenciômetro (que requer ADC) e um anel de LEDs RGB (que requer temporização precisa).
O primeiro byte enviado pelo Raspberry Pi determinará a operação:
- 0 indica leitura do potenciômetro. Esta escrita será seguida de uma operação de leitura I2C que retornará dois bytes, correspondente à leitura do potenciômetro (0 a 1023).
- 1 indica atualização dos LEDs RGB. Deve ser seguido de 21 bytes, três para cada LED. O primeiro byte é a intensidade do verde, o segundo a intensidade do vermelho e o terceiro a intensidade do azul.
A montagem que usei está abaixo, reparem que usei MOSFETs 2N7000 separar as vias I2C de 3,3 e 5 Volts e não coloquei resistores de pullup externos (os pullups internos são suficientes).
O software para os dois lados está no github. Para uma demonstração simples, o Raspberry lê periodicamente o potenciômetro e atualiza os LEDs RGB.
Nenhum comentário:
Postar um comentário