esp32-i2c

Cómo usar el bus I2C en un ESP32

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

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

ModelSDASCL
ESP322122
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
}