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("");
}
--------------------------------------------------------------------------------------------------------------------------------------------------
Tags:
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...
Bem-vindo a
Laboratorio de Garagem (arduino, eletrônica, robotica, hacking)
© 2024 Criado por Marcelo Rodrigues. Ativado por