El bus I2C es un protocolo de comunicación síncrona que permite la interacción entre microcontroladores y dispositivos (como sensores, memorias, convertidores analógico-digitales, entre muchos otros).
Uno de los puntos más interesantes del I2C es que nos permite conectar varios dispositivos a través de solo dos líneas:
- SDA (Serial Data Line)
- SCL (Serial Clock Line)
Esto nos permite ahorrar pines de E/S en el microcontrolador, y líneas de comunicación nuestro proyecto. Ambas líneas requieren resistencias pull-up.
El controlador I2C supervisa la comunicación entre dispositivos a través del bus I2C. Este controlador incluye las siguientes funciones:
- Modo maestro: Puede iniciar la comunicación, leer y escribir bytes
- Modo Esclavo: Puede leer y escribir bytes, si previamente un maestro se comunica con él
Si no sabes lo que es el bus I2C o necesitas más ayuda consulta estas entradas:
El bus I2C en el ESP32
El ESP32, ESP32-S2 y ESP32-S3 tienen dos controladores de I2C, mientras que el ESP32-C3 tiene uno.
El uso del I2C en el ESP32 es muy similar a lo que encontraríamos en un Arduino convencional o en un ESP8266
El Core del ESP32 en Arduino ofrece la biblioteca Wire.h
con las funciones ofrecidas para I2C. Por otro lado, el objeto que gestiona un controlador I2C se llama TwoWire
.
Una vez que el terreno está preparado, puedes iniciar la comunicación I2C en tu código:
void setup() {
// Iniciar comunicación I2C
Wire.begin();
}
La mayor diferencia es que, en el caso del ESP32, podemos remapear el controlador I2C sin pérdida de rendimiento.
En algunos modelos el controlador I2C viene preconfigurado por defecto a ciertos pines. Pero por ejemplo, en el ESP32-S3
Model | SDA | SCL |
---|---|---|
ESP32 | 21 | 22 |
ESP32-S3 | - | - |
No hay problema, siempre podemos decidir que pines podemos usar
Wire.begin(I2C_SDA, I2C_SCL);
De hecho, por compatibilidad y evitaros errores, no está de más que lo indiquéis siempre explícitamente.
Cómo usar I2C en ESP32 en el entorno de Arduino
El uso del bus I2C en el ESP32 en el entorno de Arduino es muy similar a hacerlo en un Arduino convencional. Ahí van unos ejemplos.
Enviar Datos
byte dataToSend = 0x42; // Datos a enviar
byte slaveAddress = 0x50; // Dirección del dispositivo esclavo
Wire.beginTransmission(slaveAddress); // Iniciar transmisión al dispositivo
Wire.write(dataToSend); // Enviar datos
Wire.endTransmission(); // Finalizar transmisión
Recibir Datos
byte receivedData;
int bytesToRead = 1; // Cantidad de bytes a leer
Wire.requestFrom(slaveAddress, bytesToRead); // Solicitar datos al dispositivo
if (Wire.available()) {
receivedData = Wire.read(); // Leer datos recibidos
}
Usando múltiples bus I2C en el ESp32
Como hemos dicho, el ESP32, ESP32-S2 y ESP32-S3 tienen dos controladores de I2C, por lo que podemos crear dos redes de dispositivos simultáneas.
#include <Wire.h>
// reemplazar por los pines que queráis usar
const int SDA_1 = 0;
const int SCL_1 = 0;
const int SDA_2 = 0;
const int SCL_2 = 0;
TwoWire MyI2C_1 = TwoWire(0);
TwoWire MyI2C_2 = TwoWire(1);
void setup() {
MyI2C_1.begin(SDA_1, SCL_1, freq1);
MyI2C_2.begin(SDA_2, SCL_2, freq2);
}
void loop()
{
delay(1000); // do nothing
}