Curso de Arduino y robótica: Protocolo I2C

Durante nuestro curso de Arduino, ya hemos visto la forma más simple de programar nuestra placa para controlar otros dispositivos con el formato más simple de señal entrada salida.

Al fin y al cabo, es cuestión de comunicar información de un dispositivo a otro. Pero las comunicaciones entre componentes pueden ser más avanzadas y definir todo un protocolo.

En tutoriales anteriores ya vimos los formatos más simples de comunicación.

Nos falta por estudiar los formatos de comunicación más avanzados disponibles en Arduino.

  • Comunicación I2C
  • Comunicación por SPI – ICSP

Aunque existen unos cuantos más como la comunicación ModBus, CANBus, etc… Pero que no vamos a ver en este curso, ya que la mayoria de componentes de Arduino se encuentran adaptados para funcionar por I2C o por SPI.

¿Qué es I2C?

I2C es un sistema de comunicación bidireccional basado en 2 hilos, el SDA (Datos) y el SCL (reloj) muy parecido al formato de comunicación Serial. I2C significa Inter-Integrated Circuit (Inter-Circuitos Integrados). desarrollada en el año 1980 por Philips cuya patente caducó en 2006. La velocidad es de 100 kbit/s en el modo estándar, aunque también permite velocidades de 3.4 Mbit/s.

Tres reglas son suficientes para comprender el protocolo I2C.

  • Los componentes I2C contienen una dirección física de acceso.
  • El protocolo I2C es síncrono
  • El protocolo se basa en peticiones «Master – Slave» ( Maestro – Esclavo )

Dirección Física

Se basa en un sistema de comunicación por dirección física de los elementos, esto quiere decir que si conectamos más de un componente por I2C, al usar solo dos cables de transmisión de datos para todo, la placa debe reconocer cada uno de los componentes por un ID o dirección física interna para diferenciarlos.

Esta dirección se encuentra dentro de la señal y todos los componentes conectados cuyo ID no coincide con su dirección dejará pasar la señal para otro componente y solo atenderá a la señar que contiene la suya.

Protocolo síncrono

Uno de los aspectos más importantes a entender de la señal I2C, es que es síncrona. Eso quiere decir que el envío y recepción de datos está sincronizado con una señal de reloj que comparte con la placa de Arduino.

I2C usa solo 2 cables, uno para el reloj (SCL) y otro para el dato (SDA). Esto significa que el maestro y el esclavo envían datos por el mismo cable, el cual es controlado por el maestro, que crea la señal de reloj. I2C no utiliza selección de esclavo, sino direccionamiento.

Maestro esclavo

El microcontrolador principal (Master) se encarga de hacer las peticiones a las direcciones físicas de los dispositivos y con ordenes concretas a los accesos de memoria y de cómo esté programado internamente cada dispositivo.

 

Dispositivos más utilizados para comunicación por I2C

Los dispositivos que se suelen utilizar con Arduino por I2C dependerán de las necesidades del fabricante, pero en esencia podemos definir los siguientes componentes que nos ayudarán en nuestros proyectos con Arduino.

  • Pantallas LCD – Muy útil para no realizar cableado infinito
  • Acelerómetro, giroscopio, magnetómetro – IMU MPU6050 – MPU9250
  • Lector tarjetas RFID
  • Shields de extensión para servomotores
  • Algunas pantallas OLED

Es importante reconocer cuáles son los pines I2C a conectar con nuestra placa. Para las placas Arduino UNO o NANO, usaremos siempre el pin analógico A4 y A5 para conectar los pines SDA y SCL respectivamente.

En caso de conectar con otras placas podemos consultar los pines de conexión en la siguiente tabla.

Board I2C / TWI pins
Uno, Ethernet A4 (SDA), A5 (SCL)
Mega2560 20 (SDA), 21 (SCL)
Leonardo 2 (SDA), 3 (SCL)
Due 20 (SDA), 21 (SCL), SDA1, SCL1

Como programar y detectar la dirección física de nuestros módulos

El protocolo I2C requiere de la librería Wire que viene instalada por defecto en Arduino.

Las funciones más básicas que podemos encontrar en la librería Wire, son las siguientes.

  • begin() – Inicia la librería Wire y especifica si es master o slave
  • requestFrom() – Usado por el maestro para solicitar datos del esclavo
  • beginTransmission() – Comenzar transmisión con esclavo.
  • endTransmission() – Finaliza la transmisión que comenzó con un esclavo y transmite los bytes en cola.
  • write() – Escribe datos desde un esclavo como respuesta a una petición del maestro o pone en cola la transmisión de un maestro.
  • available() – Devuelve el número de bytes para leer
  • read() – Lee un byte transmitido desde un esclavo a un maestro o viceversa
  • onReceive() – Llama a una función cuando un esclavo recibe una transmisión de un maestro. Registra una función de callback.
  • onRequest() – Llama a una función cuando un maestro solicita datos de un maestro. Registra una función de callback.

 

#include <Wire.h>
 
 
void setup()
{
  Wire.begin();
 
  Serial.begin(9600);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {

    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknow error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

Al abrir el monitor serie nos encontrará las direcciones de los componentes I2C que luego usaremos en posteriores programas.

Si nuestro proyecto contiene múltiples componentes I2C, aunque ya sepamos cuál es su dirección, este programa debería ser el primero a programar para revisar cuáles son las direcciones físicas que posteriormente utilizaremos para mandar los datos.

 


Una vez completado este tutorial, puedes acceder al siguiente nivel.

 

Los ejercicios de código, proyectos y recursos que desarrollaremos durante el curso se pueden consultar a través de nuestro Github.

Documentacion ZaragozaMakerSpace Github

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

dieciocho + doce =

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.