Electroensaimada DIY, Raspberry Pi, Arduino ...
  • Home
  • Raspberry Pi
    • Básico >
      • Primeros pasos
      • IP estática
      • Montar Pendrive
      • Escritorio remoto
      • Conexión Wifi
      • no-ip
    • Intermedio >
      • Openelec Xbmc
      • OwnCloud
      • Torrent
      • Parpadeo led
      • Xbee
    • Avanzado >
      • SPI con WiringPi
      • ADC
      • Control temperatura
      • Alarma con aviso por mail
    • Raspberry Pi Expansion Board >
      • Control temperatura
      • Alarma con aviso por mail
  • Arduino
    • Motor paso a paso
    • Servomotor
    • PWM
    • Sensor Infrarrojo
    • SPI
    • I2C
    • Relé y LDR
    • Mando Radiocontrol
  • Blog
    • Contacto
  • CNC
    • Material
    • Codigo Maquina >
      • Leer el fichero
      • Decodificar fichero
      • Entorno de usuario
    • Movimiento >
      • Recta a trozos
      • Taladrar o cortar
    • Estructura
    • Estructura(2º Version)
    • Modelo CAD 3D
  • Software
    • Qt
    • Eagle >
      • Instalación y primeros pasos eagle
      • Librerías
  • Utilidades
  • Laboratorio
    • Fuente alimentación >
      • Material
      • Montaje

arduino

Tutorial Arduino : I2C

En este tutorial se explicara el funcionamiento del bus I2C, entrando en detalle en como se transmite la trama así como las diferencias con otros buses. Además se explicara su uso con Arduino con varios ejemplos de funcionamiento.

I2C (Inter-Integrated Circuit) es un bus de comunicación muy utilizado para comunicar circuitos integrados, uno de sus usos mas comunes es la comunicación entre un microcontrolador y sensores periféricos. El I2C es un bus multi-maestro es decir permite que haya múltiples maestros y múltiples esclavos en el mismo bus.


El bus I2C cuenta con dos lineas SDA(datos) y SCL(clock) ademas de masa. Como hemos visto en SPI a cada flanco de SCL se captura un bit de SDA, aunque la forma de transmitir la información es diferente. Ademas hay que tener en cuenta que la linea SDA solo puede cambiar de valor en caso de que la linea SCL este a 0.
Imagen
Conexión I2C. Fuente Wikipedia.
En este caso la misma linea de datos envia la información en las dos direcciones, por lo que es necesario un control de acceso al bus y un direccionamiento de cada elemento.
En I2C hay un valor fuerte y otro valor débil, normalmente el 0 es el valor fuerte y el 1 el débil  Esto es así porque el 0 se consigue forzando la linea a esa tensión pero por contra el 1 se consigue con pull-up, por lo tanto en caso de que alguien transmita un 0 y otro un 1, en la linea solo se vera reflejado el 0. Por lo tanto se define como el valor de reposo del bus como el 1, ya que si alguien quiere empezar a comunicar siempre podrá modificar el estado del bus y los demás se darán cuenta.

Otro aspecto a tener en cuenta en I2C es que los maestros o maestro son los únicos que pueden controlar la linea de SCL, eso implica que solo un maestro puede iniciar una transmisión por lo que un Slave tendrá que esperar a que un maestro le pregunte por un dato para poder enviarlo.

 Así en I2C cada dispositivo tiene una dirección de 7 bits, es decir se pueden tener hasta 128 dispositivos conectados al mismo bus, hay que tener en cuenta que existen versiones extendidas de I2C con direccionamiento a 8,10 y 12 bits. 
En el caso del I2C el protocolo del bus si reserva unos campos para poder realizar la transmisión, cosa totalmente diferente con el SPI donde podíamos enviar en cada byte el dato que queramos.

Una trama I2C esta comprendida por los siguientes campos.
  1. Bit de start: Este es un bit especial ya que como hemos dicho antes la linea SDA no puede cambiar a menos que SCL este a 0. Este bit rompe dicha norma y provoca un cambio de 1 a 0 cuando SCL esta a nivel alto.
  2. Address: El primer byte enviado empieza con 7 bits de dirección, el cual indica a quien enviamos o solicitamos el dato.
  3. R/W (Read/Write): El siguiente bit indica si vamos a realizar una operación de lectura o escritura. 
  4. ACK: Este bit esta presente al final de cada byte que enviamos y nos permite asegurarnos que el byte ha llegado a su destino. De este modo el que envía deja el bit a 1 y si alguien a recibido el mensaje fuerza ese bit a 0. De esta manera confirma que le ha llegado el byte y la transmisión puede continuar.
  5. 1º Byte de datos: Este es el primer  byte de datos propiamente dicho ya que lo anterior no lo podemos elegir nosotros y nos viene impuesto por el protocolo. Aquí podemos poner el dato que queramos  en caso de comunicación con sensores remotos un uso habitual es poner el numero de registro al que queremos escribir o leer. Después del byte de datos se espera otro ACK del receptor.
  6. Se repite el paso 5 tantas veces como sea necesario.
  7. Bit de Stop. En este caso ocurre lo contrario al bit de Start, se pasa de 0 a 1 cuando la linea SCL se encuentra en alto. Esto termina la transmisión y deja el bus libre para que otro puede empezar a transmitir.
Imagen
Trama I2C
Lo explicado anteriormente es una trama típica de I2C aunque en realidad puede haber algunas variantes, ya que en caso de que el mismo Master quiera seguir comunicándose  no es necesario terminar la transmisión con un Stop y luego volver a empezar una transmisión .El protocolo permite que en medio de una trama se realice otro Start por lo que se tendrá que volver a enviar la dirección y el R/W, así que se puede cambiar el modo de comunicación y pasar a una lectura o a otra escritura y acceder a otro sensor o a otro registro del mismo sensor. En la siguiente imagen se puede ver una trama de este tipo.
Imagen
Trama con dos Starts.
Imagen

Uso en Arduino.

Vista la teoría del bus I2C es el momento de ver como podemos usarlo en nuestro Arduino. En el Arduino Uno los pines del I2C se encuentran en el pin analógico 4(SDA) y el pin analógico 5(SCL). En el Arduino Mega se encuentran en los pines 20 (SDA) y en el 21(SCL). Finalmente en el nuevo Arduino Leonardo los pines I2C están pintados al lado de AREF.

En lo referente a conexiones conectamos los SDA y los SCL de los dispositivos entre ellos y a la vez una pull-up por cada linea. Estas resistencias pueden tener valores entre 1k y 10 k, dependiendo de la velocidad de comunicación. Un buen valor para esta velocidad es 4.7K. Aunque es cierto que se pueden conectar sin las pull-up y funciona, en el osciloscopio la señal no se veía muy bien, así que para evitar posibles errores lo mejor es asegurarse poniendo las pull-up.
Imagen
Conexión del I2C con solo un dispositivo.
Para usar el bus I2C en Arduino hay que incluir la librería Wire con #include <Wire.h>. A continuación en el setup hay que usar la función Wire.begin() esto inicia el bus I2C y nos define como maestros. Dentro del begin se puede poner una dirección aunque si solo hay un master no es necesario ya que nadie nos va a solicitar datos sino que seremos nosotros los que siempre iniciemos la comunicación.

Una vez iniciado el bus podemos empezar a transmitir. Para ello se usan 3 instrucciones:
  1. Wire.beginTransmission(dirección) :Inicia el bus y ponemos con que dirección vamos a comunicarnos.
  2.  Wire.write(bytes): Esta función envía uno o varios bytes a la dirección anterior.    
  3.  Wire.endTransmission(): Finaliza la comunicación con un STOP y deja el bus libre.
Imagen
Código que envía el byte 0x52.
i2c_1.zip
File Size: 0 kb
File Type: zip
Descargar archivo

Ahora vamos a ver el resultado con el osciloscopio, en el este caso no hay nadie conectado al otro lado por lo que no se recibirá un ACK y se abortara la transmisión. Así podemos ver como con I2C podemos saber si el mensaje a llegado a su destino.
Imagen
Trama con not ACK.
Se puede observar como la velocidad de comunicación es de 100 Kbps esto es debido a que a diferencia del SPI el protocolo I2C en el modo estándar la velocidad máxima es de 100 Kpbs, aunque se puede llegar hasta 3.4 Mbps en otras configuraciones.

En el siguiente ejemplo vamos a conectar dos Arduinos , uno sera configurado como esclavo y otro como maestro. El código del maestro sera el mismo que el anterior y ahora vamos a programar el esclavo para que nos enseñe por el monitor Serial lo que recibe por I2C.
Imagen
Conexión dos Arduinos por I2C.
Imagen
Código del Slave.
i2c_2.zip
File Size: 0 kb
File Type: zip
Descargar archivo

Vemos como configuramos el Arduino para actuar como Slave y ademas configuramos la recepcion por Evento. De esta forma al llegar una trama nos saltara a la interrupción y podremos leer los datos almacenados en el buffer. En nuestro ejemplo solo se envía el byte 0x52 por lo que con el Serial.print(rec,HEX) nos permite ver ese valor en hexadecimal por el monitor.
Imagen
Trama con Address 0xF5 y dato 0x52
Imagen
Monitor Serial del slave.

Envió con Slave.

Finalmente nos queda por ver como enviar datos desde un slave y recibirlos en un master. Desde el master enviaremos dos números  en este caso el 5 y el 7. Y en el Slave los recibiremos y los sumaremos, posteriormente cuando el master nos lo pida se enviara el resultado de la suma al Master.
Imagen
Código del slave.
i2c_3.zip
File Size: 0 kb
File Type: zip
Descargar archivo

Imagen
Código del Master.
i2c_4.zip
File Size: 0 kb
File Type: zip
Descargar archivo

Con estos dos programas en el Arduino, vemos como podemos interactuar entre dos microcontroladores. Podemos ver el resultado en el osciloscopio donde se distinguen las tramas de envió y de recepción.
Imagen
Imagen con una envió desde el Master y otro desde el Slave.
Finalmente el resultado por el monitor Serial.
Imagen
Para terminar vamos a exponer las principales ventajas e inconvenientes que presenta el bus I2C.
Ventajas:
  1. 2 hilos + masa para funcionar.
  2. Control de flujo.
  3. Mecanismo para asegurar que el mensaje ha llegado a su destino mediante ACK.
  4. Muy usado en sensores y otros circuitos integrados.
  5. Velocidad media-alta en Arduino 100 Kbps aunque existe otro modo a 3.4 Mbits pero no en Arduino.
  6. Cada nodo posee una dirección con el cual podemos comunicarnos individualmente

Desventajas:
  1. No es Full-Duplex por lo que no permite envíos y recepciones al mismo tiempo.
  2. Un poco mas complejo que SPI.
  3. No hay control de errores, por ejemplo mediante paridad etc. Aunque si se puede realizar por Software.
  4. Velocidad no tan elevada como SPI.
  5. En el modo estándar numero de nodos limitado a 128.
Con tecnología de Crea tu propio sitio web único con plantillas personalizables.
  • Home
  • Raspberry Pi
    • Básico >
      • Primeros pasos
      • IP estática
      • Montar Pendrive
      • Escritorio remoto
      • Conexión Wifi
      • no-ip
    • Intermedio >
      • Openelec Xbmc
      • OwnCloud
      • Torrent
      • Parpadeo led
      • Xbee
    • Avanzado >
      • SPI con WiringPi
      • ADC
      • Control temperatura
      • Alarma con aviso por mail
    • Raspberry Pi Expansion Board >
      • Control temperatura
      • Alarma con aviso por mail
  • Arduino
    • Motor paso a paso
    • Servomotor
    • PWM
    • Sensor Infrarrojo
    • SPI
    • I2C
    • Relé y LDR
    • Mando Radiocontrol
  • Blog
    • Contacto
  • CNC
    • Material
    • Codigo Maquina >
      • Leer el fichero
      • Decodificar fichero
      • Entorno de usuario
    • Movimiento >
      • Recta a trozos
      • Taladrar o cortar
    • Estructura
    • Estructura(2º Version)
    • Modelo CAD 3D
  • Software
    • Qt
    • Eagle >
      • Instalación y primeros pasos eagle
      • Librerías
  • Utilidades
  • Laboratorio
    • Fuente alimentación >
      • Material
      • Montaje