Infrared sensor

Is it hot? Arduino + MLX90614 IR Thermometer

Tuesday, February 15 th , 2011

Being able to sense temperature is cool… But being able to read the temperature of an object without even touching it is simply awesome. The MLX90614 is a sensor that can do just that. By reading the infrared light coming off an object, this guy can sense between -95 and 720ºf (-70 to 382.2°C) with 17bit resolution. That’s 128X more precise than the Arduino’s ADC, and means this little guy can tell the difference between 25ºC and 25.02ºC without even coming in contact. (Though 17bits split between -70 and 382 should give us 0.0034ºC resolution). 

I have had my eye on this guy ever since I saw it at Sparkfun, but never had a reason to get one. Then, looking around, the MLX90614 seemed to be giving some people a hard time when trying to connect it to their Arduino. So… we at bildr did what we do best, we bought one, and took some time to make your lives easier and get this running. This is an I2C device like many sensors we have talked about before, but unlike all the I2C sensors we have written about before this, the MLX90614 can’t use the wire library to communicate with it, so we will be using another library, also, unlike what we typically deal with, the MLX90614 is not on a breakout board, so it requires some pull-up resistors on both the data and clock lines (Typically, these are included on the board, we just don’t notice them.)

The standard wire library wasn’t working for people, so we will be using the i2cmaster library instead. To complicate things even more, the i2cmaster wont run on the Arduino out of the box, some files need to be renamed and changed, and an extra txt file is needed to get it working. But… because it is open-sourced I can make those changes, and redistribute it. So that’s what I’m going to do, I’m just giving it to you here in its working version to save you some time and headache. You will need to drop the library into your Arduino library folder for it to work, but we will get there.

As for hooking this up, on your Arduino (everything but the mega) SDA is on analog input pin 4, and SCL is on analog pin 5. On an Arduino mega, SDA is digital 20, and SCL is digital 21. Look at the picture to see how it should be connected, but a 4.7KΩ resistor needs to be connected from SDA to 3.3V, and another one from SCL to 3.3V. I also have a .1uf capacitor between power andground as stated in the data sheet, but I have seen others not use it, and I have tested it without and it still worked.

 

Code

So, here is the code. Because it consists of many files, I am using bildr’s fancy bildrCode wrapper. This allows us to have wiki like control over many files for a single project – just like this. All this code does is output the temperature in both Celsius and Fahrenheit via serial. So open your serial monitor!

To make this code work, before you load the code, or even open the Arduino program, we need to place the “I2Cmaster” in your Arduino Library. If you don’t know where that is by default, Look to the right.

Once the I2CMaster folder is in there, you can just go ahead and open MLX90614.pde in your Arduino software, and upload it.

Code example

#include <i2cmaster.h>

void setup(){
Serial.begin(9600);
Serial.println(“Setup…”);

i2c_init(); //Initialise the i2c bus
PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups
}

void loop(){
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;

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

// read
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();

//This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
double tempData = 0x0000; // zero out the data
int frac; // data past the decimal point

// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;

float celcius = tempData – 273.15;
float fahrenheit = (celcius*1.8) + 32;

Serial.print(“Celcius: “);
Serial.println(celcius);

Serial.print(“Fahrenheit: “);
Serial.println(fahrenheit);

delay(1000); // wait a second before printing again
}