Go Down

Topic: Read EEPROM from MLX90614 over I2C (Read 2005 times) previous topic - next topic

banff

Dec 29, 2015, 12:30 pm Last Edit: Dec 29, 2015, 02:34 pm by robtillaart
Hello everybody!

I have some problems to read out the EEPROM of my MLX90614 DCI infrared sensor, which is connected via I2C to my Arduino Uno. So the problem is less the sensor, than my limited programing skills..

To set a new emissivity I need to change the values in two EEPROM cells of the MLX, 0x04 and 0x0F. However, I'm not familiar with the wire library and only wanted to read out the current values by using to following code:

Code: [Select]

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_MLX90614.h>


Adafruit_MLX90614 mlx = Adafruit_MLX90614();
#define MLX90614_I2CADRESS 0x5A

//float emissivity = 0.95;  //0xF332 in hex, which is the new value, but not used here


void setup() {
  Serial.begin(9600);
  Wire.begin();
  mlx.begin();

}

void loop() {
  
Wire.beginTransmission(MLX90614_I2CADRESS);
 Wire.requestFrom(0x04, 2);     //cell with the emissivity, factory default 1 (0xFFFF), 16bit long

  while(Wire.available()) {
    char c = Wire.read();    
    Serial.print(c);

Wire.endTransmission();
 }
}


But it is not working. There is no error occuring when I upload the code on the Arduino, but there is nothing shown in the serial monitor.

I found something similar in the forum: https://forum.arduino.cc/index.php?topic=55524.0
Unfortunately, I cannot find the used i2cmaster library which is used there and more over I don't really know what the code is all about. I only want to read the content of the cells and write some new values to them. This shouldn't be that much code or am I wrong?

Thanks a lot in advance!
Regards,
banff

robtillaart

#1
Dec 29, 2015, 02:34 pm Last Edit: Dec 29, 2015, 02:35 pm by robtillaart
Moderator: updated the title to better reflect the problem
Rob Tillaart

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

banff

I had a closer look on the adafruit MLX90614 library and i found something that might help to get rid of my problem.

Code: [Select]
class Adafruit_MLX90614  {
 public:
  Adafruit_MLX90614(uint8_t addr = MLX90614_I2CADDR);
  boolean begin();
  uint32_t readID(void);

  double readObjectTempC(void);
  double readAmbientTempC(void);
  double readObjectTempF(void);
  double readAmbientTempF(void);

 private:
  float readTemp(uint8_t reg);

  uint8_t _addr;
  uint16_t read16(uint8_t addr);
  void write16(uint8_t addr, uint16_t data);
};


read16() and write16 should work for my purpose. uint8_t is the adress, as it is 8bit long and uint16_t for my desired value, right?

But I was irritated by the following: The Melexis datasheet says that 0x04 is the adress for the emissivity. In the Adafruit library it is: #define MLX90614_EMISS 0x24
So which one is it?

Thanks and regards,
banff

jremington

#3
Dec 29, 2015, 07:57 pm Last Edit: Dec 29, 2015, 08:19 pm by jremington
I would trust the datasheet.

The correction can be applied after you make the measurement -- there is no need to update the sensor. For the record, you need to acquire both the ambient (chip) temperature Ta, and the object temperature Tom in Kelvin. The corrected object temperature Toc is given by the following expression in C, where eps is the actual surface emissivity:

Toc = pow( ( ( (pow(Tom,4)-pow(Ta,4))/eps) + pow(Ta,4) ), 0.25);

banff

I would trust the datasheet.

The correction can be applied after you make the measurement -- there is no need to update the sensor. For the record, you need to acquire both the ambient (chip) temperature Ta, and the object temperature Tom in Kelvin. The corrected object temperature Toc is given by the following expression in C, where eps is the actual surface emissivity:

Toc = pow( ( ( (pow(Tom,4)-pow(Ta,4))/eps) + pow(Ta,4) ), 0.25);
It was not passible to test the adress, because the functions in the mlx90614 library I mentioned are private.. So there will be no way to use them right?
However, with your calculation I got very similar results (+- 0.1°C) to my previous, where I simply multiplied the measured value of the object temperature with the emissivity.
Thank you.

robtillaart

#5
Dec 30, 2015, 02:44 pm Last Edit: Dec 30, 2015, 02:44 pm by robtillaart
>> Toc = pow( ( ( (pow(Tom,4)-pow(Ta,4))/eps) + pow(Ta,4) ), 0.25);

quite expensive formula, can be done substantial faster

Tom4 = Tom * Tom;
Tom4 = Tom4*Tom4;
Ta4 = Ta * Ta;
ta4 = Ta4*Ta4;

Toc = pow(((Tom4 -Ta4)/eps) + Ta4), 0.25);

the latter line can be optimized to Toc = sqrt(sqrt((((Tom4 - Ta4) / eps) + Ta4)));

testsketch
Code: [Select]
//
//    FILE: performance.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: demo
//    DATE: 2015-12-30
//     URL: http://forum.arduino.cc/index.php?topic=368545
//
// Released to the public domain
//

uint32_t start;
uint32_t stop;

float Tom = 300.0;
float Ta = 1.23;
float Tom4, Ta4, Toc;
float eps = 0.1;

void setup()
{
  Serial.begin(115200);
  Serial.print("Start ");
  Serial.println(__FILE__);

  start = micros();
  Toc = pow((((pow(Tom, 4) - pow(Ta, 4)) / eps) + pow(Ta, 4) ), 0.25);
  stop = micros();
  Serial.print(stop - start);
  Serial.print("\t");
  Serial.println(Toc, 7);
  delay(1000);

  start = micros();
  Tom4 = Tom * Tom;
  Tom4 = Tom4 * Tom4;
  Ta4 = Ta * Ta;
  Ta4 = Ta4 * Ta4;

  Toc = pow((((Tom4 - Ta4) / eps) + Ta4), 0.25);
  stop = micros();
  Serial.print(stop - start);
  Serial.print("\t");
  Serial.println(Toc, 7);
  delay(1000);

  start = micros();
  Tom4 = Tom * Tom;
  Tom4 = Tom4 * Tom4;
  Ta4 = Ta * Ta;
  Ta4 = Ta4 * Ta4;
  Toc = sqrt(sqrt((((Tom4 - Ta4) / eps) + Ta4)));
  stop = micros();
  Serial.print(stop - start);
  Serial.print("\t");
  Serial.println(Toc, 7);
  delay(1000);
}

void loop()
{
}


output:

1156   533.4833984
424   533.4837036
152   533.4838256


so 7x faster is possible
Rob Tillaart

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

banff

>> Toc = pow( ( ( (pow(Tom,4)-pow(Ta,4))/eps) + pow(Ta,4) ), 0.25);

quite expensive formula, can be done substantial faster

Tom4 = Tom * Tom;
Tom4 = Tom4*Tom4;
Ta4 = Ta * Ta;
ta4 = Ta4*Ta4;

Toc = pow(((Tom4 -Ta4)/eps) + Ta4), 0.25);

the latter line can be optimized to Toc = sqrt(sqrt((((Tom4 - Ta4) / eps) + Ta4)));



optimization is good, but I don't understand why Tom*Tom = Tom4 and Tom4*Tom4 = Tom4 also? And the same with Ta.
What does the 4 mean? To the power of 4?

Thanks again

robtillaart

optimization is good, but I don't understand why Tom*Tom = Tom4 and Tom4*Tom4 = Tom4 also? And the same with Ta.
What does the 4 mean? To the power of 4?

Thanks again
indeed, the 4 indicates to the power of 4.
More descriptive names are better however you got the idea. Maybe introduce Tom2 for tom squared but that would introduce an extra variable (probably the compiler would optimize it away). Would be easier to understand.

Tom2 = Tom * Tom;
Tom4 = Tom2 * Tom2;
Rob Tillaart

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

banff

>> Toc = pow( ( ( (pow(Tom,4)-pow(Ta,4))/eps) + pow(Ta,4) ), 0.25);

quite expensive formula, can be done substantial faster

Tom4 = Tom * Tom;
Tom4 = Tom4*Tom4;
Ta4 = Ta * Ta;
ta4 = Ta4*Ta4;

Toc = pow(((Tom4 -Ta4)/eps) + Ta4), 0.25);

the latter line can be optimized to Toc = sqrt(sqrt((((Tom4 - Ta4) / eps) + Ta4)));

robtillaart, can you tell me where you got this formula from?
Thanks,
banff

jremington

Rob Tillaart optimized for calculation speed a formula that I posted.

The procedure is outlined here: http://www.melexis.com/Asset/Changing-emissivity-MLX90614xxx-DownloadLink-5813.aspx

Apparently you now have to register with Melexis to read it.

banff

Rob Tillaart optimized for calculation speed a formula that I posted.
Yes, sorry, you're right.

The procedure is outlined here: http://www.melexis.com/Asset/Changing-emissivity-MLX90614xxx-DownloadLink-5813.aspx

Apparently you now have to register with Melexis to read it.
However, I can't read it, but I'm registered. Whenever I copy your link, I'm forwarded to the page which asks for registration.
But if it is the PDF which explaines the change of emissivity from Melexis, I already got it.
The formula of emissivity: E=(TOnew^4-TAnew^4)/(TOreal^4-TAreal^4). Do you solve for TOnew or TOreal?

Tanks, banff

jremington

#11
Jan 11, 2016, 04:22 am Last Edit: Jan 11, 2016, 04:22 am by jremington
I found their notation confusing, so I rewrote the formula for eps as follows (assuming Ta is constant)
Code: [Select]

        Tom^4 - Ta^4
eps= -----------------
        Toc^4 - Ta^4

and solved for Toc, the corrected object temperature. This requires that eps in the sensor is set to 1.0

cyril_mathew

I had a closer look on the adafruit MLX90614 library and i found something that might help to get rid of my problem.

Code: [Select]
class Adafruit_MLX90614  {
 public:
  Adafruit_MLX90614(uint8_t addr = MLX90614_I2CADDR);
  boolean begin();
  uint32_t readID(void);

  double readObjectTempC(void);
  double readAmbientTempC(void);
  double readObjectTempF(void);
  double readAmbientTempF(void);

 private:
  float readTemp(uint8_t reg);

  uint8_t _addr;
  uint16_t read16(uint8_t addr);
  void write16(uint8_t addr, uint16_t data);
};


read16() and write16 should work for my purpose. uint8_t is the adress, as it is 8bit long and uint16_t for my desired value, right?

But I was irritated by the following: The Melexis datasheet says that 0x04 is the adress for the emissivity. In the Adafruit library it is: #define MLX90614_EMISS 0x24
So which one is it?

Thanks and regards,
banff
Though the datasheet says that the address of emissivity value is 0x04, the command opcode for EEPROM starts with 001XXXXX. Hence the address which needs to be sent is 0x24 and not 0x04.

Sending 0x04 access the RAM of the device.

Go Up