No post Barramento I²C, utilizamos um Arduíno UNO como Master, um Duemilanove e um Nano como Slavers. Neste post, vamos substituir o Arduíno UNO Master por um Raspberry PI.
Segue lista de materiais utilizados:
- 1 Raspberry PI Rev B
- 1 Arduíno Duemilanove
- 1 Arduíno Nano
Na nossa montagem, o Raspberry irá imprimir uma mensagem enviada por cada Arduíno, similar ao post Barramento I²C:
Raspberry PI
Por default, os pinos I²C do Raspberry estão desabilitados. Segue abaixo os passos habilitá-los.
1 - Via console, acesse a ferramenta de configuração
$ sudo raspi-config
2 - Selecione Advanced Options
3 - Selecione A7 I2C
4 - Selecione Yes e depois OK
5 - Selecione Yes e depois OK
6 - Selecione Finish
7 - Desligue o Raspberry como o comando abaixo, desligue a força e faça conexões dos Arduínos.
$ sudo halt
Esquema de ligação
Segue abaixo a lista de pinos do Raspberry PI Rev B
Os pinos I²C são: 3 - SDA(Dados) e 5 - SCL (Clock). O esquema de ligação é exatamente o mesmo do post Barramento I²C.
Segue esquemático:
Apesar de o Raspberry Pi trabalhar a 3,3V e o Arduíno a 5V, como o Raspberry PI será o Master a tensão do barramento será definida por ele e por isso, não se faz necessário montar um circuito para limitar a tensão (se o arduíno for Master, ele pode queimar a porta do Raspberry). Além disso, o Raspberry PI já tem um resistor pull-up nos pinos utilizado no barramento I²C que dispensa o seu uso em outros dispositivos.
Programação dos Arduínos.
A biblioteca que utilizaremos no Raspberry só permite a leitura de um inteiro por vez (não é possível ler um buffer) e por isso, enviaremos a mensagem caractere a caractere, com o primeiro caractere de controle. Explicarei com mais detalhes mais a frente.
Código do Nano:
#include <Wire.h>
void setup()
{
Wire.begin(0x50);//endereço de I2C
Wire.onRequest(requestEvent);
pinMode(13, OUTPUT);
}
void loop()
{
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}
char * buff="*hello I'm Nano";
byte count = 0;
void requestEvent()
{
Wire.write(buff[count]);
if(count == 14)
count = -1;
count ++;
}
Código do Duemilanove:
#include <Wire.h>
void setup()
{
Wire.begin(0x40);//endereço de I2C
Wire.onRequest(requestEvent);
pinMode(13, OUTPUT);
}
void loop()
{
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}
char * buff="*hello I'm Due";
byte count = 0;
void requestEvent()
{
Wire.write(buff[count]);
if(count == 13)
count = -1;
count ++;
}
Programação do Raspberry PI.
Para confirmar se o módulo I²C está ativo, basta digitar a linha de comando abaixo:
$ lsmod | grep i2c
Devemos ter uma saída similar a essa:
pi@raspberrypi:~ $ lsmod | grep i2c
i2c_bcm2708 5988 0
i2c_dev 6386 0
A saída acima indica que o módulo i2c_bmc2708 está ativo.
Agora, vamos instalar a biblioteca para o I²C. Para mais detalhes sobre ela, clique aqui.
$ sudo apt-get install libi2c-dev
O Raspberry vem com um programa para detectar o endereço dos dispositivos conectados no barramento.
Basta digitar o comando abaixo:
$ i2cdetect -y 1
Se seu Raspberry PI for Rev 1, digite:
$ i2cdetect -y 0
Essa diferença acontece, pois houve uma alteração nos pinos utilizados pelo I²C entre Rev 1 e 2.
A saída deve ser de acordo com texto abaixo:
pi@raspberrypi:~ $ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
0x40 e 0x50 são os Arduínos conetados no barramento.
Agora vamos a codificação.
Makefile - Crie o arquivo de acordo com o texto abaixo:
#
# Makefile:
#################################################################################
#DEBUG = -g -O0
DEBUG = -O3
CC = gcc
INCLUDE = -I/usr/local/include
CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe
LDFLAGS = -L/usr/local/lib
LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm
# Should not alter anything below this line
###############################################################################
SRC = i2cTest.cpp \
Crie um arquivo chamado i2cTest.cpp, de acordo com o texto abaixo:
#include <stdio.h> #include <wiringPi.h> #include <wiringPiI2C.h> void readI2CString(int fd, char*buffer,int length,char charController) { for(;;)//aguardando caractere de controle para guardar a mensagem if(wiringPiI2CRead(fd)==charController) break; for(int i = 0; i < length; i++)//lendo mensagem { buffer[i]=wiringPiI2CRead(fd); } } int main (int argc, char *argv[]) { int fd1,fd2;//identificadores de cada dispositivo char buffer[20];//buffer para armazenar a mensagem wiringPiSetup ();//inicializando biblioteca fd1=wiringPiI2CSetup (0x40);//conectando com dispositivo 40 fd2=wiringPiI2CSetup (0x50);//conectando com dispositivo 50 if(fd1==-1||fd2==-1) { printf("Can't setup the I2C devices\n"); return -1; } else { for (;;) { readI2CString(fd1,buffer,13,'*');//Lendo mensagem do dispositivo 40 buffer[13] = '\0'; printf("%s\n",buffer); readI2CString(fd2,buffer,14,'*');//Lendo mensagem do dispositivo 50 buffer[14] = '\0'; printf("%s\n",buffer); } } return 0; }
$
make i2cTest
Para executar o programa, basta digitar o comando:
$ sudo ./i2cTest
A saída deverá ser essa:
Entendimento do código
Esse método abaixo, irá chamar o método wiringPiI2CRead da biblioteca wiringPiI2C que retorna um inteiro (valor lido). Como queremos imprimir uma String, se simplesmente imprimíssemos os caracteres no console, poderíamos imprimir llo I'm Duehe ou o I'm Duehello, ou outra combinação, pois o arduíno irá enviar sequencialmente e infinitamente a sequencia de caracteres. Assim, adicionei um caractere de controle para indicar que a mensagem iniciará no próximo caractere e o código irá esperar que venha esse caractere para começar a gravar a mensagem.
void readI2CString(int fd, char*buffer,int length,char charController)
{
for(;;)//aguardando caractere de controle para guardar a mensagem
if(wiringPiI2CRead(fd)==charController)
break;
for(int i = 0; i < length; i++)//lendo mensagem
{
buffer[i]=wiringPiI2CRead(fd);
}
}
Aqui, a aplicação ficará em loop, lendo as mensagens de cada um dos Arduínos.
for (;;)
{
readI2CString(fd1,buffer,13,'*');//Lendo mensagem do dispositivo 40
buffer[13] = '\0';
printf("%s\n",buffer);
readI2CString(fd2,buffer,14,'*');//Lendo mensagem do dispositivo 50
buffer[14] = '\0';
printf("%s\n",buffer);
}
O Arduíno Duemilanove, que está com o endereço 0x40, irá enviar o caractere de controle '*' e a mensagem hello I'm Due, caractere a caractere (13 caracteres excluindo o de controle)
char * buff="*hello I'm Due";
byte count = 0;
void requestEvent()
{
Wire.write(buff[count]);
if(count == 13)
count = -1;
count ++;
}
O Arduíno Nano, que está com o endereço 0x50, irá enviar o caractere de controle '*' e a mensagem hello I'm Nano, caractere a caractere (14 caracteres excluindo o de controle)
char * buff="*hello I'm Nano";
byte count = 0;
void requestEvent()
{
Wire.write(buff[count]);
if(count == 14)
count = -1;
count ++;
}
E por isso, no loop do Raspberry, ele esperará 13 caracteres do Duemianove e 14 do Nano.
Sem comentários:
Enviar um comentário