1
\$\begingroup\$

I am using an MLX90632 (MLX90632-S-LD-BCB-000) infrared temperature sensor to build an application which reads an object's temperature among other things. MLX90632 manual

The MLX90632 comes with a default refresh rate of 2 Hz which is unacceptably low for my application. Supposedly, the sensor has configurable refresh rate, which is configured by writing specific values at 2 specific memory addresses in its eeprom memory.

The datasheet says that the eeprom should be unlocked with a command, the specific memory positions should be erased by writing 0x0000 to them and then the eeprom should be unlocked again and write the actual values.

I had written the program below to do this task but it does not seem to work, when i read the sensor's refresh rate,after changing it, it has the default rate (eeprom contents not changed).

I have also seen Sparkfun's driver which has the same implementation as mine and they have put a comment there:

Requires unlocking the EEPROM, writing 0x0000, unlocking again, then writing value. The datasheet doesn't go a good job of explaining how writing to EEPROM works. This should work but doesn't. It seems the IC is very sensitive to I2C traffic while the sensor is recording the new EEPROM.

For this reason instead of polling the sensor to check its eeprom_busy bit i just put a delay, long enough for the memory operation to finish before trying anything else. Still does not work.

I wonder if anyone has managed to write new values to this sensor's eeprom memory and how they managed it. Is there anything wrong with the logic in my implementation?

Note: The program sends what it is supposed to send via i2c to the sensor - this has been checked with a logic analyzer - I am just looking for errors in the process

int main (void){

    // initialize mcu code etc...
    // ...
    // ...

    rate = mlx90632_get_refresh_rate();  //the rate we get here is 2Hz
    mlx90632_set_refresh_rate_1Hz  ();  //write the new refresh rate to sensor's eeprom


    // mlx90632_reset();   // a reset won't help here either

    rate = mlx90632_get_refresh_rate();  //after changing the rate, still gets 2 Hz refresh rate


}

/*-------------------------------------------------------------------------*/



// function to set the refresh rate to 1 Hz
int32_t mlx90632_set_refresh_rate_1Hz  ( void ){

    uint32_t meas;      

    meas = 0x810D811D;  //value supposed to be written to configure the 1Hz refresh rate

    // put to sleep mode before writing to eeprom
    mlx90632_mode_type previous_mode = mlx90632_get_mode();
    if (previous_mode == continuous_mode) 
                mlx90632_set_mode(sleep_step_mode);

    //EE_MEAS_1 and EE_MEAS_2 are two 16-bit registers, needed to be written for the configuration
    //  EE_MEAS_2 is right after EE_MEAS_1. We write the incrementally as one 32-bit register
    if ( mlx90632_write_eeprom32( EE_MEAS_1, meas ) < 0 )   
        return -1;


    // return to previous mode
    mlx90632_set_mode(previous_mode);

} 

/*-------------------------------------------------------------------------*/


int32_t mlx90632_write_eeprom32( uint16_t address, uint32_t value ){

    while( mlx90632_eeprom_busy() ){;}    //wait until sensor is free

    if ( mlx90632_unlock_eeprom() < 0 )     // unlock eeprom for writing
            return -1;

    // erase eeprom register before writing
    if ( mlx90632_write_reg32(address, 0x0000) < 0 ) return -1;     //write a 32 bit value to the eeprom starting from  "address"
        nrf_delay_ms(500);  
        //while( mlx90632_eeprom_busy() ){;}   

    if ( mlx90632_unlock_eeprom() < 0 )
            return -1;

    // actually write the desired value
    if ( mlx90632_write_reg32(address, value) < 0 ) return -1;
            nrf_delay_ms(500);
            //while( mlx90632_eeprom_busy() ){;}    // to do: add timeout?

    return 0;
}

/*-------------------------------------------------------------------------*/
\$\endgroup\$
1
\$\begingroup\$

It seems that there is nothing wrong with the procedure after all.

The problem seems to be that this sensor for some reason, has a high possibility of writing adjacent eeprom memory locations by mistake. Generally the behavior of the eeprom memory when trying to erase it or write it, is far from identical (reading is not problematic).

In this particular case when i tried to write memory location EE_MEAS_1 ( 0x24E1 ), memory location EE_MEAS_2 (0x24E2) was written too with the same value and vice versa. That led to wrong configuration because these two memory locations are not supposed to hold the same value, according to the datasheet.

The solution that seemed to work for me, was to erase/write something to the memory and then check if the correct values have been written. When checking the values, check all the values you want to overwrite, because one memory location may be written ok, but when you try to erase/write the next one, the former might get corrupted. So, check all the values you need to write at once (in my case the addresses 0x24E1 and 0x24E2). If the values are not correct, I reset the sensor with the appropriate command, wait for 100ms and repeat the same operation (erase/write) until the correct values are written. It usually takes two tries when i implement it with a do-while loop.

It's also good to try and write every memory location (16-bit wide) with a separate i2c command, instead of using incremental writing (as I did in the code i posted). Reading with an incremental i2c command, also does not work properly sometimes, it's best to read each address with a separate command.

I know it's not the optimal solution, but it works fairly well with no problems so far. I hope Melexis(the company that makes the sensor) will fix this issue, because from what I read others deal with the same issue too.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.