Connecting Infrared Thermometer MLX90614 to Wiring/es

From Wiring

Jump to: navigation, search

por Jaime Patarroyo

El MLX90614 es un termómetro infrarrojo de gran utilidad (sin necesidad de contacto) que da una lectura promedio de la temperatura de todos los objetos en el rango de visión. Además de su función principal (lectura de temperatura), puede ser utilizado para detectar movimiento o presencia.

Hay dos maneras de interactuar este sensor, a través de comunicación PWM o comunicación SMBus (TWI o I²C). No conseguí hacerlo a través de PWM así que lo hice a través de SMBus I²C que no es fácil de fácil de programar, pero tiene algunas ventajas sobre PWM. A través de I²C se pueden conectar más de 127 dispositivos usando sólo dos pines de la tarjeta Wiring y adicionalmente, en este sensor específico (MLX90614), se obtiene una mejor resolución en la lectura.

Wiring ya viene con una librería para comunicar dispositivos I²C (librería wire), pero desafortunadamente, esta biblioteca no es compatible con el MLX90614, ya que no soporta el uso de la función de arranque repetido (si quiere leer más sobre este problema vea este enlace). Por lo tanto, vamos a utilizar la librería I²Cmaster que ha sido modificada por la gente de bildr.blog para que funcione correctamente con la tarjeta Wiring.

Descargue la pieza MLX90614 para Fritzing.


Contents

Descargar e instalar la librería I²Cmaster

Lo primero que hay que hacer es descargar e instalar a la librería I²Cmaster. Como mencioné antes, vamos a usar un versión modificada por la gente de bildr.blog.

Descargar la librería I²Cmaster.

Después, descargue, descomprima y sitúe el contenido en la carpeta 'libraries' de Wiring:
En Mac: Documentos / Wiring / libraries
En el PC: Mis documentos / Wiring / libraies

Para revisar que la librería quedo bien instalada, abra Wiring (si estaba abierto ciérrelo y ábralo de nuevo) y vaya a:
Sketch > Import Library… > Contributed
y allí debería encontrar I²Cmaster.


Conectar un sensor MLX90614

Una vez instalada la librería, puede utilizar el siguiente esquema y código para leer la temperatura de un sensor MLX90614 conectado a los pines TWI (en la tarjeta Wiring v1: 0 (SCL) y 1 (SDA) y en la tarjeta Wiring S: 8 (SCL ) y 9 (SDA)). Ambos (diagrama y código) están basados en el tutorial de bildr.blog Is it hot? Arduino + MLX90614 IR Thermometer.


Esquema

Ambas resistencias son de 3.7 k Ohm y la pequeña pestaña del sensor apunta la esquina superior derecha del diagrama.

MLX90614.jpg


Código

/**
 * Termómetro Infrarrojo MLX90614
 * por Jaime Patarroyo
 * basado en 'Is it hot? Arduino + MLX90614 IR Thermometer' por bildr.blog
 * 
 * Devuelve la temperatura en Celcius y Fahrenheit de un termómetro 
 * infrarrojo MLX90614, conectado a los pines TWI/I²C (en la tarjeta Wiring 
 * v1: 0 (SCL) y 1 (SDA) y en la tarjeta Wiring S: 8 (SCL) and 9 (SDA)).
 */

#include <i2cmaster.h>


int deviceAddress = 0x5A<<1;    // En la hoja técnica del MLX906114, 0x5A es 
                                // la dirección de comunicación I²C por defecto.
                                // Corra la dirección 1 bit a la derecha, la
                                // librería I²Cmaster solo necesita los 7 bits
                                // mas significativos para la dirección.

float celcius = 0;              // Variable que contiene la temperatura en Celcius.
float fahrenheit = 0;           // Variable que contiene la temperatura en Fahrenheit.

void setup() {
  Serial.begin(9600);           // Inicia la comunicación serial a 9600bps.

  i2c_init();                               // Inicia el bus i2c.
  PORTC = (1 << PORTC4) | (1 << PORTC5);    // Habilita ‘pullups’.
}

void loop() {
  celcius = temperatureCelcius(deviceAddress);  // Lee los datos del MLX90614
                                                // con la dirección dada,
                                                // los transforma en la
                                                // temperatura en Celcius y
                                                // la almacena en la variable
                                                // celcius.
  
  fahrenheit = (celcius*1.8) + 32;     // Convierte Celcius en Fahrenheit 
                                       // y almacena en la variable Fahrenheit.

  Serial.print("Celcius: ");           // Imprime ambas lecturas en el
  Serial.println(celcius);             // puerto serial.
  Serial.print("Fahrenheit: ");
  Serial.println(fahrenheit);

  delay(1000);                         // Espera un segundo antes de imprimir de nuevo.
}

float temperatureCelcius(int address) {
  int dev = address;
  int data_low = 0;
  int data_high = 0;
  int pec = 0;

  // Escribe
  i2c_start_wait(dev+I2C_WRITE);
  i2c_write(0x07);

  // Lee
  i2c_rep_start(dev+I2C_READ);
  data_low = i2c_readAck();       // Lee 1 byte y envía ack.
  data_high = i2c_readAck();      // Lee 1 byte y envía ack
  pec = i2c_readNak();
  i2c_stop();

  // Esto convierte los bytes altos y bajos juntos y procesa la temperatura.
  double tempFactor = 0.02;       // 0.02 grados por LSB (medida de
                                  // resolución del MLX90614).
  double tempData = 0x0000;       
  int frac;                       // Datos después del punto decimal.

  // Esto oculta el error del byte alto y lo mueve a la izquierda
  // 8 bits y agrega el byte bajo.
  tempData = (double)(((data_high & 0x007F) << 8) + data_low);
  tempData = (tempData * tempFactor)-0.01;
  float celcius = tempData - 273.15;
  
  // Retorna la temperatura en Celcius.
  return celcius;
}


Conectar dos o mas sensores MLX90614

Conectar dos o más sensores MLX90614 es un poco más difícil, como se puede ver en el ejemplo anterior, vienen de fábrica con la misma dirección de comunicación (0x5A). Si se conectan dos al tiempo tal como vienen, la tarjeta Wiring no va a saber la diferencia entre ellos y va a devolver la lectura de alguno de los dos. La dirección universal (0) permite acceder al dispositivo, incluso si asignó una nueva dirección, así que si olvida la dirección asignada a un dispositivo siempre puede usar 0.

Cambiar la dirección

Tiene que asignar una dirección a cada uno de los MLX90614 que quiera conectar al mismo tiempo. Solo puede cambiar una dirección a la vez. NO CONECTE MAS DE UN DISPOSITIVO CUANDO ESTÉ CAMBIANDO UNA DIRECCIÓN.

El código a continuación está basado en la respuesta #6 de paulrd en el tema Multiple Melexis MLX90614 on the same i2c, how to change addresses? en el foro de Arduino y sirve solo para cambiar la dirección de un dispositivo, para leer la temperatura usaremos otro código más adelante.

Recuerde cambiar la dirección de caca dispositivo en la linea 14 del código, para el ejemplo voy a usar las direcciones 0x50 y 0x55.

Esquema

Ambas resistencias son de 3.7 k Ohm y la pequeña pestaña del sensor apunta la esquina superior derecha del diagrama.

MLX90614.jpg

Código

/**
 * Cambia la dirección de un dispositivo I²C
 * por Jaime Patarroyo
 * basado en la respuesta #6 del tema 'Multiple Melexis MLX90614 on the 
 * same i2c, how to change addresses?' en el foro de Arduino.
 * 
 * Asigna una nueva dirección a un dispositivo TWI/I²C conectado a los pines 
 * TWI/I²C (en la tarjeta Wiring v1: 0 (SCL) y 1 (SDA) y en la tarjeta Wiring S: 
 * 8 (SCL) y 9 (SDA)).
 */

#include <i2cmaster.h>

byte newAddress = 0x55<<1;      // Escriba acá la dirección nueva que
                                // quiere asignar. En este ejemplo, la nueva
                                // dirección será 0x55.
                                // Corra la dirección 1 bit a la derecha, la
                                // librería I²Cmaster solo necesita los 7 bits
                                // mas significativos para la dirección.

void setup()
{
  Serial.begin(9600);                      // Inicia la comunicación serial 
                                           // a 9600bps.

  i2c_init();                              // Inicia el bus i2c.
  PORTC = (1 << PORTC4) | (1 << PORTC5);   // Habilita ‘pullups’.

  delay(5000);                             // Espera para permitir la comunicación serial.
  ChangeAddress(newAddress, 0x00);         // Cambia la dirección al nuevo valor.
}

void loop()
{
}

word ChangeAddress(byte NewAddr1, byte NewAddr2) {
  Serial.println("> Change address");

  i2c_start_wait(0 + I2C_WRITE);      // Envía el comando de inicio.
  i2c_write(0x2E);                    // Envía comando para que el dispositivo
                                      // devuelva la dirección (0x2E).
  i2c_write(0x00);                    // Envía cero para borrar.
  i2c_write(0x00);                    // Envía cero para borrar.
  if (i2c_write(0x6F) == 0) {
    i2c_stop();                       // Libera el bus, termina la transacción.
    Serial.println("  Data erased."); // Mensaje de confirmación de dirección borrada.
  }
  else {
    i2c_stop();                       // Libera el bus, termina la transacción.
    Serial.println("  Failed to erase data");
    return -1;
  }

  Serial.print("  Writing data: ");
  Serial.print(NewAddr1, HEX);
  Serial.print(", ");
  Serial.println(NewAddr2, HEX);

  for (int a = 0; a != 256; a++) {
    i2c_start_wait(0 + I2C_WRITE);    // Envía el comando de inicio.
    i2c_write(0x2E);                  // Envía comando para que el dispositivo 
                                      // devuelva la dirección (0x2E).
    i2c_write(NewAddr1);              // Envía nueva dirección.
    i2c_write(NewAddr2);              // Envía nueva dirección.
    if (i2c_write(a) == 0) {
      i2c_stop();                     // Libera el bus, termina la transacción.
      delay(100);                     // Espera 10ms.
      Serial.print("Found correct CRC: 0x");
      Serial.println(a, HEX);
      return a;
    }
  }
  i2c_stop();                         // Libera el bus, termina la transacción.
  Serial.println("Correct CRC not found");
  return -1;
}

Leer los Sensores

Ahora que tenemos una dirección diferente para cada dispositivo, podemos conectar los dos sensores al tiempo y leer su temperatura de forma independiente.

Esquema

Ambas resistencias son de 3.7 k Ohm y la pequeña pestaña del sensor apunta la esquina superior derecha del diagrama.

TwoMLX90614.jpg

Código

/**
 * Dos termómetros infrarrojos MLX906114
 * por Jaime Patarroyo
 * basado en 'Is it hot? Arduino + MLX90614 IR Thermometer' por bildr.blog
 * 
 * Devuelve la temperatura en Celcius y Fahrenheit de dos termómetros 
 * infrarrojos MLX90614, conectados a los pines TWI/I²C (en la tarjeta 
 * Wiring v1: 0 (SCL) y 1 (SDA) y en la tarjeta Wiring S: 8 (SCL) y 9 (SDA)).
 */

#include <i2cmaster.h>

int device1Address = 0x50<<1;   // 0x50 es la dirección asignada para 
                                // comunicación I²C del sensor 1.
                                // Corra la dirección 1 bit a la derecha, la
                                // librería I²Cmaster solo necesita los 7 bits
                                // mas significativos para la dirección.
int device2Address = 0x55<<1;   // 0x55 es la dirección asignada para 
                                // comunicación I²C del sensor 1.
                                // Corra la dirección 1 bit a la derecha, la
                                // librería I²Cmaster solo necesita los 7 bits
                                // mas significativos para la dirección.

float celcius1 = 0;             // Variable que contiene la temperatura en Celcius
                                // para el sensor 1.
float fahrenheit1 = 0;          // Variable que contiene la temperatura en Fahrenheit
                                // para el sensor 1.
float celcius2 = 0;             // Variable que contiene la temperatura en Celcius
                                // para el sensor 2.
float fahrenheit2 = 0;          // Variable que contiene la temperatura en Fahrenheit
                                // para el sensor 2.

void setup()
{
  Serial.begin(9600);           // Inicia la comunicación serial a 9600bps.
  
  i2c_init();                               // Inicia el bus i2c.
  PORTC = (1 << PORTC4) | (1 << PORTC5);    // Habilita ‘pullups’.
}

void loop()
{
  celcius1 = temperatureCelcius(device1Address);// Lee los datos del MLX90614
  celcius2 = temperatureCelcius(device2Address);// con la dirección dada,
                                                // los transforma en
                                                // temperatura en Celcius y
                                                // la guarda en las variables
                                                // celcius1 o celcius2.
 
  fahrenheit1 = (celcius1*1.8) + 32;     // Convierte Celcius en Fahrenheit 
  fahrenheit2 = (celcius2*1.8) + 32;     // y almacena en las variables 
                                         // Fahrenheit1 o Fahrenheit2.

  Serial.print("Sensor 1: Celcius: ");   // Imprime las todas las lecturas en
  Serial.print(celcius1);                // el puerto serial.
  Serial.print("  Fahrenheit: ");
  Serial.println(fahrenheit1);
  Serial.print("Sensor 2: Celcius: ");
  Serial.print(celcius2);
  Serial.print("  Fahrenheit: ");
  Serial.println(fahrenheit2);

  delay(1000);                         // Espera un segundo para imprimir de nuevo.
}

float temperatureCelcius(int address) {
  int dev = address;
  int data_low = 0;
  int data_high = 0;
  int pec = 0;

  // Escribe
  i2c_start_wait(dev+I2C_WRITE);
  i2c_write(0x07);

  // Lee
  i2c_rep_start(dev+I2C_READ);
  data_low = i2c_readAck();       // Lee 1 byte y envía ack.
  data_high = i2c_readAck();      // Lee 1 byte y envía ack
  pec = i2c_readNak();
  i2c_stop();

  // Esto convierte los bytes altos y bajos juntos y procesa la temperatura.
  double tempFactor = 0.02;       // 0.02 grados por LSB (medida de
                                  // resolución del MLX90614).
  double tempData = 0x0000;       
  int frac;                       // Datos después del punto decimal.

  // Esto oculta el error del byte alto y lo mueve a la izquierda
  // 8 bits y agrega el byte bajo.
  tempData = (double)(((data_high & 0x007F) << 8) + data_low);
  tempData = (tempData * tempFactor)-0.01;
  float celcius = tempData - 273.15;
  
  // Retorna la temperatura en Celcius.
  return celcius;
}


Idioma: English  • Español
Personal tools