Mejora tu programación con Arduino: comunicación I2C

Anteriormente trabajamos con el protocolo de comunicación para periféricos SPI, y con el logramos mandar datos desde nuestro Arduino al registro de corrimiento. También existe el protocolo IIC o I2C, que significa Inter Integrated Circuit. Es muy util para comunicar un microcontrolador con dispositivos externos. Combina las ventajas de UART y SPI, ya que solo utiliza 2 cables de comunicación y permite manejar distintos dispositivos esclavos, sin embargo, su velocidad de transmisión es mas baja.

Es un tanto más complicado que el protocolo SPI, ya que tiene más pasos a seguir para transmitir la información. También es necesario que el microcontrolador cuente con el puerto I2C, a diferencia del protocolo UART que podemos implementarlo por software.

Resumen: En este tutorial vamos a comunicar dos arduinos entre sí, lo que permitirá comprender como se manejan los paquetes de datos con este protocolo.

Como mencionamos, solo se tienen dos cables para transmitir los datos, SCL y SDA, correspondientes a la señal de reloj y la de datos, respectivamente.

Para empezar la comunicación se requiere enviar los paquetes de datos con el siguiente formato: un bit de INICIO, una DIRECCIÓN de 7 a 10 bits, un bit de LECTURA/ESCRITURA y un bit de CONFIRMACIÓN que puede afirmar o negar la correcta comunicación. Seguido de esto se pueden enviar datos de 8 bits con su respectivo bit de confirmación, para finalizar con un bit de paro.

El programa para el Arduino maestro en esencia establece la comunicación serial con la PC y la comunicación I2C, después, pide al Arduino esclavo que mande 6 bytes, y cada byte lo guarda como caracter, que después imprime en el monitor serial.

#include <Wire.h>
// Este código inicia la comunicación, recibe los datos del esclavo y los imprime
void setup() {
  Wire.begin();        // Esta función inicia el protocolo
  Serial.begin(9600);  // Comenzar la comunicación serial con la PC
}

void loop() {
  Wire.requestFrom(8, 6);    //Pedir 6 bytes del dispositivo esclavo

  while (Wire.available()) { // Revisar si el esclavo mandó los 6 bytes
    char c = Wire.read(); // guardar el byte recibido como caracter
    Serial.println(c);         // imprimir el caracter en el monitor serial
  }
  delay(500);
}

Para el Arduino esclavo le indicamos que inicie la comunicación I2C con la dirección 8 y creamos un evento que depende del protocolo serial, cuando se registra el evento se ejecuta la función que manda los 6 bytes.

#include <Wire.h>

void setup() {
  Wire.begin(8);            // unirse a la comunicación con la dirección 8
  Wire.onRequest(requestEvent); // registrar evento
}

void loop() {
  delay(100);
}

// esta función se ejecuta cuando el maestro pide un dato
// esta función se registra como un evento, descrita en el setup()
void requestEvent() {
  
  Wire.write("hola! "); // responder con un mensaje de 6 bytes
  // como espera el dispositivo maestro
}

A continuación se muestra la conexión de los Arduino, si se planea utilizar la misma fuente de alimentación (USB) se puede utilizar el pin de 5V para energizar ambas tarjetas.

El monitor serial debería mostrar el string que programamos en el Arduino esclavo.

Con este tutorial vimos como establecer la comunicación I2C mediante la libreria Wire.h y las funciones asociadas, para utilizar este protocolo con otros periféricos basta con seleccionar la dirección correcta y leer los registros adecuados.

Referencias:

Basics of I2C communication protocol

Comentarios