Descobrindo o endereço I2C de dispositivos com Arduino
Quando compramos equipamentos de lojas desconhecidas quase sempre nos deparamos com o problema de não termos disponível um datasheet ou algum tipo de documentação que auxilie na utilização dos mesmos. Sabendo disso, neste tutorial nós iremos aprender a como identificar o endereço I2C de dispositivos com um Arduino.
[toc]
Protocolo I2C
O protocolo I2C, ou Inter-Integrated Circuit é um protocolo de comunicação desenvolvido pela Philips, que teve como objetivo inicial, interconectar dispositivos de baixa velocidade e curta distância. A comunicação i2C funciona por meio de um barramento onde apenas um dispositivo, denominado mestre, é responsável por requisitar informações dos dispositivos conectados. A conexão I2C é feita através de dois fios, sendo eles:
- sda: Transmitir dados entre receptor e transmissor via barramento.
- scl: Temporizar e sincronizar unidades conectadas ao sistema.
É também interessante possuir um resistor pull-up nas trilhas sda e scl para estabilizar o barramento de comunicação
Como a comunicação I2C é feita via um barramento, cada dispositivo conectado ao sistema deve possuir um endereço único. Este código é composto por um valor de 7 bits, disponibilizando um total de 127 endereços onde apenas o intervalo 0x8 até 0 intervalo 0x77 está disponível para utilização.
Mãos à obra – Descobrindo o endereço I2C de dispositivos utilizando o seu Arduino
Componentes utilizados:
Montando o projeto
Como teste do nosso código de pesquisa, iremos conectar um dispositivo I2C ao nosso Arduino Nano. Para fazer isso basta conectar o pino SDA ao pino A4 do Arduino e o pino SCL ao pino A5 do Arduino, além é claro dos pinos utilizados para alimentação. A figura abaixo ilustra o processo de ligação dos fios de comunicação e alimentação.
Veja como ficou a montagem na prática.
Atenção, sempre monte o seu circuito com a alimentação do Arduino desligada. Para evitar possíveis curtos circuitos que possam vir a danificar o seu módulo ou até mesmo o microcontrolador.
Programando
Agora que temos conectado ao nosso sistema um módulo que supostamente não sabemos o seu endereço. Iremos utilizar carregar o seguinte código em nossa placa para sua identificação.
#include <Wire.h> #define TEMPOLEITURA 100 #define TEMPOESPERA 3000 byte endereco; byte codigoResultado=0; byte dispositivosEncontrados=0; void setup() { Serial.begin(9600); Wire.begin(); while (!Serial); scanI2c(); } void scanI2c(){ for (endereco=0; endereco<128; endereco++){ Wire.beginTransmission(endereco); codigoResultado = Wire.endTransmission(); if (codigoResultado==0){ Serial.print ("Dispositivo I2c detectado no endereço: "); Serial.println(endereco,HEX); dispositivosEncontrados++; delay(TEMPOESPERA); } delay(TEMPOLEITURA); } if (dispositivosEncontrados>0){ Serial.print("Foi encontrado um total de: "); Serial.print(dispositivosEncontrados); Serial.println(" dispositivos"); } else{ Serial.println("Nenhum dispositivo foi encontrado !!!"); } } void loop() { }
Entendendo a fundo
Software
– Incluindo as bibliotecas necessárias
De início, para ser possível a utilização da comunicação I2C no nosso Arduino, nós iremos precisar adicionar a biblioteca wire.h que pode ser feita através da seguinte sentença:
#include <Wire.h>
– Temporizadores de pesquisa e tempo de espera
Iremos também neste código criar dois temporizadores para definir de quanto em quantos milissegundos o nosso código deverá fazer a pesquisa em um novo endereço e por quanto tempo ele deve esperar após encontrar um dispositivo conectado ao barramento I2C. Para isso, iremos criar 2 diretivas define que serão responsáveis por armazenar estes valores, fazendo com que eles sejam facilmente parametrizáveis.
#define TEMPOLEITURA 100 #define TEMPOESPERA 3000
– Função setup
Na função setup, iremos inicializar a comunicação I2C para identificação de dispositivos e também iremos inicializar a comunicação serial, para que os dados sejam mostrados no serial monitor.
void setup() { Serial.begin(9600); Wire.begin(); while (!Serial); scanI2c(); }
Na versão Leonardo do Arduino, para utilização correta da porta serial, é importar adicionar o trecho:
while (!Serial);Pois assim iremos garantir que a comunicação serial está de fato funcionando corretamente.
– Variáveis de controle
Para deslocarmos entre os endereços, identificarmos se o dispositivo está realmente conectado ao barramento e contar quantos dispositivos estão conectados, nós iremos utilizar três variáveis do tipo byte. A utilização destas variáveis com este tipo deve-se ao fato de que como estes valores nunca serão maiores que 255(,) não existe a possibilidade de overflow. Sendo assim iremos economizar cerca de 3 bytes de memória, se utilizássemos por exemplo o tipo int para armazenar.
byte endereco; byte codigoResultado=0; byte dispositivosEncontrados=0;
– Função scanI2c
Dentro da função scanI2c nós iremos realizar todo o processo de busca por dispositivos conectados, que será feito da seguinte forma:
- Através do comando for, percorrer todos os endereços disponíveis no protocolo I2C, partindo do 0 até o 127.
for (endereco=0; endereco<128; endereco++);
- Utilizando o método Wire.beginTransmission, iremos tentar estabelecer uma comunicação com o dispositivo conectado, utilizando como endereço a posição atual do for.
Wire.beginTransmission(endereco);
- Logo em seguida iremos encerrar a transmissão através do método Wire.endTransmission
. Estemétodo possui um retorno que consiste em:- Igual a 0 – Conexão fechada com sucesso
- Diferente de 0 – Falha na transmissão ou não existe dispositivo conectado
- Sabendo disso, iremos armazenar este valor de retorno em nossa variável codigoResultado
codigoResultado = Wire.endTransmission();
- Logo em seguida verificamos se a variável codigoResultado é igual a zero, caso seja mostramos o código do dispositivo e contabilizamos a variável que mostra o total de dispositivos encontrados e aguardamos o tempo em milissegundos definido em TEMPOESPERA
if (codigoResultado==0){ Serial.print ("Dispositivo I2c detectado no endereço: "); Serial.println(endereco,HEX); dispositivosEncontrados++; delay(TEMPOESPERA); }
- Após cada tentativa de leitura também aguardamos um intervalo de tempo definido em TEMPOLEITURA.
delay(TEMPOLEITURA);
- Ao fim do for verificamos se o número de dispositivos encontrados é maior que zero, caso seja mostramos este valor na serial, caso contrário informamos que nenhum dispositivo foi encontrado.
if (dispositivosEncontrados>0){ Serial.print("Foi encontrado um total de: "); Serial.print(dispositivosEncontrados); Serial.println(" dispositivos"); } else{ Serial.println("Nenhum dispositivo foi encontrado !!!"); }
Vídeo Tutorial
Vocês também podem ver uma explicação do código em vídeo no canal abaixo:
Desafio
Agora que você sabe como descobrir o endereço de dispotivos I2C. Tente conectar mais de um ao barramento e veja se o código consegue detectar todos. Tente também criar uma lógica para salvar o endereço dos dispositivos identificados pelo sistema.
Considerações Finais
Este tutorial, teve como objetivo mostrar uma forma bem simples para encontrar o endereço de dispositivos conectados via I2C. Espero que tenham gostado do conteúdo apresentado, sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.
Caso queira saber mais sobre o Display LCD 16×2 com Adaptador I2C, acesse o tutorial: Display LCD 20×4 e LCD 16×2 com Adaptador I2C – Utilizando o display com Arduino
este endereço i2c pode ser mudadao?
como posso alterar o endereço i2c ?
Estou tentando criar um sistema conectando dois sensores de temperatura infravermelho mlx60914 ao arduino. Porém, por padrão de fábrica, vieram como o mesmo endereço e, pra realizar a comunicação i2c preciso alterar pelo menos um desses endereços, você sabe como posso fazer isso?
Corrigindo somente haverá alterações se possuir um falha de de capacitância na linha.
Mestre parabéns pelo método fiquei muito nsentivado, não sou técnico em eletrônica formado mais Tenho um pouquinho de experiência e me esforço. Trabalho com uma marca específica de smart ao qual possuem este protocolo seria possível e considerável com esse projeto sabermos se falta comunicação entre os CIs? Usamos apenas o multímetro ao qual e evela a tensão 1v8. Uso um equipamento baseado nas linhas de Lissajus, porém não é conclusivo, pq não há variações nas elipses, somente se haverá um falha de capacitância na linha.
Muito legal e muito bem explicado viu! Parabéns!