G031 El Bus I2C

Descripción 
A medida que la capacidad integración en un único chip aumentaba, el número de  bloques de construcción electrónicos integrados en un único chip, pero cuando tu diseño requería usar una docena de esos bloques, ponerlos de acuerdo y conseguir que se comunicaran, se convirtió en un problema.

Por eso, en los 80, uno de los grandes fabricantes de electrónica (Phillips), propuso una norma de comunicación digital, entre los diferentes componentes de una sistema electrónico.
Una norma que especificaba la velocidad, niveles de tensión,  y el protocolo a seguir para conseguir esa comunicación y la hizo abierta para que todo el mundo pudiera usarla.

Esa norma se llamó Inter Integrated Circuits bus, o IIC = I2C = I2C y pronto se convirtió en un estándar de facto en la industria. Las especificaciones han ido mejorando con los años, pero la idea básica sigue siendo la misma:

Protocolo de dos hilos de control, uno para transmitir los datos, SDA y otro, el reloj asíncrono que indica cuando leer los datos SCL. Mas GND y 5V (cuando se requiera).

Cada dispositivo conectado al bus I2C y cada uno tiene su dirección exclusiva, de 7 bits, (Asi que, en teoría, podemos conectar 27 = 128, dispositivos).


Uno de estos componentes, debe actuar como master, es decir controla el reloj.

No se requiere una velocidad de reloj estricta, ya que es el master quien controla el Clock.

Es multi master, el master puede cambiar, pero solo uno puede estar activo a la vez, y proporciona un protocolo de arbitraje y detección de colisiones. (Si no has entendido esto, no te preocupes, todavía es pronto).
 
Puedes encontrar que a este bus se le llama, IIC, I2C o I2C, y también, como TWI (Two Wire Interface, o interface de 2 hilos), pero siempre es lo mismo.
 
La idea es que todos los componentes se conecten en paralelo a las dos líneas del Bus, SDA y SCL. En cada momento solo puede haber un master, en este caso, Arduino y los demás se configuran como esclavos.

Puede haber más de un master. La norma propone un sistema de arbitraje, para transferir el control de uno a otro, pero en un instante dado, solo uno puede ser el master de ese instante el que haga de árbitro.

Hay unas resistencias de Pullup conectadas a SDA y SCL. Son OBLIGATORIAS, ya que el bus es activo bajo (Esto es, la señal activa es un 0, no un 1. Pero tranquilo, que esto no te afecta)

Cuando vayas a conectar algo al bus I2C, es imprescindible que leas el manual para saber si los pullups los tienes que poner tú, o vienen puestos en el componente.

En el caso del display I2C que vamos a usar, normalmente incluyen los pullups.
 
Arduino lo soporta de fábrica con una librería estándar, que utiliza dos de los pines analógicos para las funciones SDA (Datos) y SCL (Clock).

En el Arduino UNO, los pines I2C están en los pines analógicos A4 (SDA) y A5 (SCL).
En el Arduino Mega y DUE, son el 20 (SDA) y en el 21(SCL).
 
La librería I2C, en Arduino se llama Wire (para que no os confiéis), y gestiona el protocolo de comunicaciones completo, lo que es un detalle, pues nos ahorra la parte aburrida de estudiar el protocolo y escribir programas para ello.

Esto no es vagancia, sino construir sobre el trabajo de terceros. Es una de las muy grandes virtudes de la comunidad Arduino. Muchas librerías para incorporar a nuestros proyectos, sin necesidad de mancharte las manos de grasa.
 
Vamos a conectar un display LCD 1602A de 16×2 con interface I2C, y así se puede comprobar porque en la última sesión os recomendé usarlo, en lugar del que se conecta directamente con 16 pines.
Pero antes, tenemos que asegúranos de otro asunto.
 
Scanner de I2C
Cada componente que conectamos al bus I2C tiene una dirección única, y cada mensaje y orden que transmitimos al bus, lleva anexa esta dirección, indicando cuál de los muchos posibles, es el receptor del mensaje.

Pero, claro, esto implica que sabemos la dirección del componente. Lo normal es comprobar la información técnica del fabricante del componente, y ahí suele decirnos cuál es la dirección por defecto.

Pero como ya sabemos, que en la vida las cosas rara vez son como en los cuentos, algún alma caritativa (y con mucho mundo a sus espaldas), hizo un programita para Arduino, que nos informa, de lo que hay en nuestro bus y con qué dirección.  Es programa es I2C scanner
Naturalmente, este programa, no tiene ni idea de quien responde y lo que hace, pero bastante es que nos informe de que hay alguien en la dirección xx.
#include <Wire.h>
 
void setup() {
  Wire.begin();
  Serial.begin(115200);
  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.println(address,HEX);
      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);          
}

Si no sabemos en qué dirección está un componente dado, basta con colocarlo solo en el bus, y ver qué dirección nos reporta el I2C scanner. EL resultado para el LCD que tengo es 0x27 Hexadecimal.
 
 




Así que ya podemos pasar a hablar de como programar  el uso del display.
 
Materiales
Placa de Arduino
Display LCD 1602A
Protoboard, Cables para conexiones, un Cable USB para conectar el Arduino al PC y que sirve además de Alimentación

Esquema
Importante los pines del módulo del bus I2C puede venir cambiados de sitio, lo importante es que SCL vaya la entrada A5 y SDA vaya a la entrada A4.

 
La conexión es, nuevamente, trivial: 
Simplemente Arduino A4 a SDA (Datos) y A5 a SCL (Clock), más GND y alimentación. 

Muchas placas de Arduino UNO suelen traer dos pines  SCL y SDA que se pueden usar en lugar de los pines A4 y A5.  Funcionan exactamente igual, es indistinto si utilizas uno u otros, incluso los puedes combinar, aunque no lo recomiendo, porque luego puede dar lugar a confusión.

Si cambias los cables para probar su uso y te empizan a salir caracteres extraños en la pantalla LCD, no te asustes, simplemente pulsa el botón de reset y todo vuelve a la normalidad con las nuevas conexiones.






Montaje


Código
Lo primero, es que descargar una nueva librería para maneja el display con I2C, Se llama LiquidCrystal_I2C y es un añadido para la librería estándar que viene con tu Arduino


Ahora vamos a incluir la librería I2c que en Arduino se llama Wire, y como es estándar la 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

Vamos ahora a definir la dirección de nuestro display. En mi caso la 0x27
#define I2C_ADDR 0x27

Y por último creamos una instancia del objeto LiquidCrystal_I2C donde especificamos los parámetros del constructor  (dirección de memoria, número de columna y número de filas) en este caso pone I2C_ADDR porque definimos esta variable con la dirección, pero se puede poner perfectamente  0X27 que sería el dirección.
LiquidCrystal_I2C lcd(I2C_ADDR, 16, 2);

Aquí tenemos el código completo que mostrará en la pantalla un contador de segundos. Primero hago un poco de publicidad durante los primeros 5 segundos y luego empieza a aparecer la cuenta de 6, 7, 8... segundos.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR 0x27

LiquidCrystal_I2C lcd(I2C_ADDR, 16, 2);

void setup()
{
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0,0);
    lcd.print("MAGOMIGUELON.ES");
    lcd.setCursor(0,1);
    lcd.print("ELECTRONICS");
    delay(5000);
    lcd.setCursor(0,0);
    lcd.print("                 ");
    lcd.setCursor(0,1);
    lcd.print("                 ");
}

void loop(){
  lcd.setCursor(0,0);
  lcd.print("HAN PASADO");
  lcd.setCursor(0,1);
  lcd.print(millis()/1000);
  lcd.print(" SEGUNDOS");
}


No hay comentarios:

Publicar un comentario