Xiao rp2040 i2c

Just received XIAO RP2040 boards. Using with Arduino IDE, basic operations are OK (Blink LED_BUILTIN, Do various examples like reading internal Temperature, NeoPixel stuff, etc.)

Here’s my problem: Can’t get the I2C to work.

This works:

  uint8_t dev_addr7 = 0x48;
  // This works: 
  // Scope display of SCL and SDA are nominal
  // Return value of zero indicates successful ACK by device
  Wire.begin();
  Wire.beginTransmission(dev_addr7);
  uint8_t err = Wire.endTransmission();
  Serial.printf("I2C probe of 0x%02X returned %u at %lu ms\n", 
                 dev_addr7, err, millis());

If I have a device with that address attached to the I2C pins (SDA on D4, SCL on D5), all is good. It prints the proper return value of zero, the I2C pins show the transfer and show the ACK by the device.

On the other hand, the following code does not wiggle the SDA or SCL pins.

  // This doesn't work: SDA and SCL pins do not wiggle and
  // return value from endTransmission is 4 (Other problem)
  uint8_t buff[2] = {0x45, 0x54};
  Wire.beginTransmission(dev_addr7);
  Wire.write(buff[0]);
  Wire.write(buff[1]);
  err = Wire.endTransmission();
  Serial.printf("After trying to write bytes to 0x%02X: err = %d at %lu ms\n", 
                 dev_addr7, err);

Output looks like this:

I2C Test Compiled on Dec 11 2021 at 16:31:05
D5  = 7, D4  = 6
SCL = 7, SDA = 6
I2C probe of 0x48 returned 0 at 4552 ms
After trying to write bytes to 0x48: err = 4 at 4552 ms

Nothing that involves the I2C hardware Write() function works. Note that the first snippet that I showed invokes a “special case” that doesn’t call the hardware Write() function.

Bottom line: I know the RP2040 I2C module works (I have several other RP2040 boards such as the Arduino Nano 33 BLE and the Arduino Nano RP2040, which I have tested extensively), but am thinking there is something in the SeeedStudio board library that is borked.

Does anyone have any experience with the XIAO RP2040 I2C hardware? Any Suggestions? Anything at all?

My setup:

  • Arduino 1.8.16 on Windows 10
  • Seeed XIAO RP2040 Board package version1.9.3 installed in Arduino Board Manager
  • Board: “Seeed XIAO RP2040” selected in Arduino IDE

Regards,

Dave

The second code does not include Wire.begin();.

Thanks.

I didn’t make clear that the second snipped I posted immediately followed the first one in the same sketch.
Here’s the whole enchilada:

/*
 * Illustration of problem with I2C on XIAO RP2040
 * 
 * davekw7x
 * December, 2021
 */

#include <Wire.h>
void setup(void) {
  Serial.begin(115200);
  
  // Wait until the connection is made
  while (!Serial);
  
  // Give it a little time to setle down 
  delay(100);
  Serial.println("\nI2C Test Compiled on " __DATE__ " at " __TIME__);

  // These are the (default) GPIO pin numbers used by I2C on Wire
  Serial.printf("D5  = %u, D4  = %u\n", D5, D4);
  Serial.printf("SCL = %u, SDA = %u\n", SCL, SDA);

  uint8_t dev_addr7 = 0x48;
  uint8_t err;
  // This works: 
  // Scope display of SCL and SDA are nominal
  // Return value of zero indicates successful ACK by device
  Wire.begin();
  Wire.beginTransmission(dev_addr7);
  err = Wire.endTransmission();
  Serial.printf("I2C probe of 0x%02X returned %u at %lu ms\n", 
                 dev_addr7, err, millis());
  
  // This doesn't work: SDA and SCL pins do not wiggle and
  // return value from endTransmission is 4 (Other problem)
  uint8_t buff[2] = {0x45, 0x54};
  Wire.beginTransmission(dev_addr7);
  Wire.write(buff[0]);
  Wire.write(buff[1]);
  err = Wire.endTransmission();
  Serial.printf("After trying to write bytes to 0x%02X: err = %d at %lu ms\n", 
                 dev_addr7, err);

  // Infinite loop: keep it here
  while (1)
    ;
}
 
void loop(void) {
}

I have tried numerous other sequences, all with the same result: SCL and SDA bits never wiggle when trying to write to a device.

Note also, that I have more than one XIAO RP2040. They all act the same. Namely, everything that I tested, other than the I2C functionality, works as expected.

Regards,

Dave

You need:

Wire.endTransmission ();

See example:

Wire.beginTransmission (4); // transmit to device # 4
Wire.write ("x is "); // sends five bytes
Wire.write (x); // sends one byte
Wire.endTransmission (); // stop transmitting

Thanks, but…

Result is the same: No code that involves Wire.write() results in SDA and SCL pins wiggling. (And endTransmission() returns a value of 4).

The bottom line is: The same sequence (byte-at-a-time or bytes in an array or string literal) that works for me on other Arduino boards, including the Nano RP2040 Connect, does NOT work on the XIAO RP2040. Since the RP2040 hardware I2C interface is OK, I believe there is an “Issue” with the Seeed software in the board package for the XIAO RP2040.

Period. Full Stop.

Regards,

Dave

Well, I found a bug in the Seeed XIAO RP2040 board package that borked the I2C.

Here’s a summary:
The RP2040 has two I2C ports, i2c0 and I2c1. Not all pins can be assigned to a given port. It’s in the RP2040 data sheet.

The XIAO RP2040 designates package pins 5 and 6 to be SDA and SCL for I2C using i2c0. These are Arduino pins D4 and D5 (connected to RP2040 GIO Pins P6 and P7) respectively.

Now, here’s the flaw in the ointment: There are two I2C modules on the RP2040, ic0 and ic1. The Arduino Wire object uses ic0 and Wire1 uses ic1.

The Seeed package software defines SDA and SCL to be GIO pins P6 and P7, but these pins can NOT be used with ic0, so I2C for those connections with Wire is doomed. Period.

I tried to imagine (and even tested some ideas) ways to implement user-level software workarounds, but came to the conclusion that library changes would be necessary.

As an outsider, I am not able to peer into the minds of the actual code implementers. (See Footnote). However, I came up with what I think are minimum library changes to make my test program work. Note that I haven’t tested EVERYTHING that might be affected by my changes but, so far, I think my approach is valid.

Here’s the changes: I edited lines 61-65 in the file
Seeduino\hardware\rp2040\1.9.3\variants\Seed_XIAO_RP2040\pins_arduino.h

As follows

#define SDA  (28u) /* Change from (6u) davekw7x */
#define SCL  (29u) /* Change from (7u) davekw7x */

#define PIN_WIRE1_SDA  (6u) /*  Change from (26u) davekw7x */
#define PIN_WIRE1_SCL  (7u) /*  Change from (27u) davekw7x */

And now all is well (at least to the extent that I have tested). I2C looks good on the 'scope, and the target device works as expected.

Some output from the attached slightly-more-edifying test program:

I2C Test Compiled by davekw7x on Dec 20 2021 at 12:01:40
Board is Seeed XIAO RP2040

I changed definitions for SCL, SDA, PIN_WIRE1_SCL, and PIN_WIRE1_SDA
in 'variants\Seed_XIAO_RP2040\pins_arduino.h'
  For Wire
    #define SDA  (28u) /* Change from (6u) davekw7x */
    #define SCL  (29u) /* Change from (7u) davekw7x */
  For Wire1
    #define PIN_WIRE1_SDA  (6u) /*  Change from (26u) davekw7x */
    #define PIN_WIRE1_SCL  (7u) /*  Change from (27u) davekw7x */

With these modifications, here are the default 'Arduino' pin connections
for the Seeed XIAO RP2040
  For Wire
    SCL is 'Arduino' D3 = GPIO29, and SDA is 'Arduino' D2 = GPIO28
  For Wire1
    SCL is 'Arduino' D5 = GPIO7, and SDA is 'Arduino' D4 = GPIO6

I2C probe of 0x48 on Wire1 returned 0 at 350 ms
After trying to write bytes to 0x48 on Wire1: err = 0 at 350 ms

Bottom line IWFMYMMV (It Works For Me; Your Mileage May Vary).

Would appreciate feedback from Seeed support people, as I couldn’t find a way to submit an “official” bug report.

Regards,

Dave
I2CForForum.zip (1.5 KB)

3 Likes

I use Wire (I2C0) and Wire1 (I2C1) properly in the sketch.

When using Wire (I2C0)
Wire.setSDA (D2);
Wire.setSCL (D3);
Wire.begin ();

When using Wire1 (I2C1)
Wire1.setSDA (D4);
Wire1.setSCL (D5);
Wire1.begin ();

I checked some sketches and they are working fine.

1 Like

Thanks!

Regards,
Dave

Just wanted to confirm this fixed my issue as well. Was using Seeed RP2040 with an MLX90614 Infrared Temp sensor. Example sketch for Library worked(output to serial correctly ), but returned blanks when data was read. Swapping to D3 and D4 after updating library completely resolved the issue.
Thank you!

Late-breaking news: This just in!

The latest version of the XIAO RP2040 board package, 2.7.2, now works with the “normal” I2C Wire object on the designated XIAO RP2040 I2C pins (SDA on D4 and SCL on D5).

I give some graphics examples driving the OLED on the XIAO Extension board in this thread:

Regards,

Dave

Hello @davekw7x,

I’ve been trying the RP2040+Arduino 1.8.19 + RP2040 2.7.2 package + XIAO Expansion board and can’t get any I2C, etc. to work with this combination. I’ve gone back and looked at your other posts and made the same changes (granted, I’m using a Mac, so just slight differences in file locations).

Was your success seen with the XIAO Expansion board (this is the one with the LCD)? I also have the other expansion board and haven’t had I2C success with that one either.

When I started this thread, the RP2040 board package had errors in the pins_arduino.h variants file that required modifications to make the RP2040 work with any I2C devices (not just with the XIAO Expansion Board).

If you read all the way through to my last post here, you can see that this has been corrected by Seeed.

The result:

With the RP2040 2.7.2 board package, no modifications to pins_arduino.h or any other system or library files are necessary to run I2C stuff that I have tried.

I’m using boards marked “Seeeduino XIAO Expansion Board v1.0”
These have been around since before the XIAO RP2040 was released, and, yes, there is an OLED display controlled by an SSD1306.

The example I linked in my most recent post here uses the Display on the expansion board. I hate to repeat myself, but this uses the 2.7.2 board package with no modifications of any kind.

I have also interfaced to I2CEEPROM devices using the Arduino <I2C_eeprom.h> library and other I2C devices with the RP2040. (I usually use solderless breadboards for prototyping, but sometimes I use the XIAO Expansion board for initial testing.)

Regards,

Dave

Footnote: I did modify the pins_arduino.h file in the 2.7.2 board package to get SPI working on the XIAO RP2040. This was for any SPI connections, not just the XIAO Expansion board.

Yup, that’s what I thought. I’ve tested the RP2040+XIAO Expansion board (multiple, actually) on different PCs/Macs with changed and original pins_arduino.h and have even removed/reinstalled 2.7.2 and I’m not getting any I2C communication. I’ll put everything on my logic analyzer to see what’s going on.

Thank you for the detailed response.

I can’t even get the thing to hold PORT!

I’ve been struggling getting the XIAO RP2040 to work with i2c. I got it working and here’s what I learned:

I seem to have better luck with the previous Arduino editor (v 1.8)

The Seeed provided board library I’ve had problems with:
The newest one (2.7.2) won’t program at all. All I get is An error occurred while uploading the sketch
The previous release (1.12.0) will program the chip fine, but I have the same i2c issues that davekw7x does above.

However, switching to use the Earle Philhower board library that now supports the XIAO RP2040 actually works 100% fine. I switched boards to that and it “just worked”. Cheers!

I just wanted to say a huge thankyou to you, davekw7x. Even 2.5 years later, running on Philhower’s Rapsberry Pi Pico/RP2040 version 3.7.2 with Arduino IDE 1.8.19, I have never been able to get I2C1 working on the XIAO RP2040 until I found your post. Changing my pins_arduino.h to:

// Wire
#define __WIRE1_DEVICE (i2c1)
#define PIN_WIRE1_SDA  (6u)
#define PIN_WIRE1_SCL  (7u)
#define SDA            PIN_WIRE1_SDA
#define SCL            PIN_WIRE1_SCL
#define I2C_SDA        (SDA)
#define I2C_SCL        (SCL)

// Wire1 not pinned out
#define __WIRE0_DEVICE (i2c0)
#define PIN_WIRE0_SDA  (28u)
#define PIN_WIRE0_SCL  (29u)

made all the difference. I also tried your I2CForForum.ino sketch with a BME280 (knowing the address would be 0x76), and it worked correctly.

Truly, thankyou.