I asked this before but I did it in the wrong place (as a comment to an older thread).
Anyway... I'm trying to use a MLX90614 BCI with an Arduino Leonardo. I was able to use it, get measurements, etc. and life was good. But not great.
So I decided to change some of the registers as recommended at http://www.cheap-thermocam.tk/ , using the "configuration sketch" in that page. BIG mistake. That sketch was written for an Arduino Uno (and let's be honest, it's not the finest piece of code), and by the time you can connect to the Leonardo's serial port the information you are supposed to keep is already gone for good. AND... the code produced an error.
It looks like my sensor was flaky to begin with, and the code at that page didn't help much. Now my MLX is completely out of whack, and Melexis won't offer any support (among other things, because "Arduino is not an approved component" :0 ).
I wonder if someone around here may help me reading the EEPROM from his/her MLX and sending the values to me. There are 32 positions, and although you are not supposed to mess with more than two or three, having the whole thing may help me identify what part of the EEPROM is bad.
I wrote a sketch that dumps EEPROM, RAM, Flags, etc., but I'm not that familiar with the Arduino and I won't feel comfortable asking you to run it on your devices, but if you can dump (or already did dump) your eeprom and send me the default values I would be very grateful. The code is here anyway...
// Configuration sketch for the MLX90614
// put together by jay_ar. Based on the
// "Configuration Sketch - Version 1.03"
// from www.cheap-thermocam.tk and some other
// examples
#include <i2cmaster.h>
extern volatile unsigned long timer0_millis;
int ledPin = 13; // Onboard led
boolean ledOn = true;
unsigned long oldTime;
void setup() {
pinMode(ledPin, HIGH); // Output
Serial.begin(9600);
i2c_init();
digitalWrite(ledPin, HIGH); // sets the LED on
oldTime=timer0_millis; // "now"
}
//To Do: disable overwriting by default
void loop(){
if (Serial.available() > 0) {
switch (Serial.read()) {
case '1': readEEP(); break;
case '2': readRAM(); break;
case '3': measureTemp(); break;
case '4': readStats(); break;
/* uncomment only if you know what you are doing!
case '8': changeTmax(); break;
case '9': changeTmin(); break;
case '0': changeCtrl(); break;
*/
}
}
if ((timer0_millis - oldTime)>1000){
ledOn = !ledOn;
digitalWrite(ledPin,ledOn);
oldTime = timer0_millis;
// led blinking = still alive!
}
}
void readEEP(){
Serial.println("EEPROM data");
char S[32];
for (int i = 0; i <= (0x1F); i++) {
unsigned int value = readAddress(0x00,0x20+i);
sprintf (S,"%02X:\t%04X",i,value);
Serial.println(S);
}
}
void readRAM(){
Serial.println("RAM data");
char S[32];
for (int i = 0; i <= (0x1F); i++) {
unsigned int value = readAddress(0x00,i);
sprintf (S,"%02X:\t%04X",i,value);
Serial.println(S);
}
}
void measureTemp(){
unsigned int data_l = 0;
unsigned int data_h = 0;
int pec = 0;
i2c_start_wait(0x00+I2C_WRITE);
i2c_write(0x07);
i2c_rep_start(0x00+I2C_READ);
data_l = i2c_readAck(); //Read 1 byte and then send ack
data_h = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();
double tempFactor = 0.02;
double temp = 0x0000;
temp = (double)(((data_h & 0x007F) << 8) + data_l);
temp = (temp * tempFactor)-0.01-273.15;
char S[32];
long int temp_i=round(100*temp);
sprintf(S,"Temp: %s%li.%02li",(temp_i < 0 ? "-" : ""), abs(temp_i / 100), abs(temp_i % 100));
Serial.println(S);
}
void readStats(){
unsigned int data_l = 0;
i2c_start_wait(0x00+I2C_WRITE);
i2c_write(0xF0);
data_l = i2c_readAck(); //Read 1 byte and then send ack
i2c_stop();
char S[32];
sprintf(S,"Flags: 0x%02X",data_l);
Serial.println(S);
}
// This part of the code may brick your MLX!!!
// Use it (uncomment cases 8..0 above) at your own risk
// To do: keep non-relevant bits from 0x05
void changeTmax(){
Serial.println("Erasing max temp settings...");
writeAddress(0x00,0x20,0x00,0x00,0x43);
delay(100);
Serial.println("Writing new max temp settings...");
writeAddress(0x00,0x20,0x23,0xFF,0x21);
cycleMLX(0x00);
delay(1000);
char S[32];
unsigned int value = readAddress(0x00,0x20+0x00);
sprintf (S,"Read:\t%04X",value);
Serial.println(S);
}
void changeTmin(){
Serial.println("Erasing min temp settings...");
writeAddress(0x00,0x21,0x00,0x00,0x28); // <- Corrected
delay(100);
Serial.println("Writing new min temp settings...");
writeAddress(0x00,0x21,0x5B,0x4F,0x59);
cycleMLX(0x00);
delay(1000);
char S[32];
unsigned int value = readAddress(0x00,0x20+0x01);
sprintf (S,"Read:\t%04X",value);
Serial.println(S);
}
void changeCtrl(){
Serial.println("Erasing filter settings...");
writeAddress(0x00,0x25,0x00,0x00,0x83);
delay(100);
Serial.println("Writing new filter settings...");
writeAddress(0x00,0x25,0x74,0xB6,0x7E);
cycleMLX(0x00);
delay(1000);
char S[32];
unsigned int value = readAddress(0x00,0x20+0x05);
sprintf (S,"Read:\t%04X",value);
Serial.println(S);
}
unsigned int readAddress (int dev, int address){
unsigned int data_l = 0;
unsigned int data_h = 0;
int pec = 0;
unsigned int data_t = 0;
i2c_start_wait(dev+I2C_WRITE);
i2c_write(address);
i2c_rep_start(dev+I2C_READ);
data_l = i2c_readAck();
data_h = i2c_readAck();
pec = i2c_readNak();
i2c_stop();
data_t = (((data_h) << 8) + data_l);
return data_t;
}
void writeAddress (int dev, int address, int LB, int HB, int pec){
i2c_start_wait(dev+I2C_WRITE);
i2c_write(address); // Should have 0x20 added beforehand!
i2c_write(LB); // LSB
i2c_write(HB); // MSB
i2c_write(pec); // Checksum
i2c_stop();
delay(5);
}
void cycleMLX(int dev){
i2c_start_wait(dev+I2C_WRITE);
i2c_write(0xFF); // Sleep command
i2c_write(0xF3); // <- Checksum, corrected
i2c_stop();
delay(5);
}
[EDIT 12-24] Corrected two bad CRCs