Conflict between SDIO SD Card and I2C device

Hello, from the schematic for ESP32-S3 Think Plus, a set of pins have been assigned for the SDIO 4-bit SD card. According to the diagram, I have:

int clk = 38; 
int cmd = 34; 
int d0 = 39; 
int d1 = 40; 
int d2 = 47; 
int d3 = 33; 

ESP32 Thing Plus ESP32-S3

Writing data to SD card via the SDIO 4-bit protocol works fine.

I also have a program which obtains the orientation from Adafruit BNO055 Qwiic sensor:

I defined it using:

Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28, &Wire); 

That program also worked fine.

However, when I combined the two programs together, the BNO055 always gives 0 as the orientation. I noticed that if I temporarily remove the following:

 if (!SD_MMC.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }

The sensor outputed the correct values. However, once I put the above block of code back, the sensor outputs 0 as the orientation even I rotated it. Is there some kind of conflict between SDIO SSD and this QWIIC device? Strangly, even the BNO055 have 0x28 and 0x29 as acceptable address, having:

Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x29, &Wire); 

cased the below code to be true and error messaged printed on the Serial Monitor.

  if(!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }

It seems that there is some kind of conflict between SDIO and I2C but I don’t know why and how to fix this problem. Could you please help?

1 - There is no such board as the “ESP32-S3 Think Plus.”

2 - Your combined code is most likely the problem here but you didn’t post it.

3 - In the event it’s not your code, it’s unlikely but there could be conflicts with the libraries you’re using.

  1. Sorry for the typo. I meant this product:SparkFun Thing Plus - ESP32-S3 - SparkFun Electronics
  2. I know because both programs worked individuals but when combined, there seems to be some conflict between the SDIO SD card and the Quiic sensor.

Are the pin assignments for clk, cmd, d0-d3 correct? I tried to google to see if anybody else has the same problem but their AI (which we should not trust entirely) stated:

Based on the SparkFun Thing Plus - ESP32-S3 hardware layout, there is a potential for conflict between the microSD card (using SDIO or SPI) and the Qwiic I2C connector if not properly managed, although the ESP32-S3’s flexible GPIO mapping allows for workarounds. The onboard microSD card slot uses SPI (defaulting to pins 18, 19, 23, and CS 5 or similar, depending on the specific revision), which can clash with specific I2C setups if not configured properly.

Do you think this is the problem?

Possibly, I’m not able to look at the schematic for the board right now but it sounds like the qwiic socket might share pins with the SD socket.

You might try using some unused I/O pins for SDA and SCL and see if that gets things working. You will need to change your code to tell it what new I2C pins you’re using.

1 Like

Thanks for the pointer. According to the schmetic, QWIIC uses 8 for SDA and 9 for SCL. They are different from the pins assigned for the SQIO SD card. I wonder what caused the conflict.

I tried another set of pins:

#define I2C_SCL 13

#define I2C_SDA 12

Adafruit_BNO055 bno;

In the setup(), I have:

  Wire.setPins(I2C_SDA, I2C_SCL);
  Wire.begin();

  bno = Adafruit_BNO055(55, 0x28, &Wire); 

but the sensor still gives only 0. Is this method of pin reassignment correct? Tried 10 (SCL) and 11 (SDA) as well as 13 (SCL) and 12 (SDA) but same problem.

I used an I2C scanner to scan. Strangly, even I have only one QWIIC device (BNO055) connected to the Thing Plus (at 0x28), it stated that here is another I2C device found at address 0x36. Disconnecting the BNO055 showed only 0x36.

The fuel gauge that is on the ESP32-S3 Thing plus has address 0x36. It looks the I2c is working.

Maybe there is a concern with the 3v3. Both use the 3.3V_P, which is 3.3V provided with an enabled LDO (RT9080). Sometimes (like with the OpenLog) there are startup problem when SD card taking to much power at start.

Not sure about your sketch, but maybe try the combined the sketch you created and first (or only) enable de BNO05.

1 Like

Yes, the sensor worked when I only enabled the BNO055 in the setup() function. It started to print only 0 when the SD_MMC.begin() function was included. Sensor gave correct outputs as soon as I commented out the SD_MMC.begin() function.

  bno = Adafruit_BNO055(55, 0x28, &Wire);
 
  if (!SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)) {
    Serial.println("Pin change failed!");
    return;
  }

  if (!SD_MMC.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
 

In the worst case of the 3v3 concern, what can be done?

I am not yet 100% sure it is de 3v3.. but it could be. Maybe you have a voltmeter to check, but even then.

How about testing to do begin ():

  1. with the SD card NOT in place OR
  2. with different pins on the SD.. I know it will fail.. but that might detect conflict. use 10, 14, 15, 16, 17 ,18 (these are the none used analog channels A0… A5) for cmd, clk etc.
  1. Even the SD card is not inserted, sensor still gives 0 (actually 0.00) as long as I have
if (!SD_MMC.begin()) {

in the program.

  1. Yes, as you predicted, I got the “Card Mount Failed"" showed up on Serial Monitor. Sensor readings still 0.00

hmmm… it does not yet makes sense to me.

  1. without the card inserted a potential 3v3 load is NOT impacting.
  2. with selecting other pins.. it does not impact pin-assignment NOR 3v3.

I don’t know yet what is causing the collision..

Try something else:

Take the I2C scanner sketch that worked (detected both devices). Now add the relevant parts to do a (potential) successful SD_MMC.begin() see what happens. Maybe something to do with the BNO055 driver-files ??

You mean just add codes related to the SDIO SD card to the I2C scanner? The SDIO part is mainly from:

arduino-esp32/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino at master ¡ espressif/arduino-esp32 ¡ GitHub

The pins shown under ESP32-S3 DevKit is different from the ones used to connect to the SDIO SD Card in the Thing Plus ESP32-S3. I changed those pin numbers as shown in the first post.

Combining the SDIO SD card to the I2C scanner had no problem. The program detected both I2C devices. Running Examples→Adafruit BNO055→sensorapi also got correct readings from the BNO055 sensor. However, when combining them together, BNO055 showed 0.00 again.

Here is the program. Perhaps somebody could figure out what went wrong?

#include <Wire.h>
#include "FS.h"
#include "SD_MMC.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>

// The following pin assignments are based on Sparkfun ESP32-S3 Thing Plus Schematic
// https://cdn.sparkfun.com/assets/5/e/6/5/0/SparkFun_Thing_Plus_ESP32-S3.pdf
int clk = 38;  //36;
int cmd = 34;  //35;
int d0 = 39;   //37;
int d1 = 40;   //38;
int d2 = 47;   // 33;
int d3 = 33;   //9;  

File myFile;
#define MAX_COUNT 10
int count = 0;

// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
//                                   id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28, &Wire);


void setup() {
  Wire.begin();
  Serial.begin(115200);
  Serial.println("\nI2C Scanner");


  
  if (!SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)) {
    Serial.println("Pin change failed!");
    return;
  }


  if (!SD_MMC.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }

  // Open a new file the SDIO way
  myFile = SD_MMC.open("/data.txt", FILE_WRITE);


  /* Initialise the sensor */
  if (!bno.begin()) {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while (1)
      ;
  } else
    Serial.println("BNO055 detected");
  delay(10000);


  bno.setExtCrystalUse(true);
}

void loop() {
  byte error, address;
  int nDevices;

  /* Get a new sensor event */
  sensors_event_t event;
  bno.getEvent(&event);

  /* Display the floating point data */
  Serial.print("X: ");
  Serial.print(event.orientation.x, 4);
  Serial.print("\tY: ");
  Serial.print(event.orientation.y, 4);
  Serial.print("\tZ: ");
  Serial.print(event.orientation.z, 4);


  Serial.println("Scanning...");
  nDevices = 0;
  for (address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      myFile.print("I2C device found at address 0x");
      if (address < 16) {
        Serial.print("0");
        myFile.print("0");
      }
      Serial.println(address, HEX);
      myFile.print(address, HEX);
      nDevices++;
    } else if (error == 4) {
      Serial.print("Unknow error at address 0x");
      if (address < 16) {
        Serial.print("0");
      }
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  } else {
    Serial.println("done\n");
  }
  count++;
  if (count > MAX_COUNT) {
    myFile.close();
    Serial.println("File closed");
  }
  delay(50);
}

Not sure if related but there is a warning at: Overview | Adafruit BNO055 Absolute Orientation Sensor | Adafruit Learning System

The BNO055 I2C implementation violates the I2C protocol in some circumstances. This causes it not to work well with certain chip families. It does not work well NXP i.MX RT1011, and it does not work well with I2C multiplexers. With ESP32 and ESP32-S3, CircuitPython 9.2.2 and later (which use ESP-IDF 5.3.2 and later) work better.

Are there good absolute oriented sensor (giving absolute rotational angles about the 3-axes) from Sparkfun that is known to work without causing the kind of problem I am having here? Ideally QWIIC.

interesting remark about the BNO055 I2c implementation.

Just for the fun in chatgpt I typed : what is wrong with the BNO055 I2C implementation ?

Got of 7 items that you can get as well, so I will not copy/paste them here.

But the first is clock stretching. That is indeed weak on the ESP32. You can try to increase the timeout in Wire after Wire.begin(). see : https://docs.arduino.cc/language-reference/funktionen/communication/wire/setWireTimeout/. Also you can use setclock() to reduce the I2C speed.

The 7th remark made me wonder “7. Bosch basically gave up and said “use UART”. REALLY ??

Chatgpt also gives advices on other IMU to use…

Tried setWireTimeout but it gave a compilation error. I am using Wire.h just like the sample program does.

Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);

Compilation error: ‘class TwoWire’ has no member named ‘setWireTimeout’; did you mean ‘setTimeout’?

This BNO055 sensor works fine with their Feather ESP32-S3 and Adalogger with RTC and SD-card product but that SD-card slot is not a SDIO one.

So there is something wrong when using the sensor with a SDIO SD card slot but we don’t know what that is.

I have hand picked two boards. They are expensive. Which one is less likely to have a conflict issue I am having? Note that I need to get the absolute rotational angles about the Yaw-Pitch-Roll axes. If you know a better one, please let me know.

SparkFun VR IMU Breakout - BNO086 (Qwiic) - SparkFun Electronics

SparkFun 9DoF IMU Breakout - ISM330DHCX, MMC5983MA (Qwiic) - SparkFun Electronics

In the ESP32 3.3.5 library there is a call: setTimeOut(uint16_t timeOutMillis) to use instead.

I am surprised to hear that it all works on the feather ESP32S3. But why ?? If it is the SDIO, according to the readme in the library:

By default, this library uses 4-bit line mode, utilizing 6 pins: CLK, CMD, D0 - D3 and 2 power lines (3.3V and GND). It is possible to use 1-bit line mode (CLK, CMD, D0, 3.3V, GND) by passing the second argument mode1bit==true:

  SD_MMC.begin("/sdcard", true);

D1, D2 and D3 should not be specified

I have no experience with the other IMU’s, maybe someone else can advice you on that.

Tried:

  void setup() {

  // Initialize Serial Monitor
  Serial.begin(115200);
  Wire.setTimeOut(60000);

but senor outputs still zeros.

Using 1-bit line mode like below also does not help.

#ifdef TEST
  // Need this if statement to work. Otherwise get "Card Mount Failed"
  if (!SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)) {
    Serial.println("Pin change failed!");
    return;
  }
#endif

  // Need this or nothing is written to file
//  if (!SD_MMC.begin()) {
    if (!SD_MMC.begin("/sdcard", true)) {
    Serial.println("Card Mount Failed");
    return;
  }

I guess it might be time to try another sensor from Sparkfun.

1 Like