bclose

El bus I2C

Arduino y el bus I2C

Objetivos

 

 

    • Comprender el bus I2C.
    • Conectar un display I2C.
    • Enviando mensajes a la pantalla

 

Material requerido.

 

 Tienda EspañaTienda Mexico
Kit Arduino Uno Kit inicio UNOKit inicio UNO
Kit Arduino MEGAKit Inicio MegaKit Inicio Mega

 

El bus I2C

 

A medida que la capacidad integración en un único chip aumentaba, el número de componentes comerciales disponibles, aumentaba exponencialmente. Cada vez era, y es, más sencillo fabricar bloques de construcción electrónicos integrados en un único chip, y pronto el grosor de los catálogos de los fabricantes, engordó peligrosamente.

Era relativamente fácil encontrar esos bloques de construcción pero cuando tu diseño requería usar una docena de esos bloques, ponerlos de acuerdo y conseguir que se comunicaran eficazmente, se convirtió en un problema.

Por eso, en los primeros 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.

Esa norma se llamó Inter Integrated Circuits bus, o IIC, 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 I2C, IIC o I2C, y también, como TWI (Two Wire Interface, o interface de 2 hilos), pero siempre es lo mismo.

Arduino y el I2C

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, nuestro Duino 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.
  • Fijaros también que hay unas resistencias de Pullup conectadas a SDA y SCL. Son imperativas, 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 busI2C, 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.
 

Y la buena noticia es que nuestro 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.
 

En esta sesión vamos a conectar un display LCD de 16×2 con interface I2C, y así podréis 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. 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.

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.

Informe I2C scan

 

Así que ya podemos pasar a hablar de como programar  el uso del display.

 

Diagrama de conexión

 

La conexión es, nuevamente, trivial:

Img_34_2

Simplemente Arduino A4 a SDA (Datos) y A5 a SCL (Clock), más GND y alimentación. Vamos con el programa.

 

Programa de control

 

Lo primero, es que descarguéis 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 Duino (tranquilo no duele y debería ser automático).

No he encontrado información del autor o autores, y solo he visto que hacen referencia a que el nombre de la librería es Malpartida (A mí no me miréis).

Descarga la librería LiquidCrystal_I2C , y vamos a instalarla lo primero

\\Programa\ImportarLibreria\Añadir \Librería

Busca en tu directorio de descargas, la librería LiquidCrystal_I2C .zip y haz doble click, para que se instale en nuestro IDE.

Ahora vamos a incluir la librería I2c que en Arduino se llama Wire, y como es estándar la incluyes con:

\\Programa\ImportarLibreria\Wire

Ahora hay que incluir la librería LiquidCrystal normal y después la de LiquidCrystal_I2C.Deberiamos tener 3lineas como estas:

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

Vamos ahora a definir una variable con la dirección de nuestro display. En mi caso la 0x27

byte dir = 0x27   // Ese 0x significa que es hexadecimal, no decimal

Y por último creamos una instancia del objeto LiquidCrystal_I2C:

LiquidCrystal_I2C             lcd( dir, 2, 1, 0, 4, 5, 6, 7);

Al que le pasamos la dirección dir del display y varios números que indican que pines debe usar la librería para el display, no de Arduino. Ignóralo y lo copias así para los displays. El resto queda así:

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

#define I2C_ADDR    0x27

LiquidCrystal_I2C             lcd(I2C_ADDR,2, 1, 0, 4, 5, 6, 7);
void setup()
   {
       lcd.begin (16,2);    // Inicializar el display con 16 caraceres 2 lineas
       lcd.setBacklightPin(3,POSITIVE);
       lcd.setBacklight(HIGH);

       lcd.home ();                   // go home
       lcd.print("Prometec.net");
       lcd.setCursor ( 0, 1 );        // go to the 2nd line
       lcd.print("Malpartida lib");
   }
void loop() 
   {}

Aquí tenéis el resultado:

Display 16x2 I2C

 

Resumen de la sesión

 

En esta curso de arduino hemos aprendido lo siguiente:

 

 

    • Hemos presentado los displays LCD de 16×2 I2C
    • Funciona igual que los normales, pere requieren muchos menos cables para instalarlos y se evitan montones de problemas.
    • Muy practicos y cuestan poco mas que uno normal.
 

 

 

 

 

 

Para porder realizar consultas a nuestros expertos, tienes que ser suscriptor. Suscribiendote nos ayudas a mantener este proyecto en marcha.

¡ Quiero Suscribirme !

Si ya eres premium y no puedes comentar haz login. Hacer login

(238) Comments

  • Indisplensable la aplicacion I2C Scanner, despues de pelearme durante meses con los display 1602 y 2004 resulta que la direccion es 2x3F.
    Gracias.

      • Ivan Uriarte

      Cuanta razón Jose, es lo primero que hay que comprobar para ahorrarse algún que otro disgusto. Un saludo.

    • Cristian

    Buenas, Muchas gracias por los tutoriales son excelentes!!! Quería preguntar por que mis lcd se ven con poco contraste, es apenas visible. Los datos o carteles que cargo salen bien. Estoy ajustando desde el preset, casi no varia nada.

      • Ivan Uriarte

      El contraste se ajusta con el potenciómetro que tiene el LCD por la parte de atrás.

    • Antonio javier

    Hola, como soy nuevo en esto de arduino, tengo que leer mucho, y gracias a tu pagina he podido solucionar un problemilla. Una pantalla lcd no me funcionaba, la dirección( en teoria definida era 0x27) pero al conectarla solo se encendia y se veia una linea pero no salia nada. Tras leer decian que habia pantallas con otras direcciones y asi. Di con tu programa de scanner y la direccion era 0x3f. Problema solucionado. Pero ahora me surgen dudas:
    Por que se cambio la dirección
    Se puede a volver a poner una direcion a un modulo

      • Ivan Uriarte

      Hola Antonio, no es que se haya cambiado, es que depende del fabricante a veces vienen con una u otra dirección, aunque siempre suelen ser esas. Si quieres cambiarle la dirección, por ejemplo si tuvieras varias pantallas iguales y quieres usar todas, puedes probar a alguna o todas las conexiones C1, C2 y C3, de esa forma puedes tomar hasta 8 direcciones diferentes.

  • hola que tal, tengo una lcd de 20×4 pero no manda el mensaje, la i2c trabaja con comunicación 0x3f, pero por mas que lo intento no manda el mensaje a la placa LCD 20×4, cual será el problema y que solución podría resolverlo?. espero su respuesta gracias

      • Ivan Uriarte

      Hola Jesús, asegúrate que esa es la dirección de tu pantalla usando el i2c scanner que puedes encontrar en esta sesión. Por otra parte, prueba a ajustar el contraste con el potenciómetro de detrás de la pantalla. También comentarte que si usas la librería que tenemos aquí, para utilizar las líneas 3 y 4 tienes que hacer como si fueran los caracteres a partir del 20 de las líneas 1 y 2. Un saludo.

    • Bahia

    He comprado en la tienda una lcd 16×02 i2c y he seguido el tutorial, me sale el siguiente mensaje de error:
    Arduino:1.8.2 (Windows 8), Tarjeta:”Arduino/Genuino Uno”
    D:\usuario\Documents\Arduino\libraries\LiquidCrystal_I2C\I2CIO.cpp:35:26: fatal error: ../Wire/Wire.h: No such file or directory
    #include
    compilation terminated.
    exit status 1
    Error compilando para la tarjeta Arduino/Genuino Uno.
    He realizado lo que se indica en uno de los comentarios:Ese error puedes solucionarlo yendo al archivo I2CIO.cpp y sustituyendo #include por #include NO ME FUNCIONA. Tengo problema al cambiar la linea y guardarla pues no me deja.
    Gracias de antemano por la ayuda.

      • Ivan Uriarte

      Puede ser que tengas que cambiar los permisos de ese archivo para que te deje modificarlo. Puedes entrar en sus propiedades y hacerlo. Un saludo.

        • Armandux

        busca en el archivo de D:\usuario\Documents\Arduino\libraries\LiquidCrystal_I2C\I2CIO.cpp:35:26, quita ../Wire/ para que quede direccionado correctamente. Saludos

    • Estimado

      El error se refiere a la ubicacion del archivo Wire.h que está declarado en el archivo I2CIO.cpp de la libreria LiquidCrystal_I2C. Por lo tanto para solucionar este problema, primero deber buscar la ubicacion del archivo “Wire.h” en tu pc, luego debes editar el archivo I2CIO.cpp en un editor de texto como notepad2. Encuentra la linea que aparece “#include ” y la modificas por “#include “.
      En mi caso la tuve que modificar por #include
      Una vez hayas realizado la modificación, guardas el archivo manteniendo la extensión. Compilas y todo ok. Espero te ayude.

      • Ubicas linea #include y la modificas por #include . En mi caso utilicé
        #include

    • Arturo

    Muchas Gracias por el tema. Muy Util el Scan. Gran detalle Jorge. Soy nuevo con Arduino, y probando dos LCD, una 16×2 y otra 20×4, me arrojaba direccion 0x3F, por lo que si las conectaba ambas iba a tener duplicidad de direccion. Voy a probar con los 3 puentes q trae: A0, A1 y A2.
    Tambien me salia solo el primer caracter de un mensaje. Lo pude solucionar enviando de a 1 caracter. Aun no puedo enviar mensajes de varios caracteres.

      • Ivan Uriarte

      Que raro lo de los caracteres. ¿Tienes la librería actualizada?

  • Hola, por que puede ser que solo me aparecen las dos primeras letras de cada linea? Gracias!!

      • Ivan Uriarte

      Hola Paco, pues no tengo mucha idea, yo lo primero que haría sería borrar la librería y descargar la más nueva que haya, a ver si se soluciona por ahí. un saludo.

    • Pascual

    Hola quisiera hacer una pregunta al foro. Tengo un LCD que no sigue exactamente el mismo patillaje que otros LCD que he visto aquí. Qué modificaciones sugerís para poder usar un módulo que por I2C puede manipular las 16 salidas que tiene.
    Gracias

      • Ivan

      Sin saber el modelo de display no sé que decirte. Por lo demás creo que hay adaptadores para I2C. Un saludo.

  • disculpa tengo un arduino due he intento cargar el ejemplo y no funciona, no se si sea problema de la librería.

      • Admin

      Prueba con la nueva libreria por si acaso:

      Busca en internet “LiquidCrystal_I2C github” y de ahi podras bajar la ultima revision

    • Carlos Coronado

    Hola, primero que todo te felicito por la pagina Web, a mi me ha servido mucho para aprender. Bueno te cuento que tengo un problema con una pantalla LCD 20×4 I2C, yo configure el Arduino UNO para que muestre unos datos sobre la pantalla LCD, eso lo hace muy bien, el problema apareció cuando al Arduino UNO le instale el Shield GSM/GPRS SIM900, después de eso no muestra ninguna información. Para el I2C uso los pines A4 y A5. Retiro el Shield GSM/GPRS y la pantalla LCD funciona sin problemas. ¿Qué puede estar pasando?

      • Ivan

      Hola Carlos, ¿qué shield estás usando? SI es como el que usamos nosotros no debería darte ningún problema. A ver si tengo un rato y pruebo a hacerlo y te comento el resultado. Un saludo.

    • Max

    Hola hace unos dias compre en esta tienda unos 6 LCD i2c 😀 funcionan todos perfectos en un arduino uno, el problema llega cuando quiero hacer tu sketch con el arduino YUN es posible que tenga que cambiar algo ya que no me detecta ni la pantalla con el i2c scanner me refiero a los pines digitales y analogicos he leido por ahi que puede ser que el YUN use otros pero no me queda nada claro si me puedes ayudar seria perfecto gracias !

      • Admin

      Hola Max,

      Me temo que no he usado casi nada el Yun y no me atrevo adarte opinion sin uno para hacer pruebas. Lo siento

  • Hola, recientemente compré el ad5933 de digilent para trabajar con impedancias pero no sé cómo usarlo con arduino, solo se que trabaja con i2c

      • Admin

      Hola Marlon, me temo que no conozco ese chip

    • Iñigo Garmendia

    Hola, espectacular post! Tengo un arduino UNO Y una LCD I2C. Al principio probé con bastantes librerías de otros webs . Algunas me compilaban y otras no y las que compilaban no hacían nada, esto es no funcionaban. El otro día me paso una el profesor y por fin me apareció algo , pero solo la primera letra de cada fila. No se cual es el problema. He probado con tantas librerias que ya no se cual no he utilizado. Cual puede ser el problema? Puede ser algo que no sea la librería? Si es la librería, por una parte me gustaría saber que librería es la buena y si aparte de esa y la librería wire se necesita otra librería como liquidcrystal o lcd.h ?Ya que en cada post usan una diferente. Tengo prisa ya que solo me falta esto para entregar el proyecto que seria para el 23. Gracias de antemano.

      • Ivan

      Hola Iñigo, si es una pantalla i2c como la de la sesión necesitarás la linrería liquidcristal:I2C que indicamos en la sesión. Prueba a hacerlo como en la sesión y si te da un error como este:

      Fatal error: ../Wire/Wire.h: No such file or directory

      libraries/LiquidCrystal_I2C/I2CIO.cpp

      tienes que cambiar una línea del archivo I2CIO.cpp de la librería y buscar una línea que pone #include < .../Wire/Wire.h>. Ahí sustituye el …/Wire/Wire.h por Wire.h

      • Pedro

      Hola, Yo tenia el mismo problema con la lcd. Usa el Arduino 1.5.7, te escribirá perfectamente en la lcd. Al menos a mi me funcionó.

    • GERARD

    Hola!

    Estoy probando de hacer funcionar este display, pero no lo consigo.
    Primero he conectado los cables con sus pines correspondientes en el Arduino UNO.
    Seguidamente, he averiguado la dirección del BUS, obteniendo este resultado:

    I2C Scanner
    Scanning…
    I2C device found at address 0x3F !
    done

    Y finalmente, he instalado la librería que recomiendas y he compilado y cargado el sketch, modificando simplemente este línea:

    #define I2C_ADDR 0x3F

    El resultado es un montón de números en las dos líneas de la pantalla que corren sin cesar.
    Qué estoy haciendo mal? Tengo otra pantalla, con dirección 0x27 y no me da ningún problema.
    Gracias de antemano!

    Gerard

      • Ivan

      Hola Gerard, las direcciones que suelen tener estas pantallas son esas 0x27 y 0x3F. Debería funcinar simplemente cambiando esa línea o poniendo LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

    • Alfonso

    Hola Amigo, creo que me has solucionado una de las dudas que tenia, pero no estoy seguro. ¿Puedo conectar una pantalla LCD a través de i2c y también puedo conectar un reloj de tiempo real? ¿La instalación tan solo seria unir los cables de datos? Un saludo.

      • Ivan

      Hola Alfonso, en principio puedes conectar todos los dispositivos I2C que quieras mientras tengan diferentes direcciones. El reloj y el LCD puedes conectarlos sin problemas. Ambos los conectarías a los pines SCA y SDL de Arduino, además de alimentarlos. Aquí tendrías exactamente lo que buscas: https://www.prometec.net/combinar-dispositivos-i2c/

      Un saludo.

  • Fatal error: ../Wire/Wire.h: No such file or directory

    libraries/LiquidCrystal_I2C/I2CIO.cpp
    Sustituir #include por #include

      • Ivan

      Hola Mateo, no sé si has podido solucionarlo porque no se ve bien el comentario. Ese error puedes solucionarlo yendo al archivo I2CIO.cpp y sustituyendo #include < .../Wire/Wire.h> por #include Un saludo.

      • No entiendo bien qué modificación hay que hacer, podrías copiar el contenido del archivo “I2CIO.cpp” modificado? o subirlo en algún servidor para descargarlo?. Gracias…

          • Ivan

          Hola Carlos, por alguna razón me borra el contenido del segundo include. A ver si puedo explicar,e. tienes que abrir el archivo I2CIO.cpp y buscar una línea que pone #include < .../Wire/Wire.h>. Ahí sustituye el …/Wire/Wire.h por Wire.h

          A ver si así se entiende bien. Un saludo.

  • Hola, no soy capaz de encender de ningún modo la Backlight.
    El código es el tuyo, pero no me sale (supongo que debería) las partes de setBacklightPin y setBacklight en color naranja, como si no lo tomase como comando.
    ¿qué podría hacer?
    Agradezco cualquier ayuda

      • Admin

      Hola Nico, es Backlight se enciende sin mas que dar tension al pin correspondiente. Pruebalo directamente y si se ilumina e sun problema de cables o de un pequeño error en cuanto al pin en uso ¿Vale?

    • Sergio

    Gracias por compartir este tipo de trabajos. Este trabajo que realizo usted me ha ayudado a comprender de manera mas practica el funcionamiento del I2C. Especialmente, en la empresa donde trabajo. Se ocupa mucho la comunicacion I2C para baterias de radios. Seria posible que compartiera mas programas sobre I2C? Gracias de nuevo

      • Ivan

      Hola Sergio, intentaremos seguir trabajando con componentes que lo utilicen y subir algún otro tutorial relacionado. Un saludo.

      • Admin

      Pues tomamos nota, Sergio, para hacer algun otro tuto sobre el I2C porque creo que puede ser muy interesante, especialmente si usamos dos o 3 nodos a la vez

    • Alejandro Garcia

    Muy pero muy bueno el post. Muchas gracias por toda la info!!

    • Andres

    Hola que tal , quería saber si pueden ayudarme ,
    quería conectar varios display (cerca de 50 ) LCD y controlarlos enviándoles diferente información a cada uno ,nose si eso lo soportaría este equipo o que me pueden recomendar,,
    Muchas gracias

      • Admin

      En principio el I2C y algunas ampliaciones lo soportaria. pero estos displays solo tienen 4 pines para fijar la direccion con lo que no podrias poner mas de 16

      • Interesante seria saber como pues se podria comunicar por bluetooth hacia los display pero utilizando en bus i2c me parece mas interesante para efectos practicos de ver distintas mediciones en distintos display

          • Ivan

          Hola Jorge, no estoy seguro de entenderte del todo, pero no sería difícil comunicarnos por un lado con el Arduino mediante Bluetooth y por otro mostrar los valores que quieras en los displays I2C.

      • /* Multiples Display sobre puerto I2C
        Por: Jorge Godoy jgodoy@desdelacalera.cl CHILE 5region 2017

        son 3 pares para fijar la direccion… A0 A1 en la interfaz se jumpea por harware para que dos interfaces iguales seteen difetentes direcciones (solo las interfaces modernas lo traen hay interfaces I2C que no cuentan con estos )
        // ============================ //
        use un display de 16×2 y otro de 24×4 en el principio debes usar el I2C scanner aca recomendado para que te identifique los dos display correctamente dentro del bus
        La interfaz en que uni A0 con A1 la asocie al display de 16×2 por eso quedo primero con la direccion 0x26
        */

        #include
        #include
        #include
        #define display01 0x26
        #define display02 0x27
        LiquidCrystal_I2C lcd01(display01,2, 1, 0, 4, 5, 6, 7);
        LiquidCrystal_I2C lcd02(display02,2, 1, 0, 4, 5, 6, 7);
        void setup()
        {
        lcd01.begin (16,2); // Inicializar el display con 16 caraceres 2 lineas
        lcd01.setBacklightPin(3,POSITIVE);
        lcd01.setBacklight(HIGH);

        lcd01.home (); // go home
        lcd01.print(“== 2017 ==”);
        lcd01.setCursor ( 0, 1 ); // go to the 2nd line
        lcd01.print(“Por: Jorge Godoy”);

        // segundo Display
        lcd02.begin (20,4); // Inicializar el display con 16 caraceres 2 lineas
        lcd02.setBacklightPin(3,POSITIVE);
        lcd02.setBacklight(HIGH);

        lcd02.home (); // go home
        lcd02.print(” ==I2C ARDUINO==”);
        lcd02.setCursor ( 0, 1 ); // go to the 2nd line
        lcd02.print(“Comunicacion Serial”);
        lcd02.setCursor ( 0, 2 ); // go to the 2nd line
        lcd02.print(“Usando I2C”);
        lcd02.setCursor ( 0, 3 ); // go to the 2nd line
        lcd02.print(“16×2 y 20×4 “);
        }
        void loop()
        {}

          • Admin

          Muchas gracias por tu aportacion Jorge

Para porder realizar consultas a nuestros expertos, tienes que ser suscriptor. Suscribiendote nos ayudas a mantener este proyecto en marcha.

¡ Quiero Suscribirme !

Si ya eres premium y no puedes comentar haz login. Hacer login