Comunicação I2C entre dois Arduinos Uno (I2C em ambos os lados)

Comunicação I2C (Inter-Integrated Circuit), protocolo síncrono serial, entre dois Arduinos Uno.

Referências para consulta:

* https://www.arduino.cc/en/Reference/Wire

* https://learn.sparkfun.com/tutorials/serial-communication

* https://learn.sparkfun.com/tutorials/i2c


Explicando este experimento:

* Neste experimento serão necessários 2 Arduinos Uno, um para master e outro para slave.

* O Arduino master enviará automaticamente caracteres para o Arduino slave.

* O Arduino slave os recebe, processa e envia o resultado para o master.

* O master recebe os dados do slave e os apresenta no serial monitor.

* Observação: é possível observar os dados enviados ou recebidos no Serial Monitor tanto

    do lado do master quanto do slave.

Pinagem entre os dois Arduinos Uno:

* Arduino (master)  <==>  Arduino (slave)

* A4 (SDA)                      A4 (SDA)

* A5 (SCL)                       A5 (SCL)

* GND                             GND

* 5V                                Vin (se for alimentar o Arduino slave através do master)

Código (sketch) para o Arduino master:

-------------------------------------------------------------------------------------------------------------------------------------------------

#include <Wire.h>                   // incluir a biblioteca para comunicação I2C

byte outData = 1;

void setup() {
  Serial.begin(9600);                // inicia o Serial Monitor, necessário se quiser depurar este sketch

  Wire.begin();                        // juntar-se à conexão I2C (para o master o endereço é opcional)
}

void loop() {
  Serial.print("Dados enviados ao slave ==> ");

  Wire.beginTransmission(8);   // transmitir dados para o slave com o endereço #8
  Wire.write("Request");          // enviar uma string
  Wire.write(outData);              // enviar uma variável numérica tipo byte
  Wire.endTransmission();       // sinaliza o fim de transmissão de dados para o slave

  Serial.print(outData);

  if(outData == 3){                   // reiniciar a contagem de outData ou acrescentar 1 a outData
    outData = 1;
  }else{
    outData++;
  }

  String inString;                      // string para armazenar bytes enviados pelo slave
  Wire.requestFrom(8, 6);         // requisitando resposta do slave.
  while(Wire.available()) {          // looping para receber todos os bytes do slave #8 
    char inChar = Wire.read();    // receber cada byte como caracter
    if(isAlphaNumeric(inChar)) {  // se caracter recebido do slave for alfanumérico, concatenar string
      inString += inChar;            // concatenar o caracter recebido
    }
  }
  Serial.print(". Resposta do slave ==> ");
  Serial.print(inString);
  Serial.println(".");
  Serial.println("");

  delay(4000);
}

-------------------------------------------------------------------------------------------------------------------------------------------------

Código (sketch) para o Arduino slave:

-------------------------------------------------------------------------------------------------------------------------------------------------

#include <Wire.h>                   // incluir a biblioteca para comunicação I2C

byte inByte;
bool inStatus = false;

void setup() {
  Serial.begin(9600);               // inicia o Serial Monitor, necessário se quiser depurar este sketch

  Wire.begin(8);                      // juntar-se à conexão I2C com o endereço de slave #8
  Wire.onReceive(receiveEvent);  // evento que chama função para receber dados do master
  Wire.onRequest(requestEvent); // evento que chama função para enviar dados para o master
}

void loop() {
  if (inStatus == true){             // se dados foram recebidos do master, tratar estes dados

    inStatus = false;                // sinalizar, neste sketch, que a resposta ao master foi enviada
  }
}

void receiveEvent(){                 // Função que é executada automaticamente assim que o slave

                                             // receber dados do master
  String inString = "";              // limpar inString para impedir concatenar dados atuais com anteriores
  while(Wire.available() > 1){    // lê até o final da string enviada pelo primeiro Wire.write() do master
    char inChar = (char)Wire.read(); // Wire.read() recebe cada byte da string de bytes
    inString += inChar;             // armazanar, concatenando, cada byte recebido do master

                                            // colocando-os numa variável String
  }
  inByte = Wire.read();            // lê o byte enviado pelo segundo Wire.write() do master

                                            // colocando numa variável numérica inteira

  Serial.print("Dados recebidos do master ==> ");
  Serial.print(inString);
  Serial.print(" ");
  Serial.print(inByte);
  inStatus = true;                    // sinalizar, neste sketch, que dados foram recebidos do master
}

void requestEvent() {               // Função que executa automaticamente assim que o slave receber

                                             //requisição do master pedindo que os dados sejam enviados
  switch (inByte) {                   // escolher qual resposta enviar ao master e enviá-la
    case 1:                              // "1" para enviar a string "red" para o master
      Wire.write("red");              // envia a string "red" para o master
      Serial.print(". Resposta ao master ==> \"red\", ");
      break;
    case 2:                              // "2" para enviar a string "blue" para o master
      Wire.write("blue"); // envia a string "blue" para o master
      Serial.print(". Resposta ao master ==> \"blue\", ");
      break;
    default:
      Wire.write("error");
      Serial.print(". Resposta ao master ==> \"error\", ");
  }
  Serial.println(inByte);
  Serial.println("");
}

--------------------------------------------------------------------------------------------------------------------------------------------------

Exibições: 3751

Responder esta

Respostas a este tópico

Analisando a comunicação SPI com o Saleae Logic16 Analyzer:

Observar nos gráficos do Saleae Logic16, abaixo:

* enquanto não há comunicação entre os Arduinos, o SDA e o SCL são mantidos em estado ALTO.

* então, no caso específico desta amostra, o master envia o caracter '2' (veja ele representado no momento +0.7 ms do gráfico) para o slave, como pode ser visto neste primeiro gráfico:

* ao findar o envio deste caracter (neste caso, o '2' enviado do master para o slave), master e slave permanecem em estado BAIXO.

* então o slave responde para o master com a string 'blue' (inicia no momento +05 ms como b+ACK, depois como l+ACK, depois u+ACK e por fim e+ACK), como pode ser visto neste segundo gráfico:

* ao findar o envio destes caracteres (neste caso, a string "blue" do slave para o master), master e slave voltam para o estado ALTO.

No Serial Monitor do Arduino master você verá o seguinte resultado...

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço