I have a bug somewhere in my code, as new values are not written. Another pair of eyes on my code would be appreciated:
// Read and Write to Melexis MLX90614 Config Register1 0x05 over SMBus
// http://www.MKRD.info/
// 18April2015
// Revision 6
#include <i2cmaster.h> //For Melexis SMBus communication
//Thermal Infrared sensor variables and constants//
//Variables below must be unsigned to prevent sign extension and one's complement representation.
unsigned int i2c_device_address = 0x5A << 1; //Default MLX90614 address in Hex, shifted left by one bit due to I2C protocol
unsigned int Config_Register1_low = 0; //Initializing low byte of Config_Register1 data
unsigned int Config_Register1_high = 0; //Initializing high byte of Config_Register1 data
unsigned int Config_Register1 = 0;
byte Config_Register1_write_low = 0;
byte Config_Register1_write_high = 0;
unsigned 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);
//Notify user of what this program does
Serial.println("This utility reads (and optionally modifies) contents of");
Serial.println("Melexis MLX90614 thermal transducer EEPROM Config Register1");
Serial.println("Reading old data present in EEPROM Config Register1:");
// Read Melexis EEPROM Config_Register1 over SMBUS to obtain default values //
/* Config Register1 0x05 */
i2c_start_wait(i2c_device_address + I2C_WRITE);
i2c_write(0b00100000 | 0x05); //0b00100000 for EEPROM ACCESS
// read
i2c_rep_start(i2c_device_address + 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();
//PRINT FIR AND IIR SEPARATELY
Serial.print("Old IIR: ");
Serial.print(bitRead(Config_Register1, 10));
Serial.print(bitRead(Config_Register1, 9));
Serial.print(bitRead(Config_Register1, 8));
Serial.println();
Serial.print("Old FIR: ");
Serial.print(bitRead(Config_Register1, 2));
Serial.print(bitRead(Config_Register1, 1));
Serial.print(bitRead(Config_Register1, 0));
Serial.println();
Serial.println();
Serial.println("Please copy-paste and/or write down the values");
Serial.println("As these may be overwritten irrevocably!");
//TODO SAVE RESULTS IN FILE
/////////////////END of Read Melexis EEPROM over SMBUS to obtain default values/////////////////////////////////////////////
//Prompt user about whether new value is to be written//
Serial.println();
Serial.println("Do you wish to write to EEPROM");
Serial.println("The following settings");
Serial.println("For fastest settling time?");
Serial.println("EEPROM IIR and FIR settings will be overwritten irrevocably!");
Serial.println("Please copy-paste and/or write down the values");
Serial.println();
Serial.println("New settings which can be written:");
Serial.println("IIR setting: 100 FIR setting: 100");
Serial.println("Settling time (90614xCx) (s): 0.06");
Serial.println("Settling time (90614xAx) (s): 0.04");
Serial.println("Spike limit: 100.00% (none)");
Serial.println("Press Y to write to EEPROM, N or any other button to Exit.");
//RUN IN LOOP UNTIL NO INPUT, THEN ONLY RUN ONCE
boolean keep_looping = true;
while (keep_looping) {
if (Serial.available() > 0) {
switch (Serial.read()) {
case 'Y': {
WriteToEEPROM();
keep_looping = false;
break;
}
case 'N': {
Serial.println("Not changing contents of EEPROM...");
keep_looping = false;
break;
}
default: {
Serial.println("Not changing contents of EEPROM...");
keep_looping = false;
break;
}
}
}
}
}
void loop() //MAIN LOOP
{
//TODO enter low-power mode
}//LOOPING!
void WriteToEEPROM() {
Serial.println("Preparing to write to EEPROM...");
Config_Register1_write_low = byte(Config_Register1);
Config_Register1_write_high = Config_Register1 >> 8;
Serial.println();
Serial.println("Splitting unsigned integer into two bytes");
Serial.print("Config Register1 low byte ");
Serial.print(Config_Register1_write_low, BIN);
Serial.println();
Serial.print("Config Register1 high byte ");
Serial.print(Config_Register1_write_high, BIN);
//CLEAR BITS FOR FIR AND IIR
//00000100 00000100
// FIR IIR
Config_Register1_write_low = Config_Register1_write_low & B11111000;
Config_Register1_write_high = Config_Register1_write_high & B11111000;
Serial.println();
Serial.println();
Serial.println("Clearing bits for FIR and IIR:");
Serial.print("Config Register1 low byte ");
Serial.print(Config_Register1_write_low, BIN);
Serial.println();
Serial.print("Config Register1 high byte ");
Serial.print(Config_Register1_write_high, BIN);
//SET NEW BITS
//00000100 00000100
// FIR IIR
//Config_Register1_write
Config_Register1_write_low = Config_Register1_write_low | B00000100;
Config_Register1_write_high = Config_Register1_write_high | B00000100;
Serial.println();
Serial.println();
Serial.println("New values for Config Register1:");
Serial.print("Config Register1 low byte ");
Serial.print(Config_Register1_write_low, BIN);
Serial.println();
Serial.print("Config Register1 high byte ");
Serial.print(Config_Register1_write_high, BIN);
//WRITE ZERO
Serial.println();
Serial.println();
Serial.println("Erasing EEPROM Config Register1 location...");
byte zeroing_buffer[] = {i2c_device_address << 1, (0b00100000 | 0x05), B00000000, B00000000}; //Concatenate parts of I2C packet into one variable
byte zeroing_crc = crc8(zeroing_buffer, sizeof zeroing_buffer);
Serial.println();
Serial.println();
Serial.print("Calculated Zeroing CRC is: 0x");
Serial.print(zeroing_crc, HEX);
i2c_start_wait(i2c_device_address + I2C_WRITE);
i2c_write(0b00100000 | 0x05); //0b00100000 for EEPROM ACCESS
i2c_write(B00000000); // Zero out low byte of EEPROM location
i2c_write(B00000000); // Zero out high byte of EEPROM location
i2c_write(zeroing_crc); // Checksum
i2c_stop();
delay(50); //Wait for ten times the recommended value of 5ms.
//WRITE BYTES and PEC, Wait
byte calculation_buffer[] = {i2c_device_address << 1, (0b00100000 | 0x05), Config_Register1_write_low, Config_Register1_write_high}; //Concatenate parts of I2C packet into one variable
byte calculated_crc = crc8(calculation_buffer, sizeof calculation_buffer);
Serial.println();
Serial.println();
Serial.print("Calculated Writing CRC is: 0x");
Serial.print(calculated_crc, HEX);
Serial.println();
Serial.println();
Serial.println("Writing new data into EEPROM Config Register1 location...");
i2c_start_wait(i2c_device_address + I2C_WRITE);
i2c_write(0b00100000 | 0x05); //0b00100000 for EEPROM ACCESS
i2c_write(Config_Register1_write_low); // Write low byte to EEPROM location
i2c_write(Config_Register1_write_high); // Write high byte to EEPROM location
i2c_write(calculated_crc); // Checksum
i2c_stop();
delay(50); //Wait for ten times the recommended value of 5ms.
//TELL USER TO CYCLE POWER
//Since Sleep mode is not available for the 5V supply version
Serial.println();
Serial.println();
Serial.println("You must now cycle power to the sensor/board");
Serial.println("Since Sleep mode is not available for the 5V supply version");
//Stop I2C
//i2c_stop();
//STOP SERIAL
Serial.flush();
Serial.end();
}//RETURNS BACK TO ORIGINAL FUNCTION!
byte crc8(byte *addr, byte len)
//The PEC calculation includes all bits except the START, REPEATED START, STOP, ACK, and NACK bits. The PEC is a CRC-8 with polynomial X8+X2+X1+1.
{
byte crc = 0;
while (len--) {
byte inbyte = *addr++;
for (byte i = 8; i; i--)
{
byte carry = (crc ^ inbyte) & 0x80;
crc <<= 1;
if (carry)
crc ^= 0x7;
inbyte <<= 1;
}
}
return crc;
} // end of crc8