I2C

Al comenzar a usar Arduino puede resultar algo complejo entender las diferencias entre los diferentes tipos de interfaces de comunicación (y protocolos asociados).

Dentro la comunicación serie integrada en los microcontroladores de Arduino tenemos:

  • UART (recepción-transmisión asíncrona universal) es uno de los protocolos serie más utilizados. La mayoría de los microcontroladores disponen de hardware UART. Usa una línea de datos simple para transmitir y otra para recibir datos. Comúnmente, 8 bits de datos son transmitidos de la siguiente forma: un bit de inicio, a nivel bajo, 8 bits de datos y un bit de parada a nivel alto. UART se diferencia de SPI y I2C en que es asíncrono y los otros están sincronizados con señal de reloj. La velocidad de datos UART está limitado a 2Mbps
  • SPI es otro protocolo serie muy simple. Un maestro envía la señal de reloj, y tras cada pulso de reloj envía un bit al esclavo y recibe un bit de éste. Los nombres de las señales son por tanto SCK para el reloj, MOSI para el Maestro Out Esclavo In, y MISO para Maestro In Esclavo Out. Para controlar más de un esclavo es preciso utilizar SS (selección de esclavo).

I2C es un protocolo síncrono. 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.

I2C es un bus de comunicaciones en serie. Su nombre viene de Inter-Integrated Circuit (Inter-Circuitos Integrados). La versión 1.0 data del año 1992 y la versión 2.1 del año 2000, su diseñador es Philips. La velocidad es de 100 kbit/s en el modo estándar, aunque también permite velocidades de 3.4 Mbit/s. Es un bus muy usado en la industria, principalmente para comunicar microcontroladores y sus periféricos en sistemas integrados (Embedded Systems) y generalizando más para comunicar circuitos integrados entre si que normalmente residen en un mismo circuito impreso.

La principal característica de I²C es que utiliza dos líneas para transmitir la información: una para los datos y otra para la señal de reloj. También es necesaria una tercera línea, pero esta sólo es la referencia (masa). Como suelen comunicarse circuitos en una misma placa que comparten una misma masa esta tercera línea no suele ser necesaria.

Las líneas se llaman:

  • SDA: datos
  • SCL: reloj
  • GND: tierra

Las dos primeras líneas son drenador abierto, por lo que necesitan resistencias de pull-up.  Dos o más señales a través del mismo cable pueden causar conflicto, y ocurrirían problemas si un dispositivo envía un 1 lógico al mismo tiempo que otro envía un 0. Por tanto el bus es “cableado” con dos resistencia para poner el bus a nivel alto, y los dispositivos envían niveles bajos. Si quieren enviar un nivel alto simplemente lo comunican al bus.

Los dispositivos conectados al bus I2C tienen una dirección única para cada uno. También pueden ser maestros o esclavos. El dispositivo maestro inicia la transferencia de datos y además genera la señal de reloj, pero no es necesario que el maestro sea siempre el mismo dispositivo, esta característica se la pueden ir pasando los dispositivos que tengan esa capacidad. Esta característica hace que al bus I2C se le denomine bus multimaestro.

Las líneas SDA y SCL son del tipo drenaje abierto, es decir, un estado similar al de colector abierto, pero asociadas a un transistor de efecto de campo (o FET). Se deben polarizar en estado alto (conectando a la alimentación por medio de resistores “pull-up”) lo que define una estructura de bus que permite conectar en paralelo múltiples entradas y salidas.

El proceso de comunicación en el bus I2C es:

  • El maestro comienza la comunicación enviando un patrón llamado “start condition”. Esto alerta a los dispositivos esclavos, poniéndolos a la espera de una transacción.
  • El maestro se dirige al dispositivo con el que quiere hablar, enviando un byte que contiene los siete bits (A7-A1) que componen la dirección del dispositivo esclavo con el que se quiere comunicar, y el octavo bit (A0) de menor peso se corresponde con la operación deseada (L/E), lectura=1 (recibir del esclavo) y escritura=0 (enviar al esclavo).
  • La dirección enviada es comparada por cada esclavo del bus con su propia dirección, si ambas coinciden, el esclavo se considera direccionado como esclavo-transmisor o esclavo-receptor dependiendo del bit R/W.
  • Cada byte leído/escrito por el maestro debe ser obligatoriamente reconocido por un bit de ACK por el dispositivo maestro/esclavo.
  • Cuando la comunicación finaliza, el maestro transmite una “stop condition” para dejar libre el bus.

Las transacciones en el bus I2C tienen este formato:

| start | A7 A6 A5 A4 A3 A2 A1 R/W | ACK | … DATA … | ACK | stop | idle |

Cuando los datos son enviados por SDA, los pulsos de reloj son enviados por SCL para mantener el maestro y el esclavo sincronizados. Puesto que los datos son enviados como un bit en cada pulso de reloj, la transferencia de datos es un octavo la frecuencia de reloj. La frecuencia del reloj estándar originalmente se puso a 100 KHz y la mayoría de los integrados y microcontroladores soportan esta velocidad. En posteriores actualizaciones, se introdujo una fast speed de 400 KHz y una high speed de 1.7 a 3.4 MHz. Arduino puede soportar la velocidad estándar y fast speed, BeagleBoard tiene tres buses I2C cada uno a una velocidad distinta y tanto BeagleBoard como Raspberry Pi soportan velocidad estándar y fast speed. Fast speed corresponde a una velocidad de transferencia de 50Kbytes/sec lo que puede ser una velocidad muy baja para algunas aplicaciones de control. Una opción en ese caso es usar SPI en lugar de I2C.

The speed grades:

I2C también se conoce como TWI (Two Wire Interface) y no dispone de un conector estandarizado. Únicamente por motivos de licencia se le denomina TWI, no obstante, la patente caducó en 2006, por lo que actualmente no hay restricción sobre el uso del término I2C.

I2C en Arduino

Arduino dispone de soporte I2C por hardware vinculado físicamente a ciertos pines. También es posible emplear cualquier otro grupo de pines como bus I2C a través de software, pero en ese caso la velocidad será mucho menor.

Los pines a los que está asociado varían de un modelo a otro. La siguiente tabla muestra la disposición en alguno de los principales modelos. Para otros modelos, consultar el esquema de patillaje correspondiente.

MODELO SDA SCK
Uno A4 A5
Nano A4 A5
Mini Pro A4 A5
Mega 20 21

Para usar el bus I2C en Arduino, el IDE Standard proporciona la librería “Wire.h”, que contiene las funciones necesarias para controlar el hardware integrado.

Características de I2C en ATmega328p:

  • Simple, yet Powerful and Flexible Communication Interface, only two Bus Lines Needed
  • Both Master and Slave Operation Supported
  • Device can Operate as Transmitter or Receiver
  • 7-bit Address Space Allows up to 128 Different Slave Addresses
  • Multi-master Arbitration Support
  • Up to 400kHz Data Transfer Speed
  • Slew-rate Limited Output Drivers
  • Noise Suppression Circuitry Rejects Spikes on Bus Lines
  • Fully Programmable Slave Address with General Call Support
  • Address Recognition Causes Wake-up When AVR is in Sleep Mode
  • Compatible with Philips I2C protocol

La librería para manejar el bus I2C en Arduino es Wire: http://arduino.cc/en/reference/wire

Esta librería permite comunicar con I2C/TWI Arduino con otros dispositivos. En las placas Arduino con el diseño R3 (1.0 pinout), la SDA (línea de datos) y SCL (línea de reloj) están en los pines cerca del pin AREF.

Funciones:

  • 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.

Escaner 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.

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 es posible que tengamos un dispositivo sin documentación, para ello hay un programa para Arduino, que nos informa, de lo que hay en nuestro bus y con qué dirección.

Ver http://playground.arduino.cc/Main/I2cScanner

 
#include "Wire.h"
extern "C" {
    #include "utility/twi.h"
}
void scanI2CBus(byte from_addr, byte to_addr, void(*callback)(byte address, byte result) )
{
  byte rc;
  byte data = 0;
  for( byte addr = from_addr; addr <= to_addr; addr++ ) {
    rc = twi_writeTo(addr, &data, 0, 1, 0);
    callback( addr, rc );
  }
}
void scanFunc( byte addr, byte result ) {
  Serial.print("addr: ");
  Serial.print(addr,DEC);
  Serial.print( (result==0) ? " Encontrado!":"   	");
  Serial.print( (addr%4) ? "\t":"\n");
}

const byte start_address = 8;
const byte end_address = 119;
 
void setup()
{
    Wire.begin();
    Serial.begin(9600);
    Serial.print("Escaneando bus I2C...");
    scanI2CBus( start_address, end_address, scanFunc );
    Serial.println("\nTerminado");
}
 
void loop()
{
    delay(1000);
}

IMU (Inertial Measurement Unit)

Una IMU es un dispositivo capaz de medir la fuerza (aceleración) y la velocidad. Generalmente consta de un Acelerómetro y un Giroscopio. Por lo tanto una IMU no mide ángulos, por lo menos no directamente, requiere algunos cálculos.

Un dispositivo I2C muy interesante es el MPU-6050 que nos sirve para probar e introducirnos en el mundo de los giroscopios y acelerómetros.

Definiciones:

El MPU-6050 es una IMU de 6DOF (se lee “6 Degrees Of Freedom“ o 6 grados de libertad). Esto significa que lleva un acelerómetro y un giroscopio, ambos de 3 ejes (3+3 = 6DOF). Hay IMUs de 9DOF, en ese caso también llevan un magnetómetro. Otras pueden tener 5DOF, en cuyo caso el giroscopio sólo mide dos ejes, etc.

El MPU-6050 opera con 3.3 voltios, aunque algunas versiones llevan un regulador que permite conectarla a 5V. El MPU-6050 utiliza el protocolo de comunicación I2C.

El acelerómetro mide la aceleración. La aceleración puede expresarse en 3 ejes: X, Y y Z, las tres dimensiones del espacio. Por ejemplo, si mueves la IMU hacia arriba, el eje Z marcará un cierto valor. Si es hacia delante, marcará el eje X, etc. La gravedad de la Tierra tiene una aceleración de aprox. 9.8 m/s², perpendicular al suelo como es lógico. Así pues, la IMU también detecta la aceleración de la gravedad terrestre. Gracias a la gravedad terrestre se pueden usar las lecturas del acelerómetro para saber cuál es el ángulo de inclinación respecto al eje X o eje Y.

Supongamos que la IMU esté perfectamente alineada con el suelo. Entonces, como puedes ver en la imagen, el eje Z marcará 9.8, y los otros dos ejes marcarán 0. Ahora supongamos que giramos la IMU 90 grados. Ahora es el eje X el que está perpendicular al suelo, por lo tanto marcará la aceleración de la gravedad.

Si sabemos que la gravedad es 9.8 m/s², y sabemos qué medida dan los tres ejes del acelerómetro, por trigonometría es posible calcular el ángulo de inclinación de la IMU. Una buena fórmula para calcular el ángulo es:

Dado que el ángulo se calcula a partir de la gravedad, no es posible calcular el ángulo Z (giro sobre si mismo) con esta fórmula ni con ninguna otra. Para hacerlo se necesita otro componente: el magnetómetro, que es un tipo de brújula digital. El MPU-6050 no lleva, y por tanto nunca podrá calcular con precisión el ángulo Z. Sin embargo, para la gran mayoría de aplicaciones sólo se necesitan los ejes X e Y.

Ejercicio IMU MPU6050

El MPU6050 que vamos a utilizar es un chip de 6 dof o grados de libertad porque incluye un acelerómetro de 3 ejes y un giróscopo de 3 ejes.

Aunque lo que miden los sensores internos son aceleraciones lineales y angulares el procesador interno del IMU es capaz de realizar cálculos sobre la marcha para darnos informaciones más útiles como los ángulos de inclinación con respecto a los 3 ejes principales. Conseguir los datos en bruto del MPU6050 es la parte fácil, procesarlos y reaccionar es otra historia que se puede complicar un poco más.

El siguiente diagrama muestra la orientación de los ejes de sensibilidad y la polaridad de rotación.

Esquema de conexión

A partir del código https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio62-MPU6050/raw_values que me da los valores en bruto de la IMU, hacer un programa que haga girar el servo en función del ángulo en el que se encuentre el eje Y.

Si sabemos que la gravedad es 9.8 m/s², y sabemos qué medida dan los tres ejes del acelerómetro, por trigonometría es posible calcular el ángulo de inclinación de la IMU. Una buena fórmula para calcular el ángulo es:

Solución Ejercicio17https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio17-I2C_Servo

Anuncios

2 pensamientos en “I2C

  1. Pingback: Saber Más Programación | Aprendiendo Arduino

  2. Pingback: Saber Más Avanzado 2017 | Aprendiendo Arduino

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s