Multiple Melexis MLX90614 on the same i2c, how to change addresses ??

There's a pretty awesome example here:

http://bildr.org/2011/02/mlx90614-arduino/

I hope it helps you instead of confusing you even more (I'm still a bit confused myself)

The Melexis data sheet lists the address in two different ways and places

on Page 11

8.3.3 EEPROM (32x16)

SMBus address 00Eh

Then on page 14

8.4.1 Functional Description

....write access to 9 EEPROM cells (at addresses .....0x2Eh....)

I am enough of a beginner that I think this could be something about memory addressing or Hex number format that I just don't understand.

one thing about your code, a spy, that seems off is the fact you are attempting to write a PEC to the device... I would guess there's no point to that.

Do you have the 3.3V version of the device?

after a bit more investigation, my money is on 00Eh as being the correct address for holding the address.

The bildr post led me to a Melexis PDF publication about changing the Emissivity of the sensor in which the address for Emissivity is described as 0x04.

this corresponds to the data from Page 11 and I'd say 2 of 3 wins.

I wish you success!

Thanks a lot, I will check it on the weekend... you will hear from me !!

Can someone please post full working code for changing addresses? Or link to work code. Huge thank you. This code is confusing me (apparently along with others). I really need to move on from this headache.

Has anyone found a solution to this? I'm having the same problem! I've tried various combinations of addresses with CRCs from CRC-8 Calculator, but no luck yet.

Ok I've solved it, as least as far as I need to. The code below rewrites the EEPROM location for the slave address and tries all possible CRC bytes until it finds the correct one. Be sure to cycle the power to the MLX after writing to it, or you get strange results.

I'm not sure what the second address config byte does, but for my purposes an address in the first location and a zero in the second seemed to work.

#include <i2cmaster.h>
// Pins: Standard: SDA:A4  SCL:A5
//       Mega:     SDA:D20 SCL:D21

byte MLXAddr = 0x5A<<1;           // Default address
//byte MLXAddr = 0;               // Universal address

void setup(){
  Serial.begin(9600);
  Serial.println("Setup...");
  
  i2c_init();                              //Initialise the i2c bus
  PORTC = (1 << PORTC4) | (1 << PORTC5);   //enable pullups
  
  delay(5000);                    // Wait to allow serial connection
  ReadAddr(0);                    // Read current address bytes
  ChangeAddr(0x55, 0x00);         // Change address to new value
  //ChangeAddr(0x5A, 0xBE);       // Change address to default value
  ReadAddr(0);                    // Read address bytes
  delay(5000);                    // Cycle power to MLX during this pause
  ReadTemp(0);                    // Read temperature using default address
  ReadTemp(MLXAddr);              // Read temperature using new address
}

void loop(){
    delay(1000); // wait a second
}

word ChangeAddr(byte NewAddr1, byte NewAddr2) {

  Serial.println("> Change address");

  i2c_start_wait(0 + I2C_WRITE);    //send start condition and write bit
  i2c_write(0x2E);                  //send command for device to return address
  i2c_write(0x00);                  // send low byte zero to erase
  i2c_write(0x00);                  //send high byte zero to erase
  if (i2c_write(0x6F) == 0) {
    i2c_stop();                     //Release bus, end transaction
    Serial.println("  Data erased.");
  }
  else {
    i2c_stop();                     //Release bus, end transaction
    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);  //send start condition and write bit
    i2c_write(0x2E);                //send command for device to return address
    i2c_write(NewAddr1);            // send low byte zero to erase
    i2c_write(NewAddr2);            //send high byte zero to erase
    if (i2c_write(a) == 0) {
      i2c_stop();                   //Release bus, end transaction
      delay(100);                   // then wait 10ms
      Serial.print("Found correct CRC: 0x");
      Serial.println(a, HEX);
      return a;
    }
  }
  i2c_stop();                       //Release bus, end transaction
  Serial.println("Correct CRC not found");
  return -1;
}

void ReadAddr(byte Address) {

  Serial.println("> Read address");

  Serial.print("  MLX address: ");
  Serial.print(Address, HEX);
  Serial.print(", Data: ");

  i2c_start_wait(Address + I2C_WRITE);  //send start condition and write bit
  i2c_write(0x2E);                  //send command for device to return address
  i2c_rep_start(Address + I2C_READ);
  
  Serial.print(i2c_readAck(), HEX); //Read 1 byte and then send ack
  Serial.print(", ");
  Serial.print(i2c_readAck(), HEX); //Read 1 byte and then send ack
  Serial.print(", ");
  Serial.println(i2c_readNak(), HEX);
  i2c_stop();
}

float ReadTemp(byte Address) {
  int data_low = 0;
  int data_high = 0;
  int pec = 0;

  Serial.println("> Read temperature");

  Serial.print("  MLX address: ");
  Serial.print(Address, HEX);
  Serial.print(", ");

  i2c_start_wait(Address + I2C_WRITE);
  i2c_write(0x07);                  // Address of temp bytes
  
  // read
  i2c_rep_start(Address + 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
  float Temperature = 0x0000;       // zero out the data
  
  // This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
  Temperature = (float)(((data_high & 0x007F) << 8) + data_low);
  Temperature = (Temperature * 0.02) - 273.16;
  
  Serial.print(Temperature);
  Serial.println(" C");
  return Temperature;
}
1 Like

hi
sorry to reopen an old thread but was wondering what values needed to be changed in the code if any? at a guess would it be on line 29 word ChangeAddr(byte NewAdd1, byte NewAddr2)
changing addr1+2 for the vales i require?

cheers in advance
and sorry again for digging this thread up :slight_smile:

NEVER MIND!!!
I figured it out :slight_smile:

Hey,
How do I go back to the default address? I am getting funny values, which part of the code should I change to get a real value.
Thanks.

  • Tosin

Never mind, find the code the read the correct device address. After changing to the correct device address. Everything works well.
Thanks.

I couldn't find any existing code for how to calculate the PEC for the MLX90614... however was able to adapt some code written for a PICAXE to get it working. Haven't fully tested it but seems to work ok so far for writing to EEPROM.

byte calcCrc8(byte X, byte crc) {
  X = X ^ crc;
  for (byte i=0; i<8; i++) {
    if (X > 0x7F) {
      X <<= 1;
      X = X ^ 0x07;
    }
    else {
      X <<= 1;
    }
  }
  return X;
}

byte calcPec(byte slaveAddr, byte memAddr, byte loByte, byte hiByte) {
  byte crc = 0x00;
  byte slaveAddr2 = slaveAddr << 1;
  crc = calcCrc8(slaveAddr2, crc);
  crc = calcCrc8(memAddr, crc);
  crc = calcCrc8(slaveAddr2+1, crc);
  crc = calcCrc8(loByte, crc);
  crc = calcCrc8(hiByte, crc);
  crc = calcCrc8(0x19, crc);
  return crc;
}

void setup(){
  Serial.begin(9600);
  byte pec = calcPec(0x00, 0x2E, 0x00, 0x55);
}

void loop(){
}

Hi guys,

I've tried this code over and over with alot of changes, but I still can't get it working. Anybody having a solution?

Im going to use 4 sensors on the same inputs, but I still can't change the name on them..

Thanks in advance!

Rrvik use the code posted by paulrd but make sure to only have one connected at once
And where it states this

.....
delay(5000);                    // Wait to allow serial connection
  ReadAddr(0);                    // Read current address bytes
  ChangeAddr(0x55, 0x00);         // Change address to new value
  //ChangeAddr(0x5A, 0xBE);       // Change address to default value
  ReadAddr(0);                    // Read address bytes
  delay(5000);                    // Cycle power to MLX during this pause
  ReadTemp(0);                    // Read temperature using default address
  ReadTemp(MLXAddr);              // Read temperature using new address
...

Comment out the first ChangeAddr to reset to default or change it to a new address. Also if I remover correctly (nearly a year since I last used this code) look for a CRC checker as it will make sure you have the correct checking bytes so that the device will respond as expected. I will update if I can find the one I used I think I still have it.

Hope this helps
Reply if you need more help

Hi,

Thanks alot for your help.

I'm using the code right of, with no changes.
All I'm getting on the monitor is:

Setup...

Read address
MLX address: 0, Data: 55, 0, 2C
Change address
Data erased.
Writing data: 55, 0
Found correct CRC: 0x22
Read address
MLX address: 0, Data: 55, 0, 0
Read temperature
MLX address: 0, 23.62 C
Read temperature
MLX address: B4,

And B4, as I am sure you know, is the same as 5A<<1.
And it only replies to that address even after running it with this program..

found the crc check i was using
http://smbus.org/faq/crc8Applet.htm

as for your problem, did you power cycle the device during the address change stage?

Try using this code i used to check the devices had changed the address (made by me :D)

/*****************************************************************************************
 *
 *   Title:         I2C Device Scanner
 *   Author:        Matthew Dinsdale <mdinsdale159@gmail.com>
 *   Date:          Sunday, February 20th, 2012
 *   Availability:  e-mail, or with consent from LJMU FSEA Team.
 *   Compiled Size: 3858 bytes.
 *
 *****************************************************************************************
 * 
 *   The included library and detailed info of each command can be found at
 *   http://dsscircuits.com/articles/arduino-i2c-master-library.html
 * 
 *   Sketch was coded using Version 5 of the library.
 * 
 ******************************************************************************************/

#include <I2C.h>

void setup()
{
  Serial.begin(115200);    //Enable serial output at 115200Baud
  Serial.println("Initialising I2C Scanner...");
  Serial.println();

  PORTC = (1 << PORTC4) | (1 << PORTC5);
  // Pins: Standard: SDA:A4  SCL:A5
  //       Mega:     SDA:D20 SCL:D21

  // Start Read cycle.
  int x = 0;
  int y = 3;     // Run for 'y' times. Change if you feel more is needed.
  while(x < y){
    ++x;

    I2c.begin();   // Starts I2C Protocol.
    delay(1000);   // Wait 1 second to allow all devices to initialise.
    I2c.scan();    // Scans and prints found address. A delay is built into this function.
    I2c.end();     // Stops I2C data.
    Serial.println();
    if (x == y){   // Stops loop once run through 'Y' amount of times.
      break;
    }
  }
  // End of Read cycle.

  // End of program info.
  Serial.println();
  Serial.print("Scanner ran ");
  Serial.print(x); // Prints the ammount of times the device bus was read.
  Serial.println(" times and was able to find the above device names.");
  Serial.println("To restart, Power Cycle or Push Reset button.");
  // Tell user that the script has finished and how to re-run.
  Serial.println("Program complete");
  Serial.println();
}

void loop()
{
  // Not used.
}

It runs 3 times just to make sure that a device wasnt sleeping during the first run time. Wish i could remember some more on what i did to get them working. I can post the code i used to read 4 devices. Hell if i can remember i may make a video!

Hi again,

Thanks alot for trying to help me!

I dont know how to "Power cycle" it, how can I do that?

When I run the program you posted I only get this:

ÑLþ?=%6üQÂÿÛS ábêSSêþ/Ç04þ?<û?%Â^ØB:1?ø

Thanks again

By power cycle it means remove power to the device your programming then reapply. It's a requirement in the data sheet that forces the EEPROM of the device to save its new configuration

As for what I posted have you changed the baud rate that the terminal is using? Should be set to 115200 and the library used is different from that used in coding the sensors. A link to it is in the code description.

May I ask how many you have to change and also what your trying to change them to? I'll try on the sensors I've got to help you out

Ok so I use the program to change the address, and as soon as its done I remove the power and reconnect it again, right?

I just need to have different addresses on them, doesn't matter what adresses.

Is it only the first part that will be the new address? Fx 0x5A 0xBE, it will be 0x5A as address, what does 0xBEdo?

Made it!

Thanks for all help!!

That's great!! Just for your info the 0xBE is the CRC check. I've got 4 of the sensors working on the same bus with 0x00 (will check tonight) and just change the 0x5A to what ever you want it to be. Be carful tho because I remember screwing up one of them because I didn't have the correct CRC. Luckily I had an unused one available so just read all the EEPROM to a file and wrote it back to the device.

have fun!!

Best way to program is with a setup like this

Arduino 5/3.3V --- button (normally closed) --- sensor

That way just press the button during programming.

i'm connecting 2 mlx90614 sensors to my arduino board and if im connecting 1 im getting the result and im haveing the proramme for that but i dont have code for connecting two sensor and get two different outputs can anyone send me the programme to ananatha.yeshwanth@gmail.com