Skip to main content
Mant Sandy
Associate II
August 3, 2017
Question

I2c cannot read from sensor

  • August 3, 2017
  • 2 replies
  • 4247 views
Posted on August 03, 2017 at 06:49

I am using mlx90614 sensor attached to my nucleo F091RC.

I have a working code with mbed :

double mlx90614::read_temp(uint8_t reg)

{

char cmd[2];

cmd[0] = 0x01;

cmd[1] = 0x00;

// Send start bit

__i2c->write(__addr, cmd, 2);

cmd[0] = reg;

// Write the RAM slave address (register) to read from..

//true argument means a repeated start..

__i2c->write(__addr, cmd, 1, true);

// Now read the response..

__i2c->read( __addr, cmd, 2);

// Reading pec bit.. we just ignore it.. not useful..

int pec = __i2c->read(true);

float temp = (cmd[0] | (cmd[1] << 8));

temp *= 0.02;

temp -= 15;

return temp;

}

But due to some issues with mbed-os, I would like to shift to STM cube HAL API's

Following exactly what I did in mbed, I wrote following function

------------------------

static int read_temp()

{

unsigned char cmd[2];

cmd[0] = 0;

cmd[1] = 1;

HAL_I2C_Master_Transmit(&hi2c2, 0x5A << 1, cmd, 2, 100);

cmd[0] = 0x07;

HAL_I2C_Master_Transmit(&hi2c2, 0x5A << 1, cmd, 1, 100);

HAL_I2C_Master_Receive(&hi2c2, 0x5A << 1, cmd, 2, 100);

float temp = (cmd[0] | (cmd[1] << 8));

temp *= 0.02;

temp -= 15;

return temp;

}

------------------------

I am getting a constant value 0xfff for cmd[0] and cmd[1];

I realized it is due to fact that HAL_I2C_Master_Transmit/Receive API's do not support repeat start.

From the data sheet, follow is the algorithm

https://cloud.githubusercontent.com/assets/5645667/26305867/06c1de46-3f2c-11e7-9dad-d3fda7dce60a.png

Therefore in order to support repeat start, I see that I can use HAL_I2C_Master_Transmit/Receive_IT() API's

I wrote the following code..

------------------------

static int read_temp_IT()

{

unsigned char cmd[2];

cmd[0] = 0;

cmd[1] = 1;

HAL_I2C_Master_Transmit(&hi2c2, 0x5A << 1, cmd, 2, 100);

cmd[0] = 0x07;

HAL_I2C_Master_Transmit_IT(&hi2c2, 0x5A << 1, cmd, 1);

while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY); HAL_I2C_Master_Receive_IT(&hi2c2, 0x5A << 1, cmd, 2);

float temp = (cmd[0] | (cmd[1] << 8));

temp *= 0.02;

temp -= 15;

return temp;

}

------------------------

The while() loop for status check - while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY); - hangs indefinitely.

I took reference of following sample project : STM32Cube_FW_F0_V1.8.0/Projects/STM32F091RC-Nucleo/Examples/I2C/I2C_TwoBoards_AdvComIT/Src/main.c

Could some one point out how to get proper I2c values from mlx90614

https://community.st.com/people/FORTOUNAS.EVANGELOS

‌ I saw your post other day. Please share your thoughts. It will greatly help me.

Note: this post was migrated and contained many threaded conversations, some content may be missing.
    This topic has been closed for replies.

    2 replies

    Vangelis Fortounas
    Associate II
    August 3, 2017
    Posted on August 03, 2017 at 12:48

    Hello!!

    According to the ''From the data sheet, follow is the algorithm'' above figure,

    The code is like this.

    char cmd=0x07; // RAM access address 07 TOBJ 
    char readbuf[3]={0,0,0};// send start bit, send slave address, send write bit, send command
     
    HAL_I2C_Master_Sequential_Transmit_IT(&hi2c2, 0x5A << 1, &cmd, 1, I2C_FIRST_FRAME); 
    while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY); 
    //send rep start bit,send slave address, read three bytes with acks(dont care for now, about pec), and stop bit 
    HAL_I2C_Master_Sequential_Receive_IT(&hi2c2, 0x5A << 1, readbuf, 3, I2C_LAST_FRAME); 
    while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY);�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    This is from datasheet found

    http://cpre.kmutnb.ac.th/esl/learning/mlx90614_infrared_thermometer/MLX90614_Datasheet.pdf

    . 0690X00000603RNQAY.jpg 0690X00000607fVQAQ.png

    ________________________________________________________________________________________

    The first mbed code , especialy

    // Send start bit ...??

    __i2c->write(__addr, cmd, 2);

    I don't understand why to send 0x00, 0x01 bytes to device

    and after, do a repeated start to write the command by

    cmd[0] = reg;

    // Write the RAM slave address (register) to read from.. //true argument means a repeated start.. __i2c->write(__addr, cmd, 1, true);

    So I couldn't made any code for this.

    Mant Sandy
    Associate II
    August 4, 2017
    Posted on August 04, 2017 at 10:37

    Thank you for your quick reply.

    Before posting this question, I tried using

    HAL_I2C_Master_Sequential_Transmit_IT

    () api.. but 1. The following line blocks indefinitely

    while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY);

    2. The examples provided by ST for nucleo F091RC are not using

    HAL_I2C_Master_Sequential_Transmit_IT

    () API. But for other F0* mcu's they are using this API. Therefore, I was thinking these API's are not supported and tried out HAL_I2C_Master_Transmit_IT() API. The result is same. The while loop to check the I2c state hangs indefinitely. Any idea why is this happenning?

    I am assuming internally, this API sends the data to I2c in the following form (start bit - slave address - writebit - command)

    HAL_I2C_Master_Sequential_Transmit_IT(&hi2c2, 0x5A << 1, &cmd, 1, I2C_FIRST_FRAME);

    Is my understanding correct?

    Vangelis Fortounas
    Associate II
    August 4, 2017
    Posted on August 04, 2017 at 11:36

    Hello.

    'I am assuming internally, this API sends the data to I2c in the following form (start bit - slave address - writebit - command)' Yes it is true but it not sends a stop bit.

    HAL_I2C_Master_Transmit_IT(), sends a stop bit after transaction. this is the difference.

    Read the the coments the file stm32f0xx_hal_i2c.c You will find all the info about theese fuctions Check the pullup resistors check the voltage of sensor, is 3.3v? Is your device's address the default 0x5A ? Is your code correct initialised with I2C interrupts enabled? When this function stucks:

    while(HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY);
    try to put a breakpoint at I2Cx_IRQHandler, to find the cause of error.
    

    LMI2
    Senior III
    August 9, 2017
    Posted on August 09, 2017 at 17:20

    There is also the Melex (the sensor manufacturer)support address somewhere in their website. They seem to be quite competent in handling this kind of problems, probably because of that SMBbus.

    There are also working MLX90614 libraries for Arduino devices.

    Mant Sandy
    Associate II
    August 10, 2017
    Posted on August 10, 2017 at 13:58

    Thanks mich. With a quick look i could not find the contact. But will search for it thoroughly if I am unable to resolve this issue..

    LMI2
    Senior III
    August 10, 2017
    Posted on August 10, 2017 at 17:30

    yeah. I remember it was hard to find.

    Edit: Or not.

    https://www.melexis.com/en/contact