Pages: 1 [2]   Go Down
Author Topic: I2C Repeated Start  (Read 9241 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
 

* MLX90614_Direct_Access.ino (3.41 KB - downloaded 123 times.)

* MLX90614_T_OBJ1_decoded.png (19.09 KB, 2211x490 - viewed 109 times.)
Logged

White River Junction, Vermont USA
Offline Offline
Full Member
***
Karma: 5
Posts: 106
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Great Dan!

I'll check it out on Monday.
Logged

White River Junction, Vermont USA
Offline Offline
Full Member
***
Karma: 5
Posts: 106
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
    //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


* cdan_theman.png (60.04 KB, 1211x352 - viewed 80 times.)
« Last Edit: February 04, 2013, 04:47:08 pm by chriskner » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

West Yorkshre UK
Offline Offline
Newbie
*
Karma: 0
Posts: 17
faster, smaller, more beautiful
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you please share your code for the MPU6050?
Logged

Russia
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-sad
Logged

White River Junction, Vermont USA
Offline Offline
Full Member
***
Karma: 5
Posts: 106
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
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:
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:
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:
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.
Logged

Russia
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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


* TI TMP006.png (33.55 KB, 467x378 - viewed 97 times.)
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Pages: 1 [2]   Go Up
Jump to: