Bus I2C/TWI

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.

Más información en:

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.

Más información:

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.

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

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, sólo uno puede ser el master.

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 bus specification: http://i2c.info/i2c-bus-specification

Especificación y manual de usuario de I2C: http://www.nxp.com/documents/user_manual/UM10204.pdf

I2C bus y como usarlo: http://www.i2c-bus.org/fileadmin/ftp/i2c_bus_specification_1995.pdf

Presentación de I2C por Philips: http://www.nxp.com/documents/application_note/AN10216.pdf

I2C no tiene limitaciones de velocidad, el maestro genera la velocidad de reloj y I2C provee de un mecanismo que si el esclavo es más lento es capaz de ponerse el maestro en modo de espera.

SMBus (Bus de Administración del Sistema) es un subconjunto del protocolo I2C definido por Intel en 1995. Todas las placas bases modernas tienen un bus SMBus al que se conectan la mayor parte de los chips de monitorización del sistema. Estos chips sirven para medir temperaturas de componentes, velocidad de ventiladores, voltajes, etc. Toda clase de información sobre hardware.

Direccionamiento I2C

En principio, el número de dispositivos que se puede conectar al bus no tiene límites, aunque hay que observar que la capacidad máxima sumada de todos los dispositivos no supere los 400 pF. El valor de los resistores de polarización no es muy crítico, y puede ir desde 1K8 (1.800 ohms) a 47K (47.000 ohms). Un valor menor de resistencia incrementa el consumo de los integrados pero disminuye la sensibilidad al ruido y mejora el tiempo de los flancos de subida y bajada de las señales. Los valores más comunes en uso son entre 1K8 y 10K.

Lo más común en los dispositivos para el bus I2C es que utilicen direcciones de 7 bits, aunque existen dispositivos de 10 bits. Este último caso es raro. Una dirección de 7 bits implica que se pueden poner hasta 128 dispositivos sobre un bus I2C, ya que un número de 7 bits puede ir desde 0 a 127. Cuando se envían las direcciones de 7 bit, de cualquier modo la transmisión es de 8 bits. El bit extra se utiliza para informarle al dispositivo esclavo si el dispositivo maestro va a escribir o va a leer datos desde él. Si el bit de lectura/escritura (R/W) es cero, el dispositivo maestro está escribiendo en el esclavo. Si el bit es 1 el maestro está leyendo desde el esclavo. La dirección de 7 bit se coloca en los 7 bits más significativos del byte y el bit de lectura/escritura es el bit menos significativo.

Direcciones de esclavos con 7,8 y 10 bits: http://www.totalphase.com/support/articles/200349176

Cada fabricante usa su propio direcionamiento para los esclavos, por ejemplo Philips: http://www.diolan.com/downloads/i2c-address-allocation-table.pdf

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.

Existen otras librerías más avanzadas que Wire.h para manejar el bus I2C, como por ejemplo I2Cdevlib o I2C library.

Para saber más de i2c en el Atmega328p ver página 260 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

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

Módulo TWI en ATmega328p:

i2c-arduino

El I2C en el microcontrolador ATmega328p usa los registros:

Register Name Function
TWCR Two Wire Control Register Controls the actions of the TWI module
TWSR Two Wire Status Register Reports the status of the TWI actions
TWDR Two Wire Data/Address Register Contains the data you want to transmit or have received
TWBR Two Wire Bit Rate Register Controls the frequency of the clock (SCL)

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.

El Arduino Due tiene dos interfaces I2C / TWI SDA1 y SCL1 que están cerca del pin AREF y los adicionales en los pines 20 y 21.

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.

Y para profundizar más en el I2C en Arduino:

Aplicaciones I2C

Podríamos usar el bus I2C para comunicar Raspberry Pi con Arduino y otros dispositivos:

Como conectar via I2C Arduino y Raspberry Pi.

Tutorial de I2C en Raspberry: http://www.instructables.com/id/Raspberry-Pi-I2C-Python/all

Librería python para usar I2C en Raspberry Pi

https://github.com/quick2wire/quick2wire-python-api

Usar I2C en Linux:

También disponemos de controladores I2C en caso de no tener disponibles puertos I2C en el microcontrolador: http://www.nxp.com/documents/application_note/AN10148.pdf que reciben datos en formato pararlelo, lo pasana  serie y lo mandan a un bus I2C y en sentido contrario.

Otro ejemplo de aplicación I2C es este shield que maneja 8 relés usando dos pines I2C e incluso se pueden apilar para manejar, 16 o 24 relés en el mismo bus I2C:

Como ejemplo curioso de I2C el Wii Remote (conocido como Wiimote) es el dispositivo de entrada principal de Wii. Es un dispositivo inalámbrico que utiliza la tecnología Bluetooth estándar para comunicarse con la Wii. Está construido alrededor de un Broadcom BCM2042 bluetooth System-on-a-chip, y contiene múltiples periféricos que le proporcionan datos, así como un puerto de expansión para complementos externos.

El mando Wii incluye un puerto de expansión de 6 pines que permite conectar periféricos externos. Las comunicaciones son I2C síncronas bidireccionales y los dispositivos proporcionan un bloque de registro virtual de longitud 0x100 que está mapeado en 0xa40000 en el espacio de direcciones del Wii Remote (La dirección I2C de 7 bits es 0x52).

Webs del proyecto:

Ejercicios I2C Arduino

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.

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.

En algunas ocasiones, sobre todo al comprar en vendedores chinos, el fabricante no nos facilita la dirección del dispositivo o incluso lo proporciona de forma incorrecta. Esta es una circunstancia común y nada preocupante. Para eso disponemos de un sketch llamado “Scanner I2C” que realiza un barrido por todas las posibles direcciones del bus, y muestra el resultado en caso de encontrar un dispositivo en la dirección.El sketch scanner I2C está disponible en este enlace, o podéis usar la siguiente versión reducida y traducida.

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);
}

Comunicar Arduinos por I2C

Ejercicio33-I2C: comunicar por I2C tres arduinos

Ejemplo de uso con dos Arduinos:

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio33-I2C

Dispositivos I2C

En el mercado hay multitud de sensores y dispositivos I2C para utilizar con Arduino, veamos alguno de los más importantes.

Para escribir en el dispositivo I2C las tramas serían las indicadas en el gráfico siguiente.

Tras la condición de Start iniciada por el microcontrolador se envía el primer byte conteniendo la dirección del dispositivo I2C con el que se quiere comunicar y en el último bit aparece el 0 indicando que se va a escribir, la información pasa del microcontrolador al dispositivo I2C.

Le sigue a esta trama el bit de acknowledgement generado por el esclavo para confirmar la correcta recepción de byte anterior. El byte siguiente se refiere a la dirección o registro del dispositivo I2C donde se quiere escribir o enviar el dato desde el microcontrolador.

A partir del tercer byte, se envían los datos de forma sucesiva, y es el dispositivo I2C el que va autoincrementando la dirección de memoria donde se guarda el dato recibido.Se finaliza la comunicación con el bit de parada.

Para leer datos del dispositivo I2C, la secuencia es la siguiente.

Inicia el dispositivo master la comunicación a través del bit de Start. Después viene la dirección del esclavo al que se dirige, indicando que va realizar la lectura del mismo (bit R/W=1). En este caso, el dispositivo I2C también va realizando un autoincremento del registro a leer.

Aplicaciones I2C: http://en.wikipedia.org/wiki/I%C2%B2C#Applications

Listado de productos I2C: http://www.nxp.com/products/interface_and_connectivity/i2c/

En el mercado podemos encontrar muchos dispositivos I2C. Ejemplos de dispositivos I2C:

Cabe destacar: módulos GPS, RTC (Real Time Clock), IMU (Inertial Measurement Unit), Display gráfico, EEPROM, Sensores de temperatura y humedad, sensor de presión, distancia, driver motor, etc…

I2C al tratarse de una comunicación serie también puede convertirse a otros protocolos serie.

Doble UART con I2C/SPI interface: http://www.nxp.com/documents/data_sheet/SC16IS752_SC16IS762.pdf, este chip ofrece conversion de protocolo bidireccional de I2C/SPI a RS-232/RS-485

Conversor de USB a I2C:

Este circuito utiliza el integrado convertidor de USB a Serie de la casa FTDI por lo que hay disponibles controladores tanto para Windows como para Apple y Linux. Una vez instalado el driver el circuito aparece en el ordenador como un puerto serie más, por lo que todo lo que hace falta para poder controlar dispositivos I2C es mandar las órdenes directamente al puerto serie y el circuito se encarga de traspasarlas directamente al bus I2C.

Más información en:

Ejemplo de pantalla LCD por I2C de http://www.prometec.net/bus-i2c/

De usb a I2C con software: http://www.telos.de/conniimm20/

Interfaz I2C de módulo EEPROM: http://www.miniinthebox.com/es/at24c02-i2c-interfaz-de-modulo-de-memoria-eeprom-blue_p643036.html

Y el código para usarlo: http://playground.arduino.cc/Code/I2CEEPROM

Colección de librerías para usar dispositivos I2C con Arduino: http://www.i2cdevlib.com/ y los dispositivos: http://www.i2cdevlib.com/devices

Si queremos saber los dispositivos que hay conectados en un bus I2C con las direcciones de cada uno de ellos y mostrarlo por consola disponemos de este código: I2C scanner http://playground.arduino.cc/Main/I2cScanner

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.

El giroscopio mide la velocidad angular, es decir, el número de grados que se gira en un segundo.En un principio, los giroscopios eléctricos eran unos voluminosos artefactos muy caros usados en aviones y para dirigir cohetes. Actualmente la miniaturización de circuitos y gracias a la tecnología MEMS, es posible tener un giroscopio en un chip a un precio muy asequible.

La media de velocidad angular en vez de medirse en grados por segundo, se mide en otra unidad que son radianes por segundo (1rad/s = 180/PI grados/s). Si sabemos el ángulo inicial de la IMU, podemos sumarle el valor que marca el giroscopio para saber el nuevo ángulo a cada momento. Supongamos que iniciamos la IMU a 0º. Si el giroscopio realiza una medida cada segundo, y marca 3 en el eje X, tendremos el ángulo con esta sencilla fórmula:

Dónde Δt es el tiempo que transcurre cada vez que se calcula esta fórmula, AnguloYAnterior es el ángulo calculado la última vez que se llamó esta fórmula y GiroscopioY es la lectura del ángulo Y del giroscopio.

Y lo mismo pasa con los ejes X, Z. Sólo que se suele ignorar el eje Z, puesto que al no poder calcular un ángulo Z con el Acelerómetro, no se puede aplicar un Filtro Complementario para el eje Z.

Podemos ver los datos del acelerómetro y giroscopio de nuestro smartphone con https://play.google.com/store/apps/details?id=com.mtorres.phonetester&hl=es

Error en las medidas. Las IMUs son unos artefactos mágicos que con un poco de trigonometría pueden dar un ángulo con total exactitud. Pero hay dos problemas muy importantes: el ruido y los errores. El ruido son todas aquellas interferencias que afectan a los dispositivos electrónicos. El acelerómetro es capaz de medir cualquier ángulo, sin embargo sus lecturas son ruidosas y tienen un cierto margen de error. Si se dibuja un gráfico de las medidas de un acelerómetro en función del tiempo, se verá algo de este estilo:

El ángulo real (ideal) está marcado en azul, y las medidas reales están en rojo. Por si esto fuera poco, el acelerómetro también detecta cualquier aceleración que no sea la de la gravedad. Por tanto, si mueves la IMU sin girarla, al aplicar una aceleración en otro eje, la IMU lo detectará como un cambio de rotación.

Por otra parte tenemos el giroscopio. A diferencia del acelerómetro, da las medidas con mucha precisión. Pero al realizar los cálculos del ángulo es inevitable que se produzca un pequeño error, que con el tiempo va acomulándose hasta que cualquier similitud con la realidad es pura coincidencia. Esto en inglés se llama drift (deriva). Hay varias formas de combinar los datos del acelerómetro y el giroscopio para así obtener medidas exactas. Para ello son necesarios los filtros.

Hay que conseguir eliminar el ruido, el drift y conseguir que el acelerómetro no cambie de ángulo al detectar otra fuerza que no sea la gravedad. Hay distintos algoritmos, llamados filtros, que hacen esta tarea. Uno de los mejores es el Filtro de Kálman, se utiliza en los aviones, cohetes y satélites geoestacionarios.

El filtro de Kálman es sorprendente. Capaz de calcular el error de cada medida a partir de las medidas anteriores, eliminarlo y dar el valor real del ángulo. En cierto modo es un algoritmo que aprende en cada iteración.

Sin embargo tiene dos problemas: Tiene un coste de procesamiento algo elevado y es muy complicado de entender. Ver https://es.wikipedia.org/wiki/Filtro_de_Kalman

Existen otros filtros a nuestra disposición. El que vamos a utilizar es conocido como Filtro Complementario o Complementary Filter en inglés. Es ideal para implementar con Arduino: fácil de utilizar, bajo coste de procesamiento y con una precisión muy buena.

¿En qué consiste exactamente? El Filtro Complementario es en realidad una unión de dos filtros diferentes: un High-pass Filter para el giroscopio y un Low-pass Filter para el Acelerómetro. El primero deja pasar únicamente los valores por encima de un cierto límite, al contrario que el Low-pass filter, que sólo permite a los que están por debajo.

La fórmula resultante de combinar (complementar, de aquí el nombre) los dos filtros es:

Dónde AnguloGyro es el ángulo del Giroscopio que hemos calculado previamente, y AnguloAccel el ángulo del Acelerómetro calculado con la fórmula de la tangente. Δt es el tiempo que ha pasado (en segundos) desde la última vez que se ha calculado el filtro. Esta fórmula es la misma para el eje X, Y.

Es posible probar a cambiar el valor de 0.98 y 0.02 por un valor personalizado. Eso sí, ambos tienen que sumar 1.

Más información para uso de MPU-6050:

DMP: El MPU6050 IMU contiene un DMP (Digital Motion Processor) que fusiona los datos del acelerómetro y del giroscopio para minimizar los efectos de los errores inherentes a cada sensor. El DMP calcula los resultados en términos de cuaterniones, y puede convertir los resultados en ángulos de Euler y realizar otros cálculos con los datos. Invensense no revelará el algoritmo que utilizan para combinar los datos.

Mientras que la información del giroscopio (velocidad angular) o acelerómetro (aceleración lineal) para cada eje (X, Y y Z) se puede leer de forma directa, el acceso a los registros del DMP es algo más compleja, debido a que el fabricante no ha abierto toda la información al respecto.

Más información de DMP:

MEMS – sistemas micro-electro-mecánicos. Los IMUs son sistemas MEMS, los avances en el campo de los semiconductores están dando lugar a circuitos integrados con características tridimensionales e incluso con piezas móviles. Estos dispositivos, llamados Sistemas Micro electromecánicos (MEMS), pueden resolver muchos problemas que un microprocesador más el software o configuración no ASIC (Chip integrados de aplicación específica) no pueden. La tecnología MEMS puede aplicarse utilizando un sin número de diferentes materiales y técnicas de fabricación; la elección dependerá del tipo de dispositivo que se está creando y el sector comercial en el que tiene que operar.

Los acelerómetros actuales son simples dispositivos MEMS consistentes en una micro estructura suspendida con una masa determinada de referencia conocida como masa sísmica dentro de una cámara de gas sellada. Bajo la influencia de aceleraciones externas la masa cambia de su posición neutral y ese cambio es convertido en una señal eléctrica mediante piezoresistencias con cambio de la capacitancia.

ABC del acelerometro (MUY BUENO): http://5hertz.com/tutoriales/?p=228

Los giroscopios basados en sistemas MEMs usan el mismo sistema que el péndulo de Foucault y usa un elemento vibrante (giroscopios  de estructura vibrante). El principio físico subyacente es que un objeto vibrante tiende a continuar vibrando en el mismo plano que gira su apoyo. En la literatura de ingeniería, este tipo de dispositivos se conocen como “giroscopio de vibración de Coriolis”, debido a que a medida que el plano de oscilación gira, la respuesta detectada por el transductor resulta del término de Coriolis presente en sus ecuaciones de movimiento. Los giroscopios de estructura vibrante son más simples y económicos, que los giroscopios de rotación convencionales. Los dispositivos de estado sólido que usan este principio son un tipo económico de indicadores de posición.

Como funciona internamente un girocopio: http://www5.epsondevice.com/en/information/technical_info/gyro/

Diferentes tipos de giroscopios:

Más información:

Guia de compras de IMU de sparkfun: https://www.sparkfun.com/pages/accel_gyro_guide

Un IMU de 9 grados de libertad incorpora un magnetómetro (brújula digital) al conjunto de acelerómetro y giroscopio. El MPU-9150 que es un MPU-6050 + brujula (magnetometro): http://playground.arduino.cc/Main/MPU-9150

Otro ejemplo de IMU de 9 grados de libertad: https://www.sparkfun.com/products/10724 que tiene un magnetometro. Tutorial de este IMU: https://github.com/ptrbrtz/razor-9dof-ahrs/wiki/Tutorial

Otra IMU con 9DOF es el GY-85. Al contrario que el MPU-6050 tiene en el mismo chip el acelerómetro y el giroscopio, el GY-85  integra tres sensores: Acelerómetro de 3 ejes, Giroscopio de 3 ejes y sensor de campo magnético de 3 ejes.

Comprar: http://www.dx.com/es/p/gy-85-6dof-9dof-imu-sensor-module-for-arduino-148436#.VzRp0oSLTcs

Las referencias de los integrados son:

Esquemático:

esquematico GY-85

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.

Para estas sesión vamos a utilizar una Breakout board bastante típica llamada GY-521, que incluye un MPU650 y un regulador de tensión, con lo que podemos alimentar a tanto 3.3V como a 5V

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

Esquema de conexión

Probar el I2C scanner http://playground.arduino.cc/Main/I2cScanner con el MPU conectado normal y luego con AD0 a masa y comprobar que cambia su dirección.

Ver los ejercicios 62 de https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio62-MPU6050

  • raw_data
  • advanced_values

Este programa es de lo más sencillo, y lo que hace es leer e imprimir los valores en bruto que los acelerómetros y giroscopios que le envían a Arduino, es decir sin procesar en absoluto, algo que sirve de muy poco. Son las medidas reales que producen los acelerómetros y los giróscopos, pero así no valen de mucho.

Hay 6 valores. Los tres primeros corresponden a los acelerómetros y los tres últimos a los giróscopos. Si vas girando el IMU en direcciones perpendiculares verás con rapidez cual es cada uno de los ejes, porque aunque el chip esté en movimiento inercial aun detectará la aceleración de la gravedad, claramente en una de las direcciones.

Vamos a instalar las librerías correspondientes y a probar con uno de los programas de ejemplo que tanto las conexiones como el  MPU6050 están en condiciones operativas.

Para medir los ángulos, vamos a usar estas librerías. Cargar el ejemplo MPU6050_DMP6.

El texto que aparece al principio de cada línea “ypr” corresponde a las iniciales en ingles de los tres ángulos de referencia Yaw, Pitch y Roll. Y los valores que van cambiando son poco más o menos el valor instantáneo de cada uno de esos ángulos.

Si el IMU dispone además de un magnetómetro de 3 ejes, ya está en condiciones de apuntar al Norte además y puede fijar con precisión el segundo eje, y el tercero cae por su propio peso, pero no es el caso del MPU6050 que estamos usando.

Ahora conectar un servo para moverlo girando la IMU:

Ver ejercicio MPU6050_DMP6_SERVO: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio62-MPU6050

RTC (Real Time Clock)

Ya conocemos la librería Time para Arduino. Empezamos utilizando el reloj interno, pero tiene varios problemas evidentes, como el hecho de que el reloj interno se reinicia cada 50 días aproximadamente, y además si cortamos la corriente a nuestro Arduino, pone el reloj a 00 y vuelve a empezar desde el 1 de enero de 1970. Una solución, que nos permita usar un reloj fiable que se mantenga incluso cuando apagamos Arduino es usar un RTC

Uno RTC muy extendido para reloj digital es el DS1307 de Maxim. Por muy poco dinero realiza todas las funciones para llevar un reloj con calendario y solo hay que añadirle una batería externa para que no pierda la hora al perder la corriente.

Un RTC es un reloj:

Generalmente los RTC son dispositivos I2C y los más comunes son el DS1307 y el DS3231.

Para usar un RTC con Arduino es necesaria la librería time que ofrece la funcionalidad de mantener la fecha y hora en Arduino y se usa el RTC como fuente de sincronización de la hora.

La librería time añade funcionalidades de tiempo a Arduino, ya sea con o sin HW externo. Nos permite obtener la fecha y hora como año, mes, dia, hora, minuto, segundo, día de la semana, etc… También da la hora con el tipo de dato estándar de C time_t de la librería <time.h>: http://www.cplusplus.com/reference/ctime/

Sabe que la librería estandard de C time.h (http://www.cplusplus.com/reference/ctime/) no existe para los microcontroladores AVR, pero si para los ARM y gracias a esta librería es posible añadir esta funcionalidad a Arduino.

La versión anterior de la librería Time es la DateTime: http://playground.arduino.cc/Code/DateTime

Las características de un RTC a la hora de comprar son:

  • Dirección I2C configurable
  • Compensación de año bisiesto (leap year)
  • Fecha máxima

Generalmente encontramos RTCs con bus I2C,pero también se pueden encontrar con puerto serie o bus SPI o 1-Wire.

RTCs de TI: http://www.ti.com/lsds/ti/clock-and-timing/real-time-clocks-products.page

RTCs de ST: http://www.st.com/web/en/catalog/sense_power/FM151/CL1410?sc=rtc

RTCs de MI: https://www.maximintegrated.com/en/products/digital/real-time-clocks.html

Más información:

El DS1307 de Maxim/Dallas es un circuito integrado capaz de almacenar y llevar la cuenta de la fecha y hora, además disponemos de unos cuantos bytes de datos de usuario en su memoria RAM no volátil (NVRAM). Arduino posee una CPU potente, sin embargo aún así es incapaz de mantener la hora correctamente a largo plazo, debido a los microsegundos que se atrasan al no dividir la frecuencia del reloj principal para dar con el segundo exacto.

Características DS1307:

  • RTC: Real Time Clock, o reloj de tiempo real. Que lleva la cuenta de segundos minutos y horas además de día mes y año automáticamente, válido hasta el año 2100.
  • 56 byte de memoria RAM respaldada por una batería exterior, que mantiene la fecha y hora cuando no hay corriente.
  • Detección automática de corte de corriente y cambio a modo batería.
  • Muy bajo consumo, lo que ayuda a que la batería dure entre 5 y 10 años.
  • I2C integrado en el mismo chip.

El DS1307 requiere un cristal de 32.768 Khz, este valor viene dado por el hecho de que 2^15 = 32,768. Esto quiere decir que la frecuencia es divisible binariamente para generar un segundo exacto. El cristal ya se incluye si compramos algún módulo con el DS1307.

El DS1307 requiere dos fuentes de alimentación: Por una parte, requiere alimentación de 5 volts que opera mientras el circuito está encendido y funcionando y otra fuente que proviene de una batería de litio (tipo reloj) que mantiene funcionando el reloj/calendario mientras la alimentación principal NO está disponible. El cambio entre ambas fuentes de alimentación es gestionado por el DS1307 de manera automática.

Disponemos de un pin de salida que puede ser configurado para que el RTC entregue una onda cuadrada con una frecuencia configurable, las frecuencias disponibles se muestran en la siguiente tabla y se configuran mediante los bits RS1, RS0 y SQWE de registro de control, si se usa este pin hay que agregar una resistencia pull-up, ya que es del tipo “Open drain” (solo puede “drenar” corriente no es fuente de corriente)

Los registros del DS1307 almacenan la fecha y la hora en formato BCD. La dirección de cada registro y la información almacenada en cada uno se muestra en la siguiente tabla:

El funcionamiento del chip se controla mediante el bit 7 del registro del segundero (0x00) y el registro de control (0x07): El bit CH del segundero detiene el reloj cuando está en alto (así se entregan los módulos de fábrica) y en este modo NO se lleva el conteo de tiempo porque el oscilador está detenido. ES MUY IMPORTANTE PONER A 0 ESTE BIT PARA QUE EL RTC FUNCIONE. El registro de control maneja la funcionalidad del pin de salida de onda cuadrada. A partir de la dirección 0x08 disponemos de memoria RAM no volátil (NVRAM) cuyo contenido no se borra con la pérdida de energía, este segmento de memoria funciona de manera similar a una memoria EEPROM.

El el DS1307 es uno de los RTC más usados y mejor documentados para Arduino. Características:

El DS1307 devuelve los valores de la hora via I2C en formato decimal codificado en binario (BCD – https://es.wikipedia.org/wiki/Decimal_codificado_en_binario). Para evitar hacer los cálculos y olvidarnos del protocolo I2C disponemos de varias librerías:

Uso del DS1307 con Raspberry Pi: http://www.instructables.com/id/DIY-RTC-DS1307-Module-and-use-with-Raspberry-Pi/?ALLSTEPS

Conexión de DS1307 con Arduino:

Otros RTCs:

Ver los ejemplos de la librería time. Dirección I2C: 0x68

__DATE__ Y __TIME__ son macros estándar predefinidas en C++ y están disponibles en todos lo compiladores que implementan el estándar.  Podemos aprovechar esto para poner en hora el reloj interno corriendo un programa que convierta estos valores a formato fecha time_t y asignarlo al valor del reloj interno, como hace SetTime.

La macro __DATE__ expande a un string que describe la fecha en la que el preprocesador/compilador está corriendo. El string contiene 11 caracteres en el formato “mmm dd yyyy”

La macro __TIME__ expande a un string que describe la hora del preprocesador/compilador. El string contiene 8 caracteres en el formato: “hh:mm:ss”

Ejercicio43-RTC1: Actualizar hora de RTC manualmente por puerto serie.

Modulo que usado para practica: https://www.sparkfun.com/products/12708

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio43-RTC/actualiza_hora_manual

Ejercicio43-RTC2: Mostrar en una pantalla LCD la fecha y hora obtenida del RTC.

Display puerto serie usado: https://www.sparkfun.com/products/9395

Quick Start: https://www.sparkfun.com/tutorials/246

Uso: http://playground.arduino.cc/Learning/SparkFunSerLCD

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/blob/master/Ejercicio43-RTC/Display_Hora/Display_Hora.ino

GPS

Los módulos GPS generalmente también vienen con interfaz I2C

Ejemplo: http://arduinoguruji.blogspot.com.es/p/gps-interfacing-with.html

Datasheet: https://www.u-blox.com/sites/default/files/products/documents/NEO-6_DataSheet_(GPS.G6-HW-09005).pdf

Librerías:

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