I2C Lost bus arbitration

Hi all,
I am trying to use Teensy 3.2 to transmit data to another device through I2C, and for some reason, then endTransmission() just keeps returning the error number 4: lost bus arbitration. The following is my code:

#include <Wire.h>

void setup() {
  Wire.begin();
  Wire.setClock(100000);
  Serial.begin(57600);  //enable Serial Monitor  
}

void loop(){
  Wire.beginTransmission(0x74);
  delay(1000);
  //Wire.requestFrom(0x74,1,1);
  int test1 = Wire.write(1);
  //Wire.requestFrom(0x74,1,1);
  int test2 = Wire.write(50);
  //Wire.requestFrom(0x74,1,1);
  uint8_t test3 = Wire.endTransmission(true);
  Serial.print(test1);
  Serial.print(test2);
  Serial.print(" ");
  Serial.print(test3);
  Serial.print('\n');
}

By running this code, I can get the output "11 4" from Serial Monitor, which means two Wire.write() function works properly, but Wire.endTransmission() function return the error: lost bus arbitration.

I probably know the reason that causes this issue. How the I2C of my slave device NCP81239 work is like:

Start->IC ADDRESS->0(write)->ACK->Register REG0Address ->ACK->REG value->ACK->...

Blue Color: From Teensy to NCP81239
Green Color: From NCP81239 to Teensy
This can be referenced from NCP81239 datasheet page 19.

I am assuming the issue is due to the slave assert an ACK during the writing, which might mess up the entire writing process, but I am not certain. Could anyone help me with this? I really need to figure this out ASAP!!

Thanks.

Can you please, reformat the program codes of your original post.

  1. Open your post in the Edit/Modify Mode.

  2. Bring the cursor at the very beginning of your code. Now, type this word: [ c o d e ]. Please, do not keep spaces among the letters while typing the word. Keep them together. I have to keep spaces due to some technical reasons.

  3. Bring the cursor at the very end of your code. Now, type this word: [ / c o d e ]. Please, do not keep spaces among the letters while typing the word. Keep them together. I have to keep spaces due to some technical reasons.

  4. Press the save button.

Now, your codes/post looks so beautiful!

I am putting below my opinion based on my experience with I2C Bus of UNO:

1. All information starting from Wire.beginTransmission(); and before Wire.endTransmission(); are queued in a buffer.

2. With the execution of the Wire.endTransmission(); all the queued information are transferred to the slave on hand-shaking basis.

3. Now, to become sure that the information has transferred correctly, there is a way of checking status which the Wire.endTransmission(); function generates. A value of 0x0000 for the status indicates successful transmission.

4. There are many ways of checking this status; however, I check this way: (you may try it). Note: This is for a healthy bus. If there is something wrong with the transmission, the bus will be locked, and you have to reset the system to come out. These codes have not included the time-out option. Alternative codes could be written giving 100 ms(say) time-out option using millis() function.

 void setup()
{
  
  do
  {
     Wire.beginTransmission(0x74);  //be sure that the slave address is correct!
     int test1 = Wire.write(1);
     int test2 = Wire.write(50);
  }
  while ((Wire.endTransmission()) != 0x00);

  Serial.print(test1);
  Serial.print(test2);
  Serial.print(" ");
  Serial.print(test3);
  Serial.print('\n');

}

void loop()
{

}

GolamMostafa:
I am putting below my opinion based on my experience with I2C Bus of UNO:

1. All information starting from Wire.beginTransmission(); and before Wire.endTransmission(); are queued in a buffer.

2. With the execution of the Wire.endTransmission(); all the queued information are transferred to the slave on hand-shaking basis.

3. Now, to become sure that the information has transferred correctly, there is a way of checking status which the Wire.endTransmission(); function generates. A value of 0x0000 for the status indicates successful transmission.

4. There are many ways of checking this status; however, I check this way: (you may try it). Note: This is for a healthy bus. If there is something wrong with the transmission, the bus will be locked, and you have to reset the system to come out. These codes have not included the time-out option. Alternative codes could be written giving 100 ms(say) time-out option using millis() function.

 void setup()

{
 
  do
  {
    Wire.beginTransmission(0x74);  //be sure that the slave address is correct!
    int test1 = Wire.write(1);
    int test2 = Wire.write(50);
  }
  while ((Wire.endTransmission()) != 0x00);

Serial.print(test1);
  Serial.print(test2);
  Serial.print(" ");
  Serial.print(test3);
  Serial.print('\n');

}

void loop()
{

}

Hi, Thanks for your response. Here I modify your testing code a little bit as follows:

#include <Wire.h>
void setup(){  
  int test1, test2;
  Wire.begin();
  Serial.begin(57600);  //enable Serial Monitor  
  do{
     Wire.beginTransmission(0x74);  //be sure that the slave address is correct!
     test1 = Wire.write(1);
     test2 = Wire.write(50);
  }while ((Wire.endTransmission()) != 0x00);
  Serial.print(test1);
  Serial.print(test2);
  Serial.print(" ");
  //Serial.print(test3);
  Serial.print('\n');
}

void loop(){

}

Then on Serial Monitor, it never shows up anything. I am assuming the endTransmission() could never give status 0x0000

So, your result and the result of my codes agree. Now, you have to proceed systematically to isolate the faulty hardware/software.

1. Disconnect all devices and wiring from your Arduino.
2. Make your Arduino I2C Bus working by checking an I2CLCD.
3. Connect your original slave with the Arduino and check if it is working.
4. If the system does not work, change your original slave?

GolamMostafa:
So, your result and the result of my codes agree. Now, you have to proceed systematically to isolate the faulty hardware/software.

1. Disconnect all devices and wiring from your Arduino.
2. Make your Arduino I2C Bus working by checking an I2CLCD.
3. Connect your original slave with the Arduino and check if it is working.
4. If the system does not work, change your original slave?

When I disconnect all wiring, the Wire.endTransmission() function will return the status 2 (address send, NACK received) instead of 4, which makes sense since it is not connected with the slave. However, when I tried to probe the SDA and SCLK on Oscilloscope, I see my Teensy actually transmit the slave address 0x74 (ob1110100) and a write (0). Oscilloscope can only read 0xE8 (which is 0b11101000). This meant the Wire.write() function does not send any data through I2C although this function returns 1. Now I just completely confused about the Wire.write() and Wire.endTransmission().