Embora um único Arduino possa realizar muitas tarefas, alguns projetos podem exigir o uso de mais de uma placa para lidar com diferentes funcionalidades. Portanto, para permitir a transferência de dados entre os dois microcontroladores, um protocolo de comunicação como CAN, SPI, I2C ou UART deve ser configurado.
Neste guia, abordaremos o básico de como o I2C funciona, as conexões de hardware e a implementação de software necessária para configurar duas placas Arduino como dispositivos I2C mestre e escravo.
MAKEUSEDO VÍDEO DO DIA ROLE PARA CONTINUAR COM O CONTEÚDO
O que é I2C?
Inter-Integrated Circuit (I2C) é um protocolo de comunicação amplamente utilizado em sistemas embarcados e microcontroladores para permitir a transferência de dados entre dispositivos eletrônicos. Ao contrário do SPI (Serial Peripheral Interface), o I2C permite conectar mais de um dispositivo mestre a um barramento com um ou vários dispositivos escravos. Foi usado pela primeira vez pela Philips e também é conhecido como protocolo de comunicação Two Wire Interface (TWI).
Como funciona a comunicação I2C?
O I2C usa duas linhas bidirecionais: Serial Data (SDA) e Serial Clock (SCL) para transferir dados e sincronizar a comunicação entre os dispositivos. Cada dispositivo conectado ao barramento I2C possui um endereço único que o identifica durante a comunicação. O protocolo I2C permite que vários dispositivos compartilhem o mesmo barramento, e cada dispositivo pode atuar como mestre ou escravo.
A comunicação é iniciada pelo dispositivo mestre e o endereçamento incorreto dos dispositivos escravos pode causar erros na transferência. Confira nosso guia detalhado sobre como funcionam as comunicações seriais UART, SPI e I2C para lhe dar algum contexto.
Uma grande vantagem da comunicação I2C digna de nota é a flexibilidade que ela oferece quando se trata de gerenciamento de energia. Dispositivos que operam em diferentes níveis de tensão ainda podem se comunicar de forma eficaz com a ajuda de conversores de tensão. Isso significa que os dispositivos operando em 3,3 V precisam de conversores de tensão para se conectar a um barramento I2C de 5 V.
A Biblioteca de Fios
A biblioteca Wire é uma biblioteca integrada do Arduino que fornece funções para se comunicar por I2C. Ele usa dois pinos - SDA e SCL - na placa Arduino para comunicação I2C.
Pinos I2C no Arduino Uno:
Pinos Arduino Nano I2C:
como definir o ip estático no raspberry pi
Para usar a biblioteca, você deve incluir o fio.h arquivo de cabeçalho no início do esboço do Arduino.
#include <Wire.h>
A biblioteca Wire fornece funções para iniciar a comunicação com um dispositivo I2C, enviar dados e receber dados. Algumas funções importantes que você deve saber incluem:
- Wire.begin() : usado para entrar no barramento I2C e iniciar a comunicação.
- Wire.beginTransmission() : usado para especificar o endereço do escravo e iniciar uma transmissão.
- Wire.write() : usado para enviar dados para o dispositivo I2C.
- Wire.endTransmission() : usado para encerrar a transmissão e verificar se há erros.
- Wire.requestFrom() : usado para solicitar dados do dispositivo I2C.
- Fio.disponível() : usado para verificar se os dados estão disponíveis para leitura do dispositivo I2C.
- wire.read() : usado para ler dados do dispositivo I2C.
Use o Wire.beginTransmission() função para definir o endereço do sensor, que é inserido como um argumento. Por exemplo, se o endereço do sensor for 0x68 , você usaria:
Wire.beginTransmission(0x68);
Configuração de Hardware Arduino I2C
Para conectar duas placas Arduino usando I2C, você precisará dos seguintes componentes de hardware:
- Duas placas Arduino (mestre e escravo)
- Protoboard
- Fios de jumper
- Dois resistores pull-up de 4,7kΩ
Conecte o SDA e SCL pinos de ambas as placas Arduino a uma breadboard. Conecte os resistores pull-up entre os SDA e SCL pinos e o 5V power rail na breadboard. Por fim, conecte as duas breadboards usando fios de jumper.
Circuito Arduino Uno
Circuito Arduino Nano
Configurando as placas Arduino como dispositivos mestre e escravo I2C
Use o Wire.requestFrom() função para especificar o endereço do dispositivo escravo com o qual queremos nos comunicar. Então use o wire.read() função para obter dados do dispositivo escravo.
Código do dispositivo mestre:
#include <Wire.h>
void setup() {
Wire.begin(); // join i2c bus
Serial.begin(9600); // start serial for output
}
void receiveData() {
int address = 8;
int bytesToRead = 6;
Wire.requestFrom(address, bytesToRead);
while (Wire.available()) {
char data = Wire.read();
Serial.print(data);
}
delay(500);
}
void loop() {
receiveData();
}
O Wire.onReceive() A função é usada para especificar o que fazer quando o escravo recebe dados do dispositivo mestre. No código acima, o Fio.disponível() função verifica se os dados estão disponíveis, e o wire.read() função lê os dados enviados pelo dispositivo mestre.
Código do dispositivo escravo:
motores de busca que não filtram resultados
#include <Wire.h>
void setup() {
Wire.begin(8); // join the I2C bus with address 8
Wire.onReceive(receiveEvent); // call receiveEvent when data is received
}
void loop() {
delay(100);
}
void receiveEvent(int bytes) {
Wire.write("hello "); // respond with message of 6 bytes as expected by master
}
Enviando e recebendo dados usando I2C
Neste exemplo, vamos ler a temperatura de um sensor de temperatura DHT11 interfaceado com o Arduino escravo e imprimir no monitor serial do Arduino mestre.
Vamos modificar o código que escrevemos anteriormente para incluir a medição de temperatura que enviaremos para a placa mestre pelo barramento I2C. A placa mestre pode então ler o valor que enviamos e exibi-lo no monitor serial.
Código do dispositivo mestre:
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("Master Initialized!");
}
void loop() {
Wire.requestFrom(8, 1); // Request temperature data from slave
if (Wire.available()) {
byte temperature = Wire.read(); // Read temperature data from slave
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
}
delay(2000); // Wait for 2 seconds before requesting temperature again
}
Código do dispositivo escravo:
#include <Wire.h>
#include <DHT.h>
#define DHTPIN 4 // Pin connected to DHT sensor
#define DHTTYPE DHT11 // DHT sensor type
DHT dht(DHTPIN, DHTTYPE);
byte temperature;
void setup() {
Wire.begin(8); // Slave address is 8
Wire.onRequest(requestEvent);
dht.begin();
}
void loop() {
delay(2000); // Wait for 2 seconds for DHT to stabilize
temperature = dht.readTemperature(); // Read temperature from DHT sensor
}
void requestEvent() {
Wire.write(temperature); // Send temperature data to master
}
Você pode personalizar este código para se adequar a quaisquer sensores que você possa ter em seu projeto, ou até mesmo exibir os valores do sensor em um módulo de exibição para faça seu próprio termômetro e medidor de umidade .
Endereçamento Escravo com I2C no Arduino
Para ler os valores dos componentes adicionados a um barramento I2C em tal projeto, é importante que você inclua o endereço escravo correto ao codificar. Felizmente, o Arduino oferece uma biblioteca de scanner que simplifica o processo de identificação de endereços escravos, eliminando a necessidade de vasculhar longas folhas de dados do sensor e documentação on-line confusa.
Use o código a seguir para identificar o endereço de qualquer dispositivo escravo presente no barramento I2C.
#include <Wire.h> // Include the Wire library for I2C communication
void setup() {
Wire.begin(); // Initialize the I2C communication
Serial.begin(9600); // Initialize the serial communication with a baud rate of 9600
while (!Serial); // Wait for the serial connection to establish
Serial.println("\nI2C Scanner"); // Print a message indicating the start of I2C scanning
}
void loop() {
byte error, address; // Declare variables to store errors and device addresses
int nDevices; // Declare a variable to store the number of devices found
Serial.println("Scanning..."); // Print a message indicating the start of I2C scanning
nDevices = 0; // Set the number of devices found to 0
for (address = 1; address < 127; address++) { // Iterate over all possible I2C addresses
Wire.beginTransmission(address); // Start a transmission to the current address
error = Wire.endTransmission(); // End the transmission and store any errors
if (error == 0) { // If no errors were found
Serial.print("I2C device found at address 0x"); // Print a message indicating a device was found
if (address < 16) Serial.print("0"); // If the address is less than 16, add a leading 0 for formatting purposes
Serial.print(address, HEX); // Print the address in hexadecimal format
Serial.println(" !"); // Print a message indicating a device was found
nDevices++; // Increment the number of devices found
}
else if (error == 4) { // If an error was found
Serial.print("Unknown error at address 0x"); // Print a message indicating an error was found
if (address < 16) Serial.print("0"); // If the address is less than 16, add a leading 0 for formatting purposes
Serial.println(address, HEX); // Print the address in hexadecimal format
}
}
if (nDevices == 0) { // If no devices were found
Serial.println("No I2C devices found\n"); // Print a message indicating no devices were found
}
else { // If devices were found
Serial.println("done\n"); // Print a message indicating the end of I2C scanning
}
delay(5000); // Delay for 5 seconds before starting the next scan
}
Expanda seu projeto hoje
A interface de duas placas Arduino usando o protocolo de comunicação I2C oferece uma maneira flexível e eficiente de realizar tarefas complexas que não podem ser realizadas por uma única placa. Com a ajuda da biblioteca Wire, a comunicação entre as duas placas usando I2C é facilitada, permitindo que você adicione mais componentes ao seu projeto.