maxbot:
Hello guys,
I want to share with you the code and wiring circuit to get the new MLX90620 working with the arduino. Like the well-known MLX90614, the sensor detects thermal radiation and measures temperatures without making contact with the object. The advantage of this sensor is that it can read 64 pixels at the same time VERY fast and accurate. For the price and size, it is a great thermal sensor.Specifications of the sensor:
- Small size, cost effective 16X4 pixel, thermal array
- Active thermopile pixel technology for fast readout Easy to integrate
- Factory calibrated in wide temperature range: -40 to 85 °C for sensor temperature and -20 to 300 °C for object temperature. 2 Field Of View options: 60X15degrees or 40X10degrees
- High speed I2C digital interface for fast data transfer
- Programmable frame rate 0.5 to 64Hz.
Price: 75$ for the 60° version -> http://www.futureelectronics.com/en/technologies/semiconductors/analog/sensors/temperature/Pages/5020660-MLX90620ESF-BAB-000-TU.aspx?IM=0 (not at stock at the moment..)
Circuit diagram:
Source Code:
#include <i2cmaster.h>
int IRDATA[64];
word EEPROM_DATA[256];
byte CFG_LSB, CFG_MSB, PTAT_LSB, PTAT_MSB, CPIX_LSB, CPIX_MSB, PIX_LSB, PIX_MSB, EEDATA2;
int PIX, CPIX, PTAT, CFG;
double ta, to;
double temperatures[64];
void config_MLX90620_16Hz(){ //Sets the To-Refresh rate to 16Hz
i2c_start_wait(0xC0);
i2c_write(0x03);
i2c_write(0xB5);
i2c_write(0x0A);
i2c_write(0x1F);
i2c_write(0x74);
i2c_stop();
}
void config_MLX90620_8Hz(){ //Sets the To-Refresh rate to 8Hz
i2c_start_wait(0xC0);
i2c_write(0x03);
i2c_write(0xB6);
i2c_write(0x0B);
i2c_write(0x1F);
i2c_write(0x74);
i2c_stop();
}
void read_EEPROM_MLX90620(){
i2c_start_wait(0xA0);
i2c_write(0x00);
i2c_rep_start(0xA1);
int i;
for(i=0;i<=255;i++){
EEPROM_DATA[i] = i2c_readAck();
}
i2c_stop();
}
void calculate_TA(){
double v_th, k_t1, k_t2;
v_th = (double) (256 * EEPROM_DATA[219]) + EEPROM_DATA[218];
if(v_th > 32767){
v_th = v_th - 65536;
}
k_t1 = (double) ((256 * EEPROM_DATA[221]) + EEPROM_DATA[220])/1024;
if(k_t1 > 32767){
k_t1 = k_t1 - 65536;
}
k_t2 = (double) ((256 * EEPROM_DATA[223]) + EEPROM_DATA[222])/1048576;
if(k_t2 > 32767){
k_t2 = k_t2 - 65536;
}
ta = (double) (-k_t1 + sqrt(square(k_t1) - (4 * k_t2 * (v_th - PTAT))))/(2*k_t2) + 25;
Serial.println(ta);
}
void calculate_TO(){
double v_ir_off_comp, v_ir_tgc_comp, v_ir_comp, v_cp_off_comp, emissivity, alpha_ij;
int a_cp, b_cp, a_ij, b_ij, tgc;
for(int i=0;i<=63;i++){
if(IRDATA[i] > 32767){
IRDATA[i] = IRDATA[i] - 65536;
}
a_cp = EEPROM_DATA[212];
if(a_cp > 127){
a_cp = a_cp - 256;
}
b_cp = EEPROM_DATA[213];
if(b_cp > 127){
b_cp = b_cp - 256;
}
v_cp_off_comp = (double) CPIX - (a_cp + (b_cp/pow(2,EEPROM_DATA[217])) * (ta - 25));
a_ij = EEPROM_DATA[i];
if(a_ij > 127){
a_ij = a_ij - 256;
}
b_ij = EEPROM_DATA[64+i];
if(b_ij > 127){
b_ij = b_ij - 256;
}
v_ir_off_comp = (double) IRDATA[i] - (a_ij + (b_ij/pow(2,EEPROM_DATA[217])) * (ta - 25));
tgc = EEPROM_DATA[216];
if(tgc > 127){
tgc = tgc - 256;
}
v_ir_tgc_comp = (double) v_ir_off_comp - ((tgc/32)v_cp_off_comp);
emissivity = (double) ((256EEPROM_DATA[229]) + EEPROM_DATA[228])/32768;
v_ir_comp = (double) v_ir_tgc_comp / emissivity;
alpha_ij = 0.0000000232776;
temperatures[i] = (double) sqrt(sqrt((v_ir_comp/alpha_ij) + pow((ta + 273.15),4))) - 273.15;
}
}
void read_IR_ALL_MLX90620(){
i2c_start_wait(0xC0);
i2c_write(0x02);
i2c_write(0x00);
i2c_write(0x01);
i2c_write(0x40);
i2c_rep_start(0xC1);
int i;
for(int i;i<=63;i++){
PIX_LSB = i2c_readAck();
PIX_MSB = i2c_readAck();
IRDATA[i] = (PIX_MSB << 8) + PIX_LSB;
}
i2c_stop();
}
void read_PTAT_Reg_MLX90620(){
i2c_start_wait(0xC0);
i2c_write(0x02);
i2c_write(0x90);
i2c_write(0x00);
i2c_write(0x01);
i2c_rep_start(0xC1);
PTAT_LSB = i2c_readAck();
PTAT_MSB = i2c_readAck();
i2c_stop();
PTAT = (PTAT_MSB << 8) + PTAT_LSB;
}
void read_CPIX_Reg_MLX90620(){
i2c_start_wait(0xC0);
i2c_write(0x02);
i2c_write(0x91);
i2c_write(0x00);
i2c_write(0x01);
i2c_rep_start(0xC1);
CPIX_LSB = i2c_readAck();
CPIX_MSB = i2c_readAck();
i2c_stop();
CPIX = (CPIX_MSB << 8) + CPIX_LSB;
if(CPIX > 32767){
CPIX = CPIX - 65536;
}
}
void read_Config_Reg_MLX90620(){
i2c_start_wait(0xC0);
i2c_write(0x02);
i2c_write(0x92);
i2c_write(0x00);
i2c_write(0x01);
i2c_rep_start(0xC1);
CFG_LSB = i2c_readAck();
CFG_MSB = i2c_readAck();
i2c_stop();
}
void check_Config_Reg_MLX90620(){
read_Config_Reg_MLX90620();
if ((CFG_MSB & 0x40) == 0){
config_MLX90620_8Hz;
}
}
void Temperatures_Serial_Transmit(){
for(int i=0;i<=63;i++){
Serial.println(temperatures[i]);
}
}
void setup(){
Serial.begin(115200);
i2c_init();
PORTC = (1 << PORTC4) | (1 << PORTC5);
config_MLX90620_8Hz();
//config_MLX90620_16Hz();
read_EEPROM_MLX90620();
}
void loop(){
read_PTAT_Reg_MLX90620();
read_CPIX_Reg_MLX90620();
read_IR_ALL_MLX90620();
calculate_TA();
calculate_TO();
Temperatures_Serial_Transmit();
check_Config_Reg_MLX90620();
delay(500); //For 8Hz, the fastest refresh is 125ms, for 16Hz 65ms
}
You also need the I2CMaster library from here: http://www.cheap-thermocam.bplaced.net/software/I2Cmaster.rar This sketch transfers all 64 pixels to the computer over the serial window. For information about which pixel correspond to which position, check out the MLX90620 datasheet: http://www.melexis.com/Asset/Datasheet-IR-thermometer-16X4-sensor-array-MLX90620-DownloadLink-6099.aspx I originally intended to integrate this sensor into my Cheap-Thermocam project (www.cheap-thermocam.tk), but I have no time to finish it at the moment.. Maybe for somebody it is useful ;)
Can you share sample of images? how fast does it do images? need computer or not?
Thanks a lot.
Jose