Loading...
Pages: [1]   Go Down
Author Topic: Multiple Melexis MLX90614 on the same i2c, how to change addresses ??  (Read 4613 times)
0 Members and 1 Guest are viewing this topic.
Vienna
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I have two MLX90614 sensors and wanna connect both on the i2cbus. How can I change the address of one of these parts ? I use the i2cmaster from peter fleury (thx!) and have found a codepart in a forum. There is mentioned the address 0x2E for the address register, in the datasheet I have read the address 00Eh - what is correct ?? Does anybody have experiences (and a tested code) for this intention ??

// Now change address. First erase
i2cstartwait(dev+I2CWRITE);  //send start condition and write bit
i2cwrite(0x2E);  //send command for device to return address
i2cwrite(0x00);  // send low byte zero to erase
i2cwrite(0x00);  //send high byte zero to erase
i2cwrite(0x6F);  // send PEC
i2cstop();  //Release bus, end transaction
delay(100); // then wait 10ms

// Then write new address
i2cstartwait(dev+I2CWRITE);  //send start condition and write bit
i2cwrite(0x2E);  //send command for device to return address
i2cwrite(0x50);  // send low byte of address
i2cwrite(0x00);  //send high byte of address
i2cwrite(0x63); // send PEC
i2cstop(); //Release bus, end transaction
delay(100); // then wait 10ms

Logged

arduino newbie...

0
Offline Offline
Jr. Member
**
Karma: 4
Posts: 64
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

Logged

0
Offline Offline
Jr. Member
**
Karma: 4
Posts: 64
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
Logged

Vienna
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

arduino newbie...

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

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.
Logged

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

Has anyone found a solution to this? I'm having the same problem! I've tried various combinations of addresses with CRCs from http://smbus.org/faq/crc8Applet.htm, but no luck yet.
Logged

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

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.

Code:
#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;
}
« Last Edit: September 12, 2011, 11:23:52 am by paulrd » Logged

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

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
Code:
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 smiley

NEVER MIND!!!
I figured it out smiley
« Last Edit: January 26, 2012, 12:41:36 pm by ginner159 » Logged

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

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
Logged

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

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

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

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.

Code:
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(){
}
« Last Edit: April 30, 2013, 04:44:39 pm by chris_flesher » Logged

Pages: [1]   Go Up
Print
 
Jump to: