//   Read and Write to Melexis MLX90614 over SMBus
//   http://www.MKRD.info/
//   8April2015
//   Revision 3
#include <i2cmaster.h> //For Melexis SMBus communication
////////////////////////////////Thermal Infrared sensor variables and
constants/////////
int thermal_dev = 0x5A << 1; //Default MLX90614 address in Hex, shifted left by one
bit due to I2C protocol
int Tomax_low = 0; //Initializing low byte of Tomax data
int Tomax_high = 0; //Initializing high byte of Tomax data
int Tomax = 0;
int Tomin_low = 0; //Initializing low byte of Tomin data
int Tomin_high = 0; //Initializing high byte of Tomin data
int Tomin = 0;
int PWMCTRL_low = 0; //Initializing low byte of PWMCTRL data
int PWMCTRL_high = 0; //Initializing high byte of PWMCTRL data
int PWMCTRL = 0;
int Ta_range_low = 0; //Initializing low byte of Ta_range data
int Ta_range_high = 0; //Initializing high byte of Ta_range data
int Ta_range = 0;
int Emissivity_correction_coefficient_low = 0; //Initializing low byte of
Emissivity_correction_coefficient data
int Emissivity_correction_coefficient_high = 0; //Initializing high byte of
Emissivity_correction_coefficient data
int Emissivity_correction_coefficient = 0;
int Config_Register1_low = 0; //Initializing low byte of Config_Register1 data
int Config_Register1_high = 0; //Initializing high byte of Config_Register1 data
int Config_Register1 = 0;
int SMBus_address_LSByte_only_low = 0; //Initializing low of
SMBus_address_LSByte_only data
int SMBus_address_LSByte_only_high = 0; //Initializing high byte of
SMBus_address_LSByte_only data
int SMBus_address_LSByte_only = 0;
int ID_number_C_low = 0; //Initializing low byte of ID_number_C data
int ID_number_C_high = 0; //Initializing high byte of ID_number_C data
int ID_number_C = 0;
int ID_number_D_low = 0; //Initializing low byte of ID_number_D data
int ID_number_D_high = 0; //Initializing high byte of ID_number_D data
int ID_number_D = 0;
int ID_number_E_low = 0; //Initializing low byte of ID_number_E data
int ID_number_E_high = 0; //Initializing high byte of ID_number_E data
int ID_number_E = 0;
int ID_number_F_low = 0; //Initializing low byte of ID_number_F data
int ID_number_F_high = 0; //Initializing high byte of ID_number_F data
int ID_number_F = 0;
int thermal_pec = 0;        //Initializing PEC. TODO check that this is calculated
properly, or at least ignored properly
///////////////////////////////////////////////////////////////////////////////////
/////
void setup()
{
  ////////////////////Initialize I2C ////////////////////
  i2c_init(); //Initialise the I2C bus
  PORTC = (1 << PORTC4) | (1 << PORTC5); //enable pullups, but this is not
necessary as I am using external resistors
  ////////////////////////////////////////////////////////
  Serial.begin(9600);
  //////////////// Read Melexis EEPROM Tomin over SMBUS to obtain default
values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x00); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  Tomax_low = i2c_readAck(); //Read 1 byte and then send ack
  Tomax_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  Tomax = (Tomax_high << 8) | Tomax_low;
  Serial.println();
  Serial.print("Tomax   decimal: ");
  Serial.print(Tomax,   DEC);
  Serial.println();
  Serial.print("Tomax   hex: ");
  Serial.print(Tomax,   HEX);
  Serial.println();
  Serial.print("Tomax   binary: ");
  Serial.print(Tomax,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM Tomin over SMBUS to obtain default
values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x01); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  Tomin_low = i2c_readAck(); //Read 1 byte and then send ack
  Tomin_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  Tomin = (Tomin_high << 8) | Tomin_low;
  Serial.println();
  Serial.print("Tomin   decimal: ");
  Serial.print(Tomin,   DEC);
  Serial.println();
  Serial.print("Tomin   hex: ");
  Serial.print(Tomin,   HEX);
  Serial.println();
  Serial.print("Tomin   binary: ");
  Serial.print(Tomin,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM PWMCTRL over SMBUS to obtain default
values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x02); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  PWMCTRL_low = i2c_readAck(); //Read 1 byte and then send ack
  PWMCTRL_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  PWMCTRL = (PWMCTRL_high << 8) | PWMCTRL_low;
  Serial.println();
  Serial.print("PWMCTRL   decimal: ");
  Serial.print(PWMCTRL,   DEC);
  Serial.println();
  Serial.print("PWMCTRL   hex: ");
  Serial.print(PWMCTRL,   HEX);
  Serial.println();
  Serial.print("PWMCTRL   binary: ");
  Serial.print(PWMCTRL,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM Ta_range over SMBUS to obtain default values
////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x03); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  Ta_range_low = i2c_readAck(); //Read 1 byte and then send ack
  Ta_range_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  Ta_range = (Ta_range_high << 8) | Ta_range_low;
  Serial.println();
  Serial.print("Ta_range   decimal: ");
  Serial.print(Ta_range,   DEC);
  Serial.println();
  Serial.print("Ta_range   hex: ");
  Serial.print(Ta_range,   HEX);
  Serial.println();
  Serial.print("Ta_range   binary: ");
  Serial.print(Ta_range,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM Emissivity_correction_coefficient over SMBUS
to obtain default values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x04); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  Emissivity_correction_coefficient_low = i2c_readAck(); //Read 1 byte and then
send ack
  Emissivity_correction_coefficient_high = i2c_readAck(); //Read 1 byte and then
send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  Emissivity_correction_coefficient = ((Emissivity_correction_coefficient_high <<
8) | Emissivity_correction_coefficient_low);
  Serial.println();
  Serial.print("Emissivity_correction_coefficient decimal: ");
  Serial.print(Emissivity_correction_coefficient, DEC);
  Serial.println();
  Serial.print("Emissivity_correction_coefficient   hex: ");
  Serial.print(Emissivity_correction_coefficient,   HEX);
  Serial.println();
  Serial.print("Emissivity_correction_coefficient   binary: ");
  Serial.print(Emissivity_correction_coefficient,   BIN);
  Serial.println();
//   printf("Printf: %x", Emissivity_correction_coefficient);
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM Config_Register1 over SMBUS to obtain
default values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x05); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  Config_Register1_low = i2c_readAck(); //Read 1 byte and then send ack
  Config_Register1_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  Config_Register1 = (Config_Register1_high << 8) | Config_Register1_low;
  Serial.println();
  Serial.print("Config_Register1   decimal: ");
  Serial.print(Config_Register1,   DEC);
  Serial.println();
  Serial.print("Config_Register1   hex: ");
  Serial.print(Config_Register1,   HEX);
  Serial.println();
  Serial.print("Config_Register1   binary: ");
  Serial.print(Config_Register1,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM SMBus_address_LSByte_only over SMBUS to
obtain default values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x0E); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  SMBus_address_LSByte_only_low = i2c_readAck(); //Read 1 byte and then send ack
  SMBus_address_LSByte_only_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  SMBus_address_LSByte_only = (SMBus_address_LSByte_only_high << 8) |
SMBus_address_LSByte_only_low;
  Serial.println();
  Serial.print("SMBus_address_LSByte_only   decimal: ");
  Serial.print(SMBus_address_LSByte_only,   DEC);
  Serial.println();
  Serial.print("SMBus_address_LSByte_only   hex: ");
  Serial.print(SMBus_address_LSByte_only,   HEX);
  Serial.println();
  Serial.print("SMBus_address_LSByte_only   binary: ");
  Serial.print(SMBus_address_LSByte_only,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM ID_number_C over SMBUS to obtain default
values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x1C); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  ID_number_C_low = i2c_readAck(); //Read 1 byte and then send ack
  ID_number_C_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  ID_number_C = (ID_number_C_high << 8) | ID_number_C_low;
  Serial.println();
  Serial.print("ID_number_C   decimal: ");
  Serial.print(ID_number_C,   DEC);
  Serial.println();
  Serial.print("ID_number_C   hex: ");
  Serial.print(ID_number_C,   HEX);
  Serial.println();
  Serial.print("ID_number_C   binary: ");
  Serial.print(ID_number_C,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM ID_number_D over SMBUS to obtain default
values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x1D); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  ID_number_D_low = i2c_readAck(); //Read 1 byte and then send ack
  ID_number_D_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  ID_number_D = (ID_number_D_high << 8) | ID_number_D_low;
  Serial.println();
  Serial.print("ID_number_D   decimal: ");
  Serial.print(ID_number_D,   DEC);
  Serial.println();
  Serial.print("ID_number_D   hex: ");
  Serial.print(ID_number_D,   HEX);
  Serial.println();
  Serial.print("ID_number_D   binary: ");
  Serial.print(ID_number_D,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM ID_number_E over SMBUS to obtain default
values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
  i2c_start_wait(thermal_dev + I2C_WRITE);
  i2c_write(0b00100000 | 0x1E); //0b00100000 for EEPROM ACCESS
  // read
  i2c_rep_start(thermal_dev + I2C_READ);
  ID_number_E_low = i2c_readAck(); //Read 1 byte and then send ack
  ID_number_E_high = i2c_readAck(); //Read 1 byte and then send ack
  thermal_pec = i2c_readNak();
  i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  ID_number_E = (ID_number_E_high << 8) | ID_number_E_low;
  Serial.println();
  Serial.print("ID_number_E   decimal: ");
  Serial.print(ID_number_E,   DEC);
  Serial.println();
  Serial.print("ID_number_E   hex: ");
  Serial.print(ID_number_E,   HEX);
  Serial.println();
  Serial.print("ID_number_E   binary: ");
  Serial.print(ID_number_E,   BIN);
  Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
  //////////////// Read Melexis EEPROM ID_number_F over SMBUS to obtain default
values ////////////////
  /*
  Tomax 0x00
  Tomin 0x01
  PWMCTRL 0x02
  Ta range 0x03
  Emissivity correction coefficient 0x04
  Config Register1 0x05
  SMBus address (LSByte only) 0x0E
  ID number 0x1C
  ID number 0x1D
  ID number 0x1E
  ID number 0x1F
  */
    i2c_start_wait(thermal_dev + I2C_WRITE);
    i2c_write(0b00100000 | 0x1F); //0b00100000 for EEPROM ACCESS
    // read
    i2c_rep_start(thermal_dev + I2C_READ);
    ID_number_F_low = i2c_readAck(); //Read 1 byte and then send ack
    ID_number_F_high = i2c_readAck(); //Read 1 byte and then send ack
    thermal_pec = i2c_readNak();
    i2c_stop();
  //This converts high and low bytes together - moves it left 8 bits and adds the
low byte.
  ID_number_F = (ID_number_F_high << 8) | ID_number_F_low;
    Serial.println();
    Serial.print("ID_number_F   decimal: ");
    Serial.print(ID_number_F,   DEC);
    Serial.println();
    Serial.print("ID_number_F   hex: ");
    Serial.print(ID_number_F,   HEX);
    Serial.println();
    Serial.print("ID_number_F   binary: ");
    Serial.print(ID_number_F,   BIN);
    Serial.println();
  /////////////////END of Read Melexis EEPROM over SMBUS to obtain default
values/////////////////////////////////////////////
void loop() //MAIN LOOP
{
}//LOOPING