- O que é o protocolo de comunicação I2C?
- Como funciona a comunicação I2C?
- Onde usar a comunicação I2C?
- I2C em Arduino
- Componentes necessários
- Diagrama de circuito
- Explicação de trabalho
- Programação I2C em Arduino
- Explicação de programação do Master Arduino
- Explicação de programação do Slave Arduino
Em nosso tutorial anterior, aprendemos sobre a comunicação SPI no Arduino. Hoje vamos aprender sobre outro protocolo de comunicação serial: I2C (Inter Integrated Circuits). Comparando I2C com SPI, I2C tem apenas dois fios, enquanto o SPI usa quatro e I2C pode ter vários mestre e escravo, enquanto o SPI pode ter apenas um mestre e vários escravos. Portanto, há mais de um microcontrolador em um projeto que precisa ser mestre e então o I2C é usado. A comunicação I2C é geralmente usada para se comunicar com giroscópio, acelerômetro, sensores de pressão barométrica, telas de LED, etc.
Neste tutorial do Arduino I2C, usaremos a comunicação I2C entre duas placas arduino e enviaremos valores (0 a 127) uma para a outra usando o potenciômetro. Os valores serão exibidos no LCD 16x2 conectado a cada um do Arduino. Aqui, um Arduino atuará como Master e outro como Slave. Então, vamos começar com a introdução sobre a comunicação I2C.
O que é o protocolo de comunicação I2C?
O termo IIC significa “ Inter Integrated Circuits ”. Normalmente é denotado como I2C ou I ao quadrado C ou mesmo como protocolo de interface de 2 fios (TWI) em alguns lugares, mas significa o mesmo. I2C é um protocolo de comunicação síncrona, o que significa que ambos os dispositivos que estão compartilhando as informações devem compartilhar um sinal de relógio comum. Ele tem apenas dois fios para compartilhar informações, dos quais um é usado para o sinal do galo e o outro é usado para enviar e receber dados.
Como funciona a comunicação I2C?
A comunicação I2C foi introduzida pela primeira vez por Phillips. Como disse anteriormente, ele tem dois fios, esses dois fios serão conectados em dois dispositivos. Aqui, um dispositivo é chamado de mestre e o outro dispositivo é chamado de escravo. A comunicação deve e sempre ocorrerá entre um Mestre e um Escravo. A vantagem da comunicação I2C é que mais de um escravo pode ser conectado a um mestre.
A comunicação completa ocorre por meio desses dois fios, a saber, Serial Clock (SCL) e Serial Data (SDA).
Serial Clock (SCL): Compartilha o sinal de clock gerado pelo mestre com o escravo
Serial Data (SDA): Envia os dados de e para o mestre e o escravo.
A qualquer momento, apenas o mestre será capaz de iniciar a comunicação. Como há mais de um escravo no barramento, o mestre deve referir-se a cada escravo usando um endereço diferente. Quando endereçado apenas o escravo com aquele endereço particular irá responder de volta com a informação enquanto os outros continuam desligando. Dessa forma, podemos usar o mesmo barramento para nos comunicarmos com vários dispositivos.
Os níveis de tensão de I2C não são predefinidos. A comunicação I2C é flexível, significa que o dispositivo que é alimentado por 5v volt, pode usar 5v para I2C e os dispositivos de 3,3v podem usar 3v para comunicação I2C. Mas e se dois dispositivos que estão operando em tensões diferentes precisarem se comunicar usando I2C? Um barramento I2C 5V não pode ser conectado com 3.3V dispositivo. Neste caso, os deslocadores de tensão são usados para combinar os níveis de tensão entre dois barramentos I2C.
Existem alguns conjuntos de condições que enquadram uma transação. A inicialização da transmissão começa com uma borda descendente de SDA, que é definida como condição 'START' no diagrama abaixo, onde o mestre deixa SCL alto enquanto define SDA baixo.
Conforme mostrado no diagrama acima abaixo, A borda descendente do SDA é o gatilho de hardware para a condição START. Depois disso, todos os dispositivos no mesmo barramento entram no modo de escuta.
Da mesma maneira, a borda ascendente do SDA para a transmissão, que é mostrada como condição 'STOP' no diagrama acima, onde o mestre deixa o SCL alto e também libera o SDA para ir para o ALTO. Portanto, a borda ascendente do SDA interrompe a transmissão.
O bit R / W indica a direção da transmissão dos bytes seguintes, se for HIGH significa que o escravo irá transmitir e se for baixo significa que o mestre irá transmitir.
Cada bit é transmitido em cada ciclo de clock, portanto, leva 8 ciclos de clock para transmitir um byte. Após cada byte enviado ou recebido, o nono ciclo de clock é mantido para o ACK / NACK (confirmado / não confirmado). Este bit ACK é gerado pelo escravo ou mestre dependendo da situação. Para ACK bit, SDA é ajustado para baixo pelo mestre escravo ou no 9 ° ciclo de relógio. Portanto, é baixo considerado como ACK caso contrário NACK.
Onde usar a comunicação I2C?
A comunicação I2C é usada apenas para comunicação de curta distância. É certamente confiável até certo ponto, pois tem um pulso de relógio sincronizado para torná-lo inteligente. Este protocolo é usado principalmente para se comunicar com o sensor ou outros dispositivos que precisam enviar informações a um mestre. É muito útil quando um microcontrolador precisa se comunicar com muitos outros módulos escravos usando, no mínimo, fios. Se você está procurando uma comunicação de longo alcance, você deve tentar o RS232 e se estiver procurando uma comunicação mais confiável, você deve tentar o protocolo SPI.
I2C em Arduino
A imagem abaixo mostra os pinos I2C presentes no Arduino UNO.
Linha I2C | Pin no Arduino |
SDA | A4 |
SCL | A5 |
Antes de começarmos a programar I2C usando dois Arduino. Precisamos aprender sobre a biblioteca Wire usada no IDE Arduino.
A biblioteca
1. Wire.begin (endereço):
Uso: esta biblioteca é usada para fazer comunicação com dispositivos I2C. Isso inicia a biblioteca Wire e junta-se ao barramento I2C como mestre ou escravo.
Endereço: O endereço do escravo de 7 bits é opcional e se o endereço não for especificado, ele entra no barramento como mestre desta forma.
2. Wire.read ():
Uso: Esta função é usada para ler um byte que foi recebido do dispositivo mestre ou escravo, que foi transmitido de um dispositivo escravo para um dispositivo mestre após uma chamada para requestFrom () ou foi transmitido de um mestre para um escravo.
3. Wire.write ():
Uso: Esta função é usada para gravar dados em um dispositivo escravo ou mestre.
Slave to Master: Slave grava dados em um master quando Wire.RequestFrom () é usado no master.
Mestre para escravo: Para transmissão de um mestre para o dispositivo escravo, Wire.write () é usado entre as chamadas para Wire.beginTransmission () e Wire.endTransmission ().
Wire.write () pode ser escrito como:
- Wire.write (valor)
valor: um valor a ser enviado como um único byte.
- Wire.write (string):
string: uma string a ser enviada como uma série de bytes.
- Wire.write (dados, comprimento):
dados: uma matriz de dados para enviar como bytes
comprimento: o número de bytes a transmitir.
4. Wire.beginTransmission (endereço):
Uso: Esta função é usada para iniciar uma transmissão para o dispositivo I2C com o endereço de escravo fornecido. Posteriormente, crie uma fila de bytes para transmissão com a função write () e transmita-os chamando a função endTransmission () . O endereço de 7 bits do dispositivo é transmitido.
5. Wire.endTransmission ();
Uso: Esta função é usada para encerrar uma transmissão para um dispositivo escravo que foi iniciada por beginTransmission () e transmite os bytes que foram enfileirados por Wire.write ().
6. Wire.onRequest ();
Uso: Esta função é chamada quando um mestre solicita dados usando Wire.requestFrom () do dispositivo escravo. Aqui podemos incluir a função Wire.write () para enviar dados ao mestre.
7. Wire.onReceive ();Uso: Esta função é chamada quando um dispositivo escravo recebe dados de um mestre. Aqui podemos incluir Wire.read (); função para ler os dados enviados do mestre.
8. Wire.requestFrom (endereço, quantidade);
Uso: Esta função é usada no mestre para solicitar bytes de um dispositivo escravo. A função Wire.read () é usada para ler os dados enviados do dispositivo escravo.
endereço: o endereço de 7 bits do dispositivo para solicitar bytes de
quantidade: o número de bytes a solicitar
Componentes necessários
- Arduino Uno (2-Nos)
- Módulo de display LCD 16X2
- Potenciômetro 10K (4-Nos)
- Tábua de pão
- Fios de conexão
Diagrama de circuito
Explicação de trabalho
Aqui, para demonstrar a comunicação I2C no Arduino, usamos Dois Arduino UNO com dois monitores LCD 16X2 conectados um ao outro e usamos dois potenciômetros em ambos arduino para determinar os valores de envio (0 a 127) de mestre para escravo e escravo para mestre variando o potenciômetro.
Pegamos o valor analógico de entrada no pino A0 do arduino de (0 a 5 V) usando o potenciômetro e os convertemos em valor analógico para digital (0 a 1023). Em seguida, esses valores ADC são posteriormente convertidos em (0 a 127), pois podemos enviar apenas dados de 7 bits por meio da comunicação I2C. A comunicação I2C ocorre por meio de dois fios nos pinos A4 e A5 de ambos os arduino.
Os valores no LCD do Slave Arduino serão alterados pela variação do POT no lado mestre e vice-versa.
Programação I2C em Arduino
Este tutorial tem dois programas, um para o Arduino mestre e outro para o Arduino escravo. Programas completos para ambos os lados são fornecidos no final deste projeto com um vídeo de demonstração.
Explicação de programação do Master Arduino
1. Em primeiro lugar, precisamos incluir a biblioteca Wire para usar as funções de comunicação I2C e a biblioteca LCD para usar as funções LCD. Defina também os pinos de LCD para LCD 16x2. Saiba mais sobre a interface do LCD com o Arduino aqui.
#incluir
2. Na configuração vazia ()
- Iniciamos a comunicação serial na taxa Baud 9600.
Serial.begin (9600);
- Em seguida, iniciamos a comunicação I2C no pino (A4, A5)
Wire.begin (); // Começa a comunicação I2C no pino (A4, A5)
- Em seguida, inicializamos o módulo de exibição LCD no modo 16X2 e exibimos a mensagem de boas-vindas e apagamos após cinco segundos.
lcd.begin (16,2); // Inicia o display LCD lcd.setCursor (0,0); // Define o Cursor na primeira linha do Display lcd.print ("Circuit Digest"); // Imprime CIRCUIT DIGEST no LCD lcd.setCursor (0,1); // Define o Cursor na segunda linha do Display lcd.print ("I2C 2 ARDUINO"); // Imprime I2C ARDUINO no LCD delay (5000); // Atraso de 5 segundos lcd.clear (); // Limpa o display LCD
3. Em loop vazio ()
- Primeiro precisamos obter dados do Slave, então usamos requestFrom () com o endereço do escravo 8 e solicitamos um byte
Wire.requestFrom (8,1);
O valor recebido é lido usando Wire.read ()
byte MasterReceive = Wire.read ();
- Em seguida, precisamos ler o valor analógico do arduino mestre POT anexado ao pino A0
valor do pot int = AnalRead (A0);
Convertemos esse valor em termos de um byte de 0 a 127.
byte MasterSend = map (potvalue, 0,1023,0,127);
- Em seguida, precisamos enviar esses valores convertidos, então começamos a transmissão com o arduino escravo com 8 endereços
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- Em seguida, exibimos esses valores recebidos do arduino escravo com um atraso de 500 microssegundos e continuamente recebemos e exibimos esses valores.
lcd.setCursor (0,0); // Define o Currsor na linha um do LCD lcd.print (">> Master <<"); // Imprime >> Master << no LCD lcd.setCursor (0,1); // Define o Cursor na linha dois do LCD lcd.print ("SlaveVal:"); // Imprime SlaveVal: no LCD lcd.print (MasterReceive); // Imprime MasterReceive no LCD recebido do Slave Serial.println ("Master Received From Slave"); // Imprime no Serial Monitor Serial.println (MasterReceive); atraso (500); lcd.clear ();
Explicação de programação do Slave Arduino
1. Da mesma forma que o mestre, em primeiro lugar, precisamos incluir a biblioteca Wire para usar as funções de comunicação I2C e a biblioteca LCD para usar as funções LCD. Defina também os pinos de LCD para LCD 16x2.
#incluir
2. Na configuração vazia ()
- Iniciamos a comunicação serial na taxa Baud 9600.
Serial.begin (9600);
- Em seguida, iniciamos a comunicação I2C no pino (A4, A5) com o endereço do escravo como 8. Aqui é importante especificar o endereço do escravo.
Wire.begin (8);
Em seguida, precisamos chamar a função quando o Slave recebe o valor do mestre e quando o mestre solicita o valor do Slave
Wire.onReceive (receiveEvent); Wire.onRequest (requestEvent);
- Em seguida, inicializamos o módulo de exibição LCD no modo 16X2 e exibimos a mensagem de boas-vindas e apagamos após cinco segundos.
lcd.begin (16,2); // Inicia o display LCD lcd.setCursor (0,0); // Define o Cursor na primeira linha do Display lcd.print ("Circuit Digest"); // Imprime CIRCUIT DIGEST no LCD lcd.setCursor (0,1); // Define o Cursor na segunda linha do Display lcd.print ("I2C 2 ARDUINO"); // Imprime I2C ARDUINO no LCD delay (5000); // Atraso de 5 segundos lcd.clear (); // Limpa o display LCD
3. Em seguida, temos duas funções, uma para solicitar evento e outra para receber evento
Para solicitar evento
Quando o mestre solicitar o valor do escravo esta função será executada. Esta função obtém o valor de entrada do Slave POT, converte-o em termos de 7 bits e envia esse valor ao mestre.
void requestEvent () { int potvalue = analogRead (A0); byte SlaveSend = map (potvalue, 0,1023,0,127); Wire.write (SlaveSend); }
Para receber evento
Quando o Mestre envia dados para o escravo com endereço de escravo (8), esta função será executada. Esta função lê o valor recebido do mestre e armazena em uma variável do tipo byte .
void receiveEvent (int howMany { SlaveReceived = Wire.read (); }
4. No loop vazio ():
Exibimos o valor recebido do mestre continuamente no módulo de display LCD.
loop vazio (vazio) { lcd.setCursor (0,0); // Define o Currsor na linha um do LCD lcd.print (">> Slave <<"); // Imprime >> Slave << no LCD lcd.setCursor (0,1); // Define o Cursor na linha dois do LCD lcd.print ("MasterVal:"); // Imprime MasterVal: no LCD lcd.print (SlaveReceived); // Imprime o valor SlaveReceived no LCD recebido do Master Serial.println ("Slave Received From Master:"); // Imprime no Serial Monitor Serial.println (SlaveReceived); atraso (500); lcd.clear (); }
Ao girar o potenciômetro de um lado, você pode ver os valores variando de LCD em um outro lado:
Então é assim que a comunicação I2C ocorre no Arduino, aqui usamos dois Arduinos para demonstrar não apenas o envio de dados, mas também o recebimento dos dados usando a comunicação I2C. Agora você pode conectar qualquer sensor I2C ao Arduino.
A codificação completa para Arduino Master e Slave é fornecida abaixo com um vídeo de demonstração