Go Down

Topic: I2C Repeated Start (Read 11014 times) previous topic - next topic

cdan

Hello,
I use this code to read the temperature from the MLX90614 IR sensor (see attachment).
The sensore has address 0x5A and I read 3 bytes from internal address 0x07.
As you can see in the captured signal, the controller sends 2 ACK and one NACK just before the STOP condition.

I suppose there is something wrong in your code, can you send it to me to have a look? Or share it somewhere on the internet.

Best regards,
Dan.

Great Dan!

I'll check it out on Monday.

#17
Feb 04, 2013, 10:44 pm Last Edit: Feb 04, 2013, 10:47 pm by chriskner Reason: 1
Dan,

You got it.  Coding error.  It looks like I had two instances of twi going on...

Everything is working fine now.

Many thanks!

Code: [Select]

    //start read, then get n-1 responses
    TWI_StartRead(pTwi, i2c_addr, i2c_register+i, 1);
   if (!Embiic_WaitByteSent()) {//A NACK indicates a bad address, or broken com.  Exit.
     Error_Code = 100;
     TWI_SendSTOPCondition(pTwi);
     break;
   }
   for(i = 0; i < numOfBytes-1; i++) {
     if (Embiic_WaitByteReceived()){
       params[i] = TWI_ReadByte(pTwi);
     } else {
       params[i] = 0;
       Error_Code = 101;
       TWI_SendSTOPCondition(pTwi);
       break;
     }
   }
   if (Error_Code > 0) {  //in case error from for loop above
     break;
   }

    //now send stop before last receive request
   TWI_SendSTOPCondition(pTwi);
   if (Embiic_WaitByteReceived()){
     params[i] = TWI_ReadByte(pTwi);
   } else {
     params[i] = 0;
     Error_Code = 101;
     TWI_SendSTOPCondition(pTwi);
     break;
   }


-Chris

ducje

Hi Dan and Chris,

Do you mind sharing the code for the use of a MLX90614? I'm also trying to get one running on a Due, but unfortunatelly I'm really not into (machine)code. What I've seen in your posts is really to much for me.

regards,
Jelle

cdan

You can find the code attached to one of the posts above.
The name of the attachment is MLX90614_Direct_Access.ino

Feel free to use it in any way you like.

beautifulsmall

I2C now working on the Due, many thanks cdan , a few address changes and the MPU6050 who am I reg is answering to your MLX90614 code.

thomasmue

Can you please share your code for the MPU6050?

jcg11

Chris, can you share the function Embiic_WaitByteSent()?
I tested the method MLX90614_Direct_Access.ino on DUE + IR sensor TI TMP006.
Object temperature is not displayed correctly :(

Sure...  It's more than you asked for, but here are some checking routines:
(Embiic is the name of the project this code was used in)
Code: [Select]

uint32_t I2C_Get_Status_Register(){
  return pTwi->TWI_SR;
}

boolean Embiic_Check_NACK(uint32_t sr) {
  return ((sr & TWI_SR_NACK) & TWI_SR_NACK);
}

boolean Embiic_Check_TXCOMP(uint32_t sr) {
  return ((sr & TWI_SR_TXCOMP) == TWI_SR_TXCOMP);
}
Code: [Select]

boolean Embiic_Wait_ACK_TXCOMP() {
  unsigned long start, now;
  uint32_t sr, tw_nack, tw_txcomp;
 
  tw_txcomp = 0;
  start = micros();
 
  while (tw_txcomp == 0) {
    sr = I2C_Get_Status_Register();
    now = micros();
    if (now < start) {  // handle overflow, at at the expense of a longer timeout
      start = now;
      now++;
    } else {
      now = now - start;
    }
    if (now > I2C_ACK_TIMEOUTuS){
      DBG_PRINTLN("Embiic_CheckTXCOMP: Timeout.");
      I2C_Reset_Request = 1;
      return false;
    }
    tw_nack = Embiic_Check_NACK(sr);
    if (tw_nack != 0) {
      DBG_PRINTLN("Embiic_CheckTXCOMP: NACK. Natch.");
      return false;
    }
    tw_txcomp = Embiic_Check_TXCOMP(sr);
  }
  return true;
}
Code: [Select]

boolean Embiic_Wait_TXCOMP() {
  unsigned long start, now;
  uint32_t sr, tw_txcomp;
 
  tw_txcomp = 0;
  start = micros();
 
  while (tw_txcomp == 0) {
    sr = I2C_Get_Status_Register();
    now = micros();
    if (now < start) {  // handle overflow, at at the expense of a longer timeout
      start = now;
      now++;
    } else {
      now = now - start;
    }
    if (now > I2C_ACK_TIMEOUTuS){
      DBG_PRINTLN("Embiic_CheckTXCOMP: Timeout.");
      I2C_Reset_Request = 1;
      return false;
    }
    tw_txcomp = Embiic_Check_TXCOMP(sr);
  }
  return true;
}
Code: [Select]

boolean Embiic_WaitByteSent() {
  uint32_t sr;
  //bad: TXCOMP is 1, NACK is 1
  unsigned long start, now;
  start = micros();
  while (1) {
    now = micros();
    if (now < start) {  // handle overflow, at at the expense of a longer timeout
      start = now;
      now++;
    } else {
      now = now - start;
    }
    if (now > I2C_ACK_TIMEOUTuS){
      DBG_PRINTLN("Embiic_WaitByteSent: Timeout.");
      I2C_Reset_Request = 1;
      return false;
    }
    sr = I2C_Get_Status_Register();
    if ((sr & TWI_SR_NACK) & TWI_SR_NACK) {
      DBG_PRINTLN("Embiic_WaitByteSent: NACK. Bad Address?");
      return false;
    }
    if ((sr & TWI_SR_TXRDY) == TWI_SR_TXRDY) {
      return true;
    }
  }
  return true;
}
Code: [Select]

boolean Embiic_WaitByteReceived() {
  unsigned long start, now;
  start = millis();
  while (!TWI_ByteReceived(WIRE_INTERFACE)) {
    now = millis();
    if (now < start) {  // handle overflow, at at the expense of a longer timeout
      start = now;
      now++;
    } else {
      now = now - start;
    }
    if (now > I2C_READ_TIMEOUTmS){
      DBG_PRINTLN("Embiic_WaitByteReceived: Timeout.");
      I2C_Reset_Request = 1;
      return false;
    }
  }
  return true;
}


-Chris
I'm not a coder. I just play one on the internets.

jcg11

Thank you Chris!
Unfortunately, did not work :(
With MEGA R3 sensor indicates correct.
I will continue to investigate the cause...

F4LK0

Hy
I tried the sketch and it work fine.
I would tell if is possible change the SA address, for multi MLX90614
Somebody has some example? thanks

Go Up