SiliconLabs / arduino

Arduino Core for Silicon Labs devices
86 stars 16 forks source link

[bug] Read failure on i2C bus with Silicon Labs xG24 Explorer Kit Qwiic module #92

Closed lboue closed 1 month ago

lboue commented 1 month ago

Hardware

DS248X_ADDRESS 0x18

This Adafruit DS248x and all other Qwiic i2c modules are working fine with ESP32 modules. But not with xG24 boards.

Core version

2.1.0

Arduino IDE version

2.3.3

Operating system

Windows 11

Radio stack variant

Matter

OpenThread Border Router device (if using Matter)

N/A

Issue description

Detailed description of the issue

I flash this sketch and it i2c scan fails.

DS2484_DS18B20.ino

IMG_1849

Serial output

No response

RTT output (if using Matter)

Adafruit DS248x test sketch!
DS248x initialization failed.
Adafruit DS248x test sketch!
DS248x initialization failed.

Minimal reproducer code

#include "Adafruit_DS248x.h"

#define DS18B20_FAMILY_CODE 0x28
#define DS18B20_CMD_CONVERT_T 0x44
#define DS18B20_CMD_MATCH_ROM 0x55
#define DS18B20_CMD_READ_SCRATCHPAD 0xBE

Adafruit_DS248x ds248x;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);

  Serial.println("Adafruit DS248x test sketch!");
  if (!ds248x.begin(&Wire, DS248X_ADDRESS)) {
    Serial.println(F("DS248x initialization failed."));
    while (1);
  }

  Serial.println("DS248x OK!");

  // Speed up I2C, as searching for ROMs, specifically, is slow!
  Wire.setClock(400000);

  while (! ds248x.OneWireReset()) {
    Serial.println("Failed to do a 1W reset");
    if (ds248x.shortDetected()) {
      Serial.println("\tShort detected");
    }
    if (!ds248x.presencePulseDetected()) {
      Serial.println("\tNo presense pulse");
    }
    delay(1000);
  }
  Serial.println("One Wire bus reset OK");
}

void loop() {
  uint8_t rom[8];

  if (!ds248x.OneWireSearch(rom)) {
    Serial.println("No more devices found\n\n");
    return;
  }

  Serial.print("Found device ROM: ");
  for (int i = 0; i < 8; i++) {
    if (rom[i] < 16) {
      Serial.print("0");
    }
    Serial.print(rom[i], HEX);
    Serial.print(" ");
  }
  Serial.println();

  // Check if the device is a DS18B20 (Family code 0x28)
  if (rom[0] == DS18B20_FAMILY_CODE) {
      // Read and print temperature
      float temperature = readTemperature(rom);
      Serial.print("\tTemperature: ");
      Serial.print(temperature);
      Serial.println(" °C");
  }
}

float readTemperature(uint8_t *rom) {
    // Select the DS18B20 device
    ds248x.OneWireReset();
    ds248x.OneWireWriteByte(DS18B20_CMD_MATCH_ROM); // Match ROM command
    for (int i = 0; i < 8; i++) {
        ds248x.OneWireWriteByte(rom[i]);
    }

    // Start temperature conversion
    ds248x.OneWireWriteByte(DS18B20_CMD_CONVERT_T); // Convert T command
    delay(750); // Wait for conversion (750ms for maximum precision)

    // Read scratchpad
    ds248x.OneWireReset();
    ds248x.OneWireWriteByte(DS18B20_CMD_MATCH_ROM); // Match ROM command
    for (int i = 0; i < 8; i++) {
        ds248x.OneWireWriteByte(rom[i]);
    }
    ds248x.OneWireWriteByte(DS18B20_CMD_READ_SCRATCHPAD); // Read Scratchpad command

    uint8_t data[9];
    for (int i = 0; i < 9; i++) {
        ds248x.OneWireReadByte(&data[i]);
    }

    // Calculate temperature
    int16_t raw = (data[1] << 8) | data[0];
    float celsius = (float)raw / 16.0;

    return celsius;
}
leonardocavagnis commented 1 month ago

Hi @lboue Please test this minimal sketch to verify I2C connectivity and report the results.

#include "Wire.h"

#define DS248X_ADDRESS 0x18

uint8_t address = DS248X_ADDRESS;

void setup() {
    Wire.begin();

    Serial.begin(115200);
    while (!Serial) {}

    Serial.println("Test I2C communication");
}

void loop() {
    uint8_t error;
    Wire.beginTransmission(address);
    Wire.write(0); //dummy write
    error = Wire.endTransmission();

    if (error == 0) {
        Serial.println("I2C device found");
    } else {
        Serial.println("I2C device NOT found");
    }

    delay(2000); // Wait 2 sec before the next check
}
lboue commented 1 month ago

@leonardocavagnis It doen't work with your minimal sketch Qwiic port

I2C device NOT found
Test I2C communication
20
19
I2C device NOT found
I2C device NOT found
I2C device NOT found
I2C device NOT found

Regular i2C port Test I2C communication 9 10 I2C device NOT found I2C device NOT found

FlexWire But it works fine with this file and FlexWire librairy:

#include <Arduino.h>
#include <FlexWire.h>
FlexWire Wire_test = FlexWire(SDA, SCL, false);

void setup() {
  Wire_test.begin(); // Initialize the I2C bus as a master
  Serial.begin(115200); // Initialize the serial communication at 115200 baud rate
  Serial.println("\nI2C Device Scanner"); // Print a header message
}

void loop() {
  byte error, address; // Variables to hold error status and I2C address
  int nDevices; // Variable to count the number of I2C devices found

  Serial.println("Scanning..."); // Print a message indicating the start of the scan
  nDevices = 0; // Reset device count

  // Loop through all possible I2C addresses (1 to 126)
  for(address = 1; address < 127; address++ ) {
    Wire_test.beginTransmission(address); // Start I2C transmission to the current address
    error = Wire_test.endTransmission(); // End the transmission and capture the error code

    if (error == 0) { // If no error occurred
      Serial.print("I2C device found at address 0x"); // Print the device found message
      if (address < 16) {
        Serial.print("0"); // Print a leading zero for addresses less than 0x10
      }
      Serial.println(address, HEX); // Print the address in hexadecimal format
      nDevices++; // Increment the device count
    }
    else if (error == 4) { // If an unknown error occurred
      Serial.print("Unknown error at address 0x"); // Print the error message
      if (address < 16) {
        Serial.print("0"); // Print a leading zero for addresses less than 0x10
      }
      Serial.println(address, HEX); // Print the address in hexadecimal format
    }
  }

  if (nDevices == 0) { // If no devices were found
    Serial.println("No I2C devices found\n"); // Print a message indicating no devices found
  }
  else { // If devices were found
    Serial.println("Scanning Completed\n"); // Print a message indicating the scan is done
  }

  delay(5000); // Wait 5 seconds before the next scan
}
Scanning...
I2C device found at address 0x18
Scanning Completed

image

leonardocavagnis commented 1 month ago

Sorry, if you're using QWIIC connector: the interface is Wire1

Try the minimal test sketch with Wire1 and share the results:

#include "Wire.h"

#define DS248X_ADDRESS 0x18

uint8_t address = DS248X_ADDRESS;

void setup() {
    Wire1.begin();

    Serial.begin(115200);
    while (!Serial) {}

    Serial.println("Test I2C communication");
}

void loop() {
    uint8_t error;
    Wire1.beginTransmission(address);
    Wire1.write(0); //dummy write
    error = Wire1.endTransmission();

    if (error == 0) {
        Serial.println("I2C device found");
    } else {
        Serial.println("I2C device NOT found");
    }

    delay(2000); // Wait 2 sec before the next check
}
lboue commented 1 month ago

Sorry, if you're using QWIIC connector: the interface is Wire1

Try the minimal test sketch with Wire1 and share the results:

Here is the result. So it doesn't work:

Test I2C communication
I2C device NOT found
I2C device NOT found
I2C device NOT found
I2C device NOT found
I2C device NOT found

But it works well with FlexWire:

Scanning...
I2C device found at address 0x18
Scanning Completed
#include <Arduino.h>
#include <FlexWire.h>
//FlexWire Wire_test = FlexWire(SDA, SCL, false);
FlexWire Wire_test = FlexWire(SDA1, SCL1, false);

void setup() {
  Wire_test.begin(); // Initialize the I2C bus as a master
  Serial.begin(115200); // Initialize the serial communication at 115200 baud rate
  Serial.println("\nI2C Device Scanner"); // Print a header message
}

void loop() {
  byte error, address; // Variables to hold error status and I2C address
  int nDevices; // Variable to count the number of I2C devices found

  Serial.println("Scanning..."); // Print a message indicating the start of the scan
  nDevices = 0; // Reset device count

  // Loop through all possible I2C addresses (1 to 126)
  for(address = 1; address < 127; address++ ) {
    Wire_test.beginTransmission(address); // Start I2C transmission to the current address
    error = Wire_test.endTransmission(); // End the transmission and capture the error code

    if (error == 0) { // If no error occurred
      Serial.print("I2C device found at address 0x"); // Print the device found message
      if (address < 16) {
        Serial.print("0"); // Print a leading zero for addresses less than 0x10
      }
      Serial.println(address, HEX); // Print the address in hexadecimal format
      nDevices++; // Increment the device count
    }
    else if (error == 4) { // If an unknown error occurred
      Serial.print("Unknown error at address 0x"); // Print the error message
      if (address < 16) {
        Serial.print("0"); // Print a leading zero for addresses less than 0x10
      }
      Serial.println(address, HEX); // Print the address in hexadecimal format
    }
  }

  if (nDevices == 0) { // If no devices were found
    Serial.println("No I2C devices found\n"); // Print a message indicating no devices found
  }
  else { // If devices were found
    Serial.println("Scanning Completed\n"); // Print a message indicating the scan is done
  }

  delay(5000); // Wait 5 seconds before the next scan
}
lboue commented 1 month ago

It also works with the CircuitPython framework:

Adafruit CircuitPython 9.1.4 on 2024-09-17; SiLabs xG24 Explorer Kit with EFR32MG24B210F1536IM48
Board ID:explorerkit_xg24_brd2703a
UID:048727FFFEE9A93500000000

code.py output:
Found device ROM: 28 F7 B2 FA 05 00 00 7A 
Temperature: 23.38 °C
Temperature: 23.38 °C
Temperature: 23.38 °C
Temperature: 23.44 °C

So there really is a i2c issue with the code from this repo.

leonardocavagnis commented 1 month ago
#include <Arduino.h>
#include <FlexWire.h>
//FlexWire Wire_test = FlexWire(SDA, SCL, false);
FlexWire Wire_test = FlexWire(SDA1, SCL1, false);

Just to clarify: Does FlexWire work with SDA, SCL or with SDA1, SCL1? The sensor is connected to the QWIIC connector, right?

lboue commented 1 month ago

Just to clarify: Does FlexWire work with SDA, SCL or with SDA1, SCL1? The sensor is connected to the QWIIC connector, right?

I manually indicated the GPIOs and tested the 2 cases (QWIIC connector and regular header). Both cases work works with CircuitPython.

leonardocavagnis commented 1 month ago

Ok, thanks for detailed report!

lboue commented 1 month ago

Ok, thanks for detailed report!

Same issue with the SparkFun Thing Plus Matter MGM240P board.

leonardocavagnis commented 1 month ago

I tested the Wire.h library with this setup: Silicon Labs xG24 Explorer DHT10 Sensor and everything worked fine. Do you have a different I2C Sensor to test the communication?

Test with this sketch connecting the sensor to Wire (Pin: SCL, SDA of Silicon Labs xG24 Explorer board):

#include "Wire.h"
#define Wire_test Wire

void setup() {
  Wire_test.begin(); // Initialize the I2C bus as a master
  Serial.begin(115200); // Initialize the serial communication at 115200 baud rate
  Serial.println("\nI2C Device Scanner"); // Print a header message
}

void loop() {
  byte error, address; // Variables to hold error status and I2C address
  int nDevices; // Variable to count the number of I2C devices found

  Serial.println("Scanning..."); // Print a message indicating the start of the scan
  nDevices = 0; // Reset device count

  // Loop through all possible I2C addresses (1 to 126)
  for(address = 1; address < 127; address++ ) {
    Wire_test.beginTransmission(address); // Start I2C transmission to the current address
    Wire_test.write(0); //dummy write
    error = Wire_test.endTransmission(); // End the transmission and capture the error code

    if (error == 0) { // If no error occurred
      Serial.print("I2C device found at address 0x"); // Print the device found message
      if (address < 16) {
        Serial.print("0"); // Print a leading zero for addresses less than 0x10
      }
      Serial.println(address, HEX); // Print the address in hexadecimal format
      nDevices++; // Increment the device count
    }
    else if (error == 4) { // If an unknown error occurred
      Serial.print("Unknown error at address 0x"); // Print the error message
      if (address < 16) {
        Serial.print("0"); // Print a leading zero for addresses less than 0x10
      }
      Serial.println(address, HEX); // Print the address in hexadecimal format
    }
  }

  if (nDevices == 0) { // If no devices were found
    Serial.println("No I2C devices found\n"); // Print a message indicating no devices found
  }
  else { // If devices were found
    Serial.println("Scanning Completed\n"); // Print a message indicating the scan is done
  }

  delay(5000); // Wait 5 seconds before the next scan
}

Serial output should be:

Scanning...
Unknown error at address 0x01
...
Unknown error at address 0x17
I2C device found at address 0x18
...
Unknown error at address 0x7E
Scanning Completed
lboue commented 1 month ago

I tested the Wire.h library with this setup: Silicon Labs xG24 Explorer DHT10 Sensor and everything worked fine. Do you have a different I2C Sensor to test the communication?

I am facing the same issue with BME280.

leonardocavagnis commented 1 month ago

I am facine the same issue with BME280.

Please, show me your connections. Share a picture of the setup.

lboue commented 1 month ago

2 modules connected to Wire

Scanning...
Unknown error at address 0x01
Unknown error at address 0x02
Unknown error at address 0x03
Unknown error at address 0x04
Unknown error at address 0x05
Unknown error at address 0x06
Unknown error at address 0x07
Unknown error at address 0x08
Unknown error at address 0x09
Unknown error at address 0x0A
...
Unknown error at address 0x44
Unknown error at address 0x45
Unknown error at address 0x46
Unknown error at address 0x47
I2C device found at address 0x48
Unknown error at address 0x49
Unknown error at address 0x4A
Unknown error at address 0x4B
Unknown error at address 0x4C
Unknown error at address 0x4D
Unknown error at address 0x4E
Unknown error at address 0x4F
Unknown error at address 0x50
...
Unknown error at address 0x70
Unknown error at address 0x71
Unknown error at address 0x72
Unknown error at address 0x73
Unknown error at address 0x74
Unknown error at address 0x75
I2C device found at address 0x76
Unknown error at address 0x77
Unknown error at address 0x78
Unknown error at address 0x79
Unknown error at address 0x7A
Unknown error at address 0x7B
Unknown error at address 0x7C
Unknown error at address 0x7D
Unknown error at address 0x7E
Scanning Completed

image

2 modules connected to Wire

Scanning...
Unknown error at address 0x01
Unknown error at address 0x02
Unknown error at address 0x03
Unknown error at address 0x04
Unknown error at address 0x05
...
Unknown error at address 0x40
Unknown error at address 0x41
Unknown error at address 0x42
Unknown error at address 0x43
Unknown error at address 0x44
Unknown error at address 0x45
Unknown error at address 0x46
Unknown error at address 0x47
I2C device found at address 0x48
Unknown error at address 0x49
Unknown error at address 0x4A
Unknown error at address 0x4B
I2C device found at address 0x4C
Unknown error at address 0x4D
Unknown error at address 0x4E
Unknown error at address 0x4F
Unknown error at address 0x50
...
Scanning Completed

image

leonardocavagnis commented 1 month ago

2 modules connected to Wire

It seems work fine

lboue commented 1 month ago

I will contact Adafruid and see what we can do for this module.