I2C error issue

'm working on an I2C communication setup between a Raspberry Pi Wiznet W5500 as the master and an Arduino Nano RP2040 Connect as the slave. I'm using the Arduino IDE, with the following setup:

TwoWire Wire0(i2c1, 6, 27);  // Custom I2C pins: SCL on pin 6, SDA on pin 27

// Master code snippet
void sendData() {
    Wire0.beginTransmission(8);
    Wire0.write(nano_mode); // "W" or "B" command
    int error = Wire0.endTransmission();

    if (error == 0) {
        Serial.println("Transmission successful");
    } else {
        Serial.print("Transmission error: ");
        Serial.println(error);
        digitalWrite(28, HIGH);  // Red LED indication on error
    }
}
// Slave code snippets
void receiveEvent(int howMany) {
    command = Wire.read();
}

void requestEvent() {
    while (output.length() < 30) {
        output += "*";  // Padding to reach 30 bytes
    }
    Wire.write(output.c_str(), 30);
    output = "";
}

The issue I'm experiencing is that the I2C communication works perfectly for several transmissions at the beginning. However, after some time, I consistently get transmission error 5 on the master side, which indicates an I2C timeout or bus error. When this error starts occurring, it never goes away, and a red LED on the Nano RP2040 Connect starts blinking. I've tried several troubleshooting steps, including adding delays, resetting the I2C bus using Wire.end() and Wire.begin() .
I would greatly appreciate any advice or guidance on what might be causing the bus to get stuck and how to resolve the persistent error state.

Use an ordinary C string (char output[31]) instead of String type.

1 Like

thank you, i m testing it right now, it works so far.

Sadly it s the same, after few execution the problem rise again .

Please show your code.

this is the Master side of the code, i just toggle the value of a variable "nano_mode" that either has "W" or "B".

TwoWire Wire0(i2c1, 6, 27);  // Custom I2C pins: SCL on pin 6, SDA on pin 27

// Master code snippet
void sendData() {
    Wire0.beginTransmission(8);
    Wire0.write(nano_mode); // "W" or "B" command
    int error = Wire0.endTransmission();

    if (error == 0) {
        Serial.println("Transmission successful");
    } else {
        Serial.print("Transmission error: ");
        Serial.println(error);
        digitalWrite(28, HIGH);  // Red LED indication on error
    }
}


void requestData_from_salve() {

 Wire0.requestFrom(8,20);
                  String taille_msg = ""; // Initialize a string to store the message
                   char d;
                   while(Wire0.available()) {
                    d=Wire0.read();
                    taille_msg += d; // Append the character to the received message
                   }
                   message+=taille_msg;

}

and this is the slave code :


#define PASSWORD_WIFI1                                    "HERBS_AP"  //minimum 8 caractéres  (limitation librairie)
#define SSID_WIFI1                                        "HERBS_AP"  // minimum 8 caractéres (limitation librairie)

#define PASSWORD_WIFI2                                    "dqp0mku7kt"  //minimum 8 caractéres  (limitation librairie)
#define SSID_WIFI2                                        "Linksys02978"  // minimum 8 caractéres (limitation librairie)

#define ID_GATEWAY                                 1
                  

int herbsrssi;
int Linkyrssi;
char output[21];
long timeout_duration = 1000;  // 1 seconds timeout
char command = '\0';
unsigned long debut_mesures;
bool mesure_done = false;

void setup() {
  Wire.begin(8);                // Join I2C bus with address #8
  Wire.onReceive(receiveEvent); // Register receive event
  Wire.onRequest(requestEvent); // Register request event
  Serial.begin(9600);           // Start serial communication at 9600 baud
  pinMode(LEDR, OUTPUT);
  pinMode(LEDG, OUTPUT);
  pinMode(LEDB, OUTPUT);
activateBLE();
}

void loop() {
  if (command == 'W') {
    listNetworks();
    command='\0';
    Serial.println("this is the output of WIFI");
    Serial.println(output);
  } else if(command == 'B') {
    activateBLE();
    strcpy(output, "/,/,");
   Serial.println(" i m scanning now for the BLE i m seeking");
    BLE.scanForName("Arduino Nano RP2040", true);
    debut_mesures=millis();
    while (!mesure_done &&  ((millis() - debut_mesures) < timeout_duration)) {
    BLEDevice device = BLE.available();
              if (device) {
                char rssiStr[8];
                snprintf(rssiStr, sizeof(rssiStr), "%d,", device.rssi());
                strcat(output, rssiStr);
                  mesure_done = true;
              } else {
                  //Serial.println("waiting for measurement of BLE");
              }
      }
      if (!mesure_done) {
          strcat(output, "KO,");
      } 
       char timeStr[5];
    snprintf(timeStr, sizeof(timeStr), "%lu", millis() - debut_mesures);
    strcat(output, timeStr);
    command='\0';
    mesure_done=false;
   //  Serial.println("this is the output of BLE");
    //Serial.println(output);
  }
}

void receiveEvent(int howMany) {
   if (howMany > 0) {
    command = Wire.read();
  }
}

void requestEvent() {
   Serial.println("this is before checking ");
   Serial.println(output);
    while (strlen(output) < 20) {
      strcat(output, "*");
    }
    Wire.write(output,20);
    Serial.println("this is after checking");
    Serial.println(output);
  output[0] = '\0';
}

void listNetworks() {
  BLE.end();
  delay(100);
  WiFi.end();
  delay(100);
  
  int herbsrssi = 0;
  int Linkyrssi = 0;
  debut_mesures=millis();
  Serial.println("i m gonna start measurement");
  int numSsid = WiFi.scanNetworks();

  if (numSsid == -1) {
    Serial.println("Couldn't get a WiFi connection");
    while (true);
  }

  // print the network number and name for each network found:
  for (int thisNet = 0; thisNet < numSsid; thisNet++) {
    if (strcmp(WiFi.SSID(thisNet), "Linksys02978") == 0) {
      Linkyrssi = WiFi.RSSI(thisNet);
    }
    if (strcmp(WiFi.SSID(thisNet), "HERBS_AP") == 0) {
      herbsrssi = WiFi.RSSI(thisNet);
    }
  }
  if (herbsrssi != 0) {
    char rssiStr[5];
    snprintf(rssiStr, sizeof(rssiStr), "%d,", herbsrssi);
    strcat(output, rssiStr);
  } else {
    strcat(output, "KO,");
  }
  if (Linkyrssi != 0) {
    char rssiStr[5];
    snprintf(rssiStr, sizeof(rssiStr), "%d,", Linkyrssi);
    strcat(output, rssiStr);
  } else {
     strcat(output, "KO,");
  }
 char timeStr[6];
  snprintf(timeStr, sizeof(timeStr), "/,%lu", millis() - debut_mesures);
  strcat(output, timeStr);
}


void activateBLE() {
  BLE.end();
  delay(100);
  WiFi.end();
  delay(100);

  if (!BLE.begin()) {
    Serial.println("Failed to initialize BLE!");
    while (1);
  }
  Serial.println("BLE Initialized.");
}

Please simplify that.
Don't do Serial output in the callback function.
Don't use String type. Preset the output buffer by the fill character. Track the output size and place the characters immediately into the char buffer instead of using strcat().

1 Like

thank you, i apologise for my late response, i was trying all kind of ideas i had, and what resolved the issue partially ( to some extent) was reseting the I2C before each operation (doing Wire.end() then Wire.begin()), but i still can't pinpoint the issue.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.