I2C Not Working on Xiao MG24 Sense - SDA Line Stuck LOW

Hardware Setup

  • Board: Seeed Studio Xiao MG24 Sense
  • Sensor: MPR121 Capacitive Touch Sensor (I2C Address 0x5A)
  • Connections:
    • MPR121 VDD → 3.3V
    • MPR121 GND → GND
    • MPR121 SDA → D4 (PC4)
    • MPR121 SCL → D5 (PC5)
    • 2.2kΩ pull-up resistors on both SDA and SCL lines

Issue Description

I’m trying to use the MPR121 capacitive touch sensor with the Xiao MG24 Sense, but I’m experiencing I2C communication issues. The SDA line appears to be stuck LOW when the sensor is connected. Here are the specific symptoms:

  1. When I scan the I2C bus, it shows that ALL addresses (0x01-0x7F) are responding - which typically indicates a bus problem.
  2. When I debug the MPR121 sensor initialization, all register reads return 0x00 values.
  3. When I disconnect the SDA line from the sensor, reads return 0xFF.

Code

Here’s my I2C initialization code:

void iic_init() {
  CMU_ClockEnable(cmuClock_GPIO, true);
  CMU_ClockEnable(cmuClock_I2C1, true);

  GPIO_PinModeSet(gpioPortC, 4, gpioModeWiredAnd, 1); // SDA
  GPIO_PinModeSet(gpioPortC, 5, gpioModeWiredAnd, 1); // SCL

  I2C_Reset(I2C1);

  I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT;
  i2cInit.master = true;
  i2cInit.freq = 100000; // 100kHz
  I2C_Init(I2C1, &i2cInit);

  Wire.begin();
}

Debug Output

When I enabled debug mode in Adafruit_I2CDevice library, I get this output for every register I try to read:

I2CWRITE @ 0x5A :: 0x5E,
I2CREAD  @ 0x5A :: 0x0,

The sensor is detected at address 0x5A, but all reads return 0x0:

Address 0x5A Detected
I2CWRITE @ 0x5A :: 0x5E,
I2CREAD  @ 0x5A :: 0x0,

Things I’ve Tried

  1. Changed pull-up resistor values from 10kΩ to 2.2kΩ
  2. Lowered I2C clock speed to 100kHz (from 400kHz)
  3. Added delays after initialization (up to 100ms)
  4. Tried bus recovery procedure (toggling SCL to unstuck potentially stuck devices)
  5. Double-checked all wiring connections
  6. Verified that MPR121 receives proper power (3.3V)
  7. Checked that SDA/SCL both measure 3.3V when nothing is transmitting

Observations

  • When SDA wire is disconnected from the sensor, the line reads HIGH (as expected)
  • When SDA is connected to the sensor, it’s being pulled LOW continuously
  • I can communicate with the device address (ACK received), but all data reads are 0x00

Any ideas what could be causing this issue with the I2C communication? Is the MPR121 possibly damaged? Or is there something specific about the Xiao MG24’s I2C implementation that I’m missing?

Thank you for your help!

Have you read this thread?

Yes, I read your thread and tried your approach, but it still didn’t work for me.

Does I2C_Scanner detect and respond on all addresses?
Is the Adafruit breakout board you are using? If so, have you tried the Adafruit library example?

Yes, the I2C scanner detects and responds on all addresses from 0x00 to 0x7F.

Uses board is https://ja.aliexpress.com/item/1005008747393305.html.

Yes, I tried the library examples. The same code works perfectly on my XIAO ESP32C3, but fails on the XIAO MG24 Sense.

I’m developing with PlatformIO, not the Arduino IDE.

;platformio.ini
[env]
platform = Seeed Studio
board = seeed-xiao-mg24-sense
framework = arduino
platform_packages = 
	framework-arduino-silabs@^2.3.0
	toolchain-gccarmnoneeabi@^1.140201.0

[env:xiao_mg24_sense]
monitor_speed = 115200
lib_deps = 
	adafruit/Adafruit MPR121@^1.1.3
	seeed-studio/Seeed Arduino LSM6DS3@^2.0.4

Have you tried @grobasoz’s two patches in two places in Wire.cpp?

Yes, I have tried.


Try the software I2C library.

I checked the waveforms.
It seems to work well for devices that only need to Write data, such as the SSD1306 display unit. However, when reading data from Slave, it does not seem to work well.

2 Likes

Yep - I’m looking into that :slight_smile:

1 Like

Thank you for sharing your observations!

I’ll try using a software I2C library as a workaround.
If that works, I’ll look into what’s causing the hardware I2C read issue and share any solutions I find.

Seems to be an unresolved bug.

1 Like

Perhaps try the Arduino IDE first (if possible)?
I’ll have a look into the Platformio option at some stage.

Thanks but the library sample code and I2CScan were done in ArduinoIDE but it didn’t work so I went back to PlatformIO.

OK - I’ll see if I can find out the issue with Platformio based code…

I don’t have the same I2C devices as you but I do have BME680 and can read the Chip Id from the device using PlatformIO based XIAO_MG24 device.
The BME680 device shows up in a scan as well… along with my own “slave” for another forum user.

Initializing I2C...
Scanning All...
No I2C device 70
No I2C device 71
No I2C device 72
No I2C device 73
I2C device found at 74
No I2C device 75
No I2C device 76
I2C device found at 77
No I2C device 78
No I2C device 79
No I2C device 7A
No I2C device 7B
No I2C device 7C
No I2C device 7D
I2C Master Starting...
Scanning...
My I2C device found

Data received from 74
ABCDEFGH
Done

Data received from 77
61
Done

I examined the waveforms.
When Scanner starts, SDA goes from HIGH to LOW and waits for SCL to go LOW, but SCL remains HIGH and does not change.
There seems to be a problem with Wire.begin() of I2C_Scanner.

What code are you referring to?

#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin();
  Serial.println("I2C Scanner");
}

void loop() {
  byte error, address;
  int nDevices;
  nDevices = 0;
 
  Serial.println("I2C1 Scanning..."); //*****************************************
  for(address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    
    if (error == 0) {
      Serial.print("I2C1 device found at address 0x");
      if (address < 16) 
        Serial.print("0");
      Serial.println(address, HEX);

      nDevices++;
    }
    else if (error == 4) {
      Serial.print("Unknown error at address 0x");
      if (address < 16) 
        Serial.print("0");
      Serial.println(address, HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C1 devices found");
  else
    Serial.println("I2C1 done");
    Serial.println("");
    delay(1000);   
}

I trigger on the falling edge of SDA, reset MG24 and observe the waveform.

1 Like

With the MG24 Wire library, you should send a “dummy” byte when scanning.

  for (address = 0x01; address < 0x7E; address++)
  {
    Wire.beginTransmission(address);
    Wire.write(DUMMY_BYTE); // Send 1 dummy byte
    i2c_error = Wire.endTransmission();

    if (i2c_error == 0)
    {
      Serial.print("I2C device found at ");
      Serial.println(address, HEX);
      nDevices++;
    }
    else
    {
      Serial.print("No I2C device ");
      Serial.println(address, HEX);
    }
}
2 Likes