Pages: [1] 2 3   Go Down
Author Topic: Reading data from multiple Melexis MLX90614 IR Sensors I2C  (Read 6810 times)
0 Members and 1 Guest are viewing this topic.
Silsden
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi guys!

this is my first time using the arduino and im kinda struggling. What im trying to do is read the temperature data from multiple MLX90614 IR Temperature Sensors, (data sheet found here http://www.melexis.com/Infrared-Thermometer-Sensors/Infrared-Thermometer-Sensors/MLX90614-615.aspx).

I have sucessfully changed the device names so that they each have there own "name" (A1 & A2) and can read temp from one device connected at once but im at a loss on how to code the program to read and display the temp from each of the devices ie;

Code:
// Print Data To Screen...
  Serial.print("Temp sensor: A1: ");
  Serial.print(celcius1);
  Serial.print(" A2: ");
  Serial.println(celcius2);

I have attached my current sketch for you to see. note sensor 3 is commented out as im waiting on it atm smiley

cheers for you help in advance!

* MLX90614ver0_1.ino (3.15 KB - downloaded 49 times.)
Logged

South of Boston
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Creating a monster with help from the Awesome Foundation
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I only see a small sample of code, not the entire sketch.

If it helps, I just got two I2C compasses working and posted the code for that.
http://arduino.cc/forum/index.php/topic,89384.0.html
Logged

Silsden
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hey
ill repost the full thing below smiley and i will have a look at yours and try get my head round it. only been using the arduino for about 3 weeks.

Code:
#include <i2cmaster.h>


void setup(){
  Serial.begin(115200);
  Serial.println("Setup...");

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

void loop(){
  int dev1 = 0xA1<<1;
  int dev2 = 0xA2<<1;
  //int dev3 = 0xA3<<1;
  int data_low = 0;
  int data_high = 0;
  int pec = 0;

  i2c_start_wait(dev1+I2C_WRITE);
  i2c_write(0x07); //Object
  
  
  i2c_start_wait(dev2+I2C_WRITE);
  i2c_write(0x07); //Object
  
  
  /*i2c_start_wait(dev3+I2C_WRITE);
  i2c_write(0x07); //Object
   */
  
  // read
  i2c_rep_start(dev1+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();

  i2c_rep_start(dev2+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();

  /*i2c_rep_start(dev3+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();
  */

// Sensor A1 Readings...

  //This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
  double tempFactor1 = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
  double tempData1 = 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.
  tempData1 = (double)(((data_high & 0x007F) << 8) + data_low);
  tempData1 = (tempData1 * tempFactor1)-0.01;

  float celcius1 = tempData1 - 273.15;

// Sensor A2 Readings...

  //This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
  double tempFactor2 = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
  double tempData2 = 0x0000; // zero out the data
  int frac2; // 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.
  tempData2 = (double)(((data_high & 0x007F) << 8) + data_low);
  tempData2 = (tempData1 * tempFactor2)-0.01;

  float celcius2 = tempData2 - 273.15;
  
/* Sensor A3 Readings...

  //This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
  double tempFactor3 = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
  double tempData3 = 0x0000; // zero out the data
  int frac3; // 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.
  tempData3 = (double)(((data_high & 0x007F) << 8) + data_low);
  tempData3 = (tempData1 * tempFactor3)-0.01;

  float celcius3 = tempData3 - 273.15;
*/

// Print Data To Screen...
  Serial.print("Temp sensor: A1: ");
  Serial.print(celcius1);
  Serial.print(" A2: ");
  Serial.println(celcius2);
  //Serial.print(" A3:");
  //Serial.println(celcius3);

  delay(3000); // wait 3 seconds before printing again
}


btw the i2cmaster can be found here http://homepage.hispeed.ch/peterfleury/i2cmaster.zip
« Last Edit: February 02, 2012, 05:08:23 am by ginner159 » Logged

Seattle
Offline Offline
Newbie
*
Karma: 0
Posts: 25
ummm?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What happens when you run your code?  The only thing that immediately pops to mind (I'm new at this, too)
is that you might need to wait a few cycles between reading different devices on the bus...  

or maybe start each device, read it, stop it, THEN move to the next one. 

t
« Last Edit: February 02, 2012, 12:00:24 pm by TobyB » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 223
Posts: 13878
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Cleaned up your code by making a function of the most important part. The code is essential the same but as it is much smaller it is easier to debug I think.

BTW double == float on Arduino

Code:
#include <i2cmaster.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("Setup...");
  
  setupI2CBus();
}

void loop()
{
  float celcius1 = readDevice(A1);
  float celcius2 = readDevice(A2);
  float celsius3 = readDevice(A3);

  // Print Data To Screen...
  Serial.print("Temp sensor: A1: ");
  Serial.print(celcius1);
  Serial.print(" A2: ");
  Serial.println(celcius2);
  Serial.print(" A3:");
  Serial.println(celcius3);

  delay(3000);
}

/////////////////////////////////////////////////////////
//
// helper functions
//
void setupI2CBus()
{
  i2c_init(); //Initialise the i2c bus
  PORTC = (1 << PORTC4) | (1 << PORTC5); //enable pullups
}

float readDevice(int address)
{
  int dev = address << 1;
  int data = 0;
  int pec = 0;

  // RAW READ
  i2c_start_wait(dev + I2C_WRITE);

  i2c_write(0x07);

  i2c_rep_start(dev + I2C_READ);

  data = i2c_readAck() * 256;
  data = data + i2c_readAck();

  pec = i2c_readNak();

  i2c_stop();
  
  // PROCESS DATA
  data = data & 0x7FFF;
  float temp = (data * 0.02) - 273.16;
  return temp;
}

Hope this helps..
« Last Edit: February 06, 2012, 10:42:48 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Silsden
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi

1st off wow! that code is tiny!! smiley-grin and i would never of thought of setting it up that way.

i was just wondering if you could possibly guide my through the code a little. This is my first ever C/C++ coding and what I've managed to do so far has been a mash up between reading the data sheet, internet searches and the forums on here.

What im trying get my head round is how each device is initiated smiley-confuse.

thanks again, and sorry im such a n00b  smiley-eek-blue

matt
Logged

Silsden
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What happens when you run your code?  The only thing that immediately pops to mind (I'm new at this, too)
is that you might need to wait a few cycles between reading different devices on the bus... 

or maybe start each device, read it, stop it, THEN move to the next one.

When i run the code both the one i posted and the one by robtillaart, all i get from the serial port is "Setup....."

One thing that im wondering is. i made myself a small I2C connected device scanner using a different library. when i run that it shows it found devices at 0x21 & 0x22 ?? when in my initial setup i named the devices 0xA1 & 0xA2. is this something todo with the byte shift thing "<<1"?

cheers again everyone for the help
matt
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 223
Posts: 13878
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I made a mistakewith teh adresses (forgot the 0x)

use the addresses found with the I2C scanner and change your code to this, could work better
(not tested smiley
Code:
#include <i2cmaster.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("Setup...");
  
  setupI2CBus();
}

void loop()
{
  float celcius1 = readDevice(0x21);   // addresses from the scanner
  float celcius2 = readDevice(0x22);  
  float celsius3 = readDevice(0x23);

  // Print Data To Screen...
  Serial.print("Temp sensor: A1: ");
  Serial.print(celcius1);
  Serial.print(" A2: ");
  Serial.println(celcius2);
  Serial.print(" A3:");
  Serial.println(celcius3);

  delay(3000);
}

/////////////////////////////////////////////////////////
//
// helper functions
//
void setupI2CBus()
{
  i2c_init(); //Initialise the i2c bus
  PORTC = (1 << PORTC4) | (1 << PORTC5); //enable pullups
}

float readDevice(int address)
{
  int dev = address << 1;   // might also be dev = address without the shift
  int data = 0;
  int pec = 0;

  // RAW READ
  i2c_start_wait(dev + I2C_WRITE);

  i2c_write(0x07);

  i2c_rep_start(dev + I2C_READ);

  data = i2c_readAck() * 256;
  data = data + i2c_readAck();

  pec = i2c_readNak();

  i2c_stop();
  
  // PROCESS DATA
  data = data & 0x7FFF;
  float temp = (data * 0.02) - 273.16;
  return temp;
}

you might need to leave out the shift, in the first line of the function readDevice().

Give it a 2nd try smiley-wink
« Last Edit: February 06, 2012, 10:43:27 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Silsden
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for getting back!

i tried it again using the names received from the scanner and the output is as follows;

Code:
Setup...
Temp sensor:
 > A1: 2.06
 > A2: 2.06
 > A3: 2.06
Temp sensor:
 > A1: 2.08
 > A2: 2.08
 > A3: 2.08
Temp sensor:
 > A1: 2.07
 > A2: 2.07
 > A3: 2.07

Also the ' << 1 ' is needed in the address otherwise  it wont read anything also states in the data sheet. Im at a bit of a loss on how to do it.

gonna keep trying over the weekend and will update if i make a breakthrough. If not i will ask my tutor for help and then repost what I found. eventually the data is going to be sent via the CANSheild, but thats for a nother day smiley smiley-cool
Logged

New Jersey
Offline Offline
Faraday Member
**
Karma: 70
Posts: 3732
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Shouldn't there be a
Code:
return temp;
after
Code:
float temp = (data * 0.02) - 273.16;
?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 223
Posts: 13878
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

definitely wildbill!  (fixed in posts above)

ginner159, please add that line with the return statement as Bill proposed.

- have no such sensor at hand and spitted out the code without testing ;(

« Last Edit: February 06, 2012, 10:44:05 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Silsden
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

cheers guys that made it work to a point...

what i mean is the devices are reading between -180 & -80 degress C ???

ill have a look at the code again soon and see if its to do with the maths encoded but over this weekend my grphics card in my laptop has jacked in but i will update if i work it out.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 223
Posts: 13878
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


looked at the datasheet   - http://www.melexis.com/Assets/IR-sensor-thermometer-MLX90614-Datasheet-5152.aspx -
and the math/code seems to be OK
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Seattle
Offline Offline
Newbie
*
Karma: 0
Posts: 25
ummm?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using the same math and it works on a single device.

I've had that experience, though, when I read the wrong addresses or 8- bit bytes from the device.

The device really demands that you start, send the byte read command, read all 3 8- bit bytes (hi, lo, pec) then stop it.

t
Logged

Silsden
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey again!

ive managed to sort it out! YAY  smiley-cool smiley-grin

speaking with my tutor we found that the code wildbill posted was only getting 8bits instated of the full 16 needed. turns out if i just used the original and add a return at the end it works!  smiley-roll-blue

here is what my code now looks like for anybody interested. i changed the device names as to fit better with the project implementation and added an extra device.

Code:
#include <i2cmaster.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("Setup...");
 
  // Setup I2CBus
  i2c_init(); //Initialise then,
  PORTC = (1 << PORTC4) | (1 << PORTC5); //enable pullups
}

void loop()
{
  float temperature1 = readDevice(0x51);   // addresses from the scanner
  float temperature2 = readDevice(0x52); 
  float temperature3 = readDevice(0x53);
  float temperature4 = readDevice(0x54);

  // Print Data To Screen...
  Serial.println("Temperature Readings (*c):");
  Serial.print("> A1(51): ");
  Serial.println(temperature1);
  Serial.print("> A2(52): ");
  Serial.println(temperature2);
  Serial.print("> A3(53): ");
  Serial.println(temperature3);
  Serial.print("> A4(54): ");
  Serial.println(temperature4);

  delay(2000);
}

/////////////////////////////////////////////////////////
//
// helper functions
//

float readDevice(int address)
{
  int dev = address << 1;
  int data_low = 0;
  int data_high = 0;
  int pec = 0;

  // RAW READ
  i2c_start_wait(dev + I2C_WRITE);

  i2c_write(0x07);

  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;

  //Process tempData
  float objTemp = tempData - 273.15;
  delay(500);
  return objTemp;

}

Ive tried myself from what ive gathered on the net but struggling and unsure if it is possible change the device names into an array format and still print out the same??
Not to worry if not, just the final system would be reading from a min of 12 devices:

tempArea1[4]={0x51, 0x52, 0x53, 0x54};
tempArea2[4]=(0x61, 0x62, 0x63, 0x64};
tempArea3...
and so on..

cheers for all your help!
Logged

Pages: [1] 2 3   Go Up
Jump to: