This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

BLE Softdevice crashes when more than one device on I2C bus

Hi

I'm working with the following products to develop a product and have chosen to use a IDE based around Arduino and Visual Studio Code. This iDE along side off the shelf products allows for rapid simple programme and hardware construction for testing and evaluation without the for deep C knowledge prior to moving to a formal product development cycle. Therefore some of the products being used rely on the Adafruit versions of the Arduino libraries to function.

Products:

SparkFun Pro nRF52840 Mini - Bluetooth Development Board - https://www.sparkfun.com/products/15025?_ga=2.135426737.141134967.1579786966-1791920524.1576505606

SparkFun IMU Breakout - MPU-9250 - https://www.sparkfun.com/products/13762?_ga=2.218676889.141134967.1579786966-1791920524.1576505606

SparkFun Micro OLED Breakout - https://www.sparkfun.com/products/14532

I'm using I2C for the communications bus between the nrf52 and the two peripherals (MPU-9259 & Micro OLED). I have successfully connected both devices and driven output to the display and received a response from the IMU, using the following code:

#include <MPU9250.h>
#include <SFE_MicroOLED.h>  // Include the SFE_MicroOLED library - I2C address of 0X3D (ADDR pin open 0X3D | closed 0X3C)

#define SerialDebug true  // Set to true to get Serial output for debugging

// MicroOLED Definition
#define PIN_RESET 9  // Connect RST to pin 9 (req. for SPI and I2C)
#define DC_JUMPER 1 // Set to either 0 (default) or 1 based on jumper, matching the value of the DC Jumper
// Also connect pin 13 to SCK and pin 11 to MOSI
// Declare a MicroOLED object. The parameters include:
// 1 - Reset pin: Any digital pin
// 2 - D/C pin: Any digital pin (SPI mode only)
// 3 - CS pin: Any digital pin (SPI mode only, 10 recommended)
MicroOLED oled(PIN_RESET, DC_JUMPER); //Example I2C declaration, uncomment if using I2C 

//MPU9250 Definition
#define I2Cclock 400000
#define I2Cport Wire
#define MPU9250_ADDRESS MPU9250_ADDRESS_AD0   // Use either this line or the next to select which I2C address your device is using
//#define MPU9250_ADDRESS MPU9250_ADDRESS_AD1
MPU9250 myIMU(MPU9250_ADDRESS, I2Cport, I2Cclock);

void setup()
{

  Serial.begin(115200);
  if (true) {while ( !Serial ) delay(10);}; //ture will wait until native usb is connected
  if (SerialDebug) {
    Serial.println("setup - Serial.begin()");
  }
  
  //set up I2C bus
  Wire.begin();
  if (SerialDebug) {
    Serial.println("setup - Wire.begin()");
  }

  //Initiate the OLED Service
  oled.begin();
  if (SerialDebug) {
    Serial.println("setup - oled.begin()");
  }
  oled.clear(ALL);  // Clear the display's memory (gets rid of artifacts)
  // To actually draw anything on the display, you must call the

  oled.setFontType(0);  // Set font to type 1
  oled.clear(PAGE);     // Clear the page
  oled.setCursor(0, oled.getLCDHeight() / 2); // Set cursor to top-left
  oled.print("StingRay");
  oled.display();

  // Read the WHO_AM_I register, test comms to MPU9250
   if (SerialDebug) {
    byte c = myIMU.readByte(MPU9250_ADDRESS, WHO_AM_I_MPU9250);
    Serial.println("");
    Serial.println("MPU9250 Test");
    Serial.println("------------");
    Serial.print(F("MPU9250 I AM 0x"));
    Serial.print(c, HEX);
    Serial.print(F(" I should be 0x"));
    Serial.println(0x71, HEX);
    Serial.println("");

    if (c == 0x71) // WHO_AM_I should always be 0x71
    {
      Serial.println(F("MPU9250 is online..."));

      // Start by performing self test and reporting values
      myIMU.MPU9250SelfTest(myIMU.selfTest);
      Serial.print(F("x-axis self test: acceleration trim within : "));
      Serial.print(myIMU.selfTest[0],1); Serial.println("% of factory value");
      Serial.print(F("y-axis self test: acceleration trim within : "));
      Serial.print(myIMU.selfTest[1],1); Serial.println("% of factory value");
      Serial.print(F("z-axis self test: acceleration trim within : "));
      Serial.print(myIMU.selfTest[2],1); Serial.println("% of factory value");
      Serial.print(F("x-axis self test: gyration trim within : "));
      Serial.print(myIMU.selfTest[3],1); Serial.println("% of factory value");
      Serial.print(F("y-axis self test: gyration trim within : "));
      Serial.print(myIMU.selfTest[4],1); Serial.println("% of factory value");
      Serial.print(F("z-axis self test: gyration trim within : "));
      Serial.print(myIMU.selfTest[5],1); Serial.println("% of factory value");

      // Calibrate gyro and accelerometers, load biases in bias registers
      myIMU.calibrateMPU9250(myIMU.gyroBias, myIMU.accelBias);

      myIMU.initMPU9250();
      // Initialize device for active mode read of acclerometer, gyroscope, and
      // temperature
      Serial.println("MPU9250 initialized for active data mode....");

      // Read the WHO_AM_I register of the magnetometer, this is a good test of
      // communication
      byte d = myIMU.readByte(AK8963_ADDRESS, WHO_AM_I_AK8963);
      Serial.print("AK8963 ");
      Serial.print("I AM 0x");
      Serial.print(d, HEX);
      Serial.print(" I should be 0x");
      Serial.println(0x48, HEX);

      if (d != 0x48)
      {
        // Communication failed, stop here
        Serial.println(F("Communication failed, abort!"));
        Serial.flush();
        abort();
      }

      //Get magnetometer calibration from AK8963 ROM
      myIMU.initAK8963(myIMU.factoryMagCalibration);
      // Initialize device for active mode read of magnetometer
      Serial.println("AK8963 initialized for active data mode....");

      //  Serial.println("Calibration values: ");
      Serial.print("X-Axis factory sensitivity adjustment value ");
      Serial.println(myIMU.factoryMagCalibration[0], 2);
      Serial.print("Y-Axis factory sensitivity adjustment value ");
      Serial.println(myIMU.factoryMagCalibration[1], 2);
      Serial.print("Z-Axis factory sensitivity adjustment value ");
      Serial.println(myIMU.factoryMagCalibration[2], 2);

      // Get sensor resolutions, only need to do this once
      myIMU.getAres();
      myIMU.getGres();
      myIMU.getMres();

      // The next call delays for 4 seconds, and then records about 15 seconds of
      // data to calculate bias and scale.
      //    myIMU.magCalMPU9250(myIMU.magBias, myIMU.magScale);
      Serial.println("AK8963 mag biases (mG)");
      Serial.println(myIMU.magBias[0]);
      Serial.println(myIMU.magBias[1]);
      Serial.println(myIMU.magBias[2]);

      Serial.println("AK8963 mag scale (mG)");
      Serial.println(myIMU.magScale[0]);
      Serial.println(myIMU.magScale[1]);
      Serial.println(myIMU.magScale[2]);
      //    delay(2000); // Add delay to see results before serial spew of data


      Serial.println("Magnetometer:");
      Serial.print("X-Axis sensitivity adjustment value ");
      Serial.println(myIMU.factoryMagCalibration[0], 2);
      Serial.print("Y-Axis sensitivity adjustment value ");
      Serial.println(myIMU.factoryMagCalibration[1], 2);
      Serial.print("Z-Axis sensitivity adjustment value ");
      Serial.println(myIMU.factoryMagCalibration[2], 2);
    } // if (c == 0x71
    else
    {
      Serial.print("Could not connect to MPU9250: 0x");
      Serial.println(c, HEX);

      // Communication failed, stop here
      Serial.println(F("Communication failed, abort!"));
      Serial.flush();
      abort();
    }
  }

}

void loop()
{

  //Main loop

}

The following output is produced with the phrase 'StingRay' displayed on the OLED:

setup - Serial.begin()
setup - Wire.begin()
setup - oled.begin()

MPU9250 Test
------------
MPU9250 I AM 0x71 I should be 0x71

MPU9250 is online...
x-axis self test: acceleration trim within : 1.4% of factory value
y-axis self test: acceleration trim within : 0.0% of factory value
z-axis self test: acceleration trim within : 2.5% of factory value
x-axis self test: gyration trim within : -4.4% of factory value
y-axis self test: gyration trim within : -1.1% of factory value
z-axis self test: gyration trim within : -0.3% of factory value
MPU9250 initialized for active data mode....
AK8963 I AM 0x48 I should be 0x48
AK8963 initialized for active data mode....
X-Axis factory sensitivity adjustment value 1.18
Y-Axis factory sensitivity adjustment value 1.18
Z-Axis factory sensitivity adjustment value 1.14
AK8963 mag biases (mG)
0.00
0.00
0.00
AK8963 mag scale (mG)
0.00
0.00
0.00
Magnetometer:
X-Axis sensitivity adjustment value 1.18
Y-Axis sensitivity adjustment value 1.18
Z-Axis sensitivity adjustment value 1.14

My problem starts when I begin the implementation BLE. I add the following code:

#include <bluefruit.h>

void setup()
{
...
...
...
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
if (SerialDebug) {
  Serial.println("setup - Bluefruit.begin()");
}
Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values
Bluefruit.setName("mStingRay");
...
...
...
}

At this point I have not implemented any more BLE functionality as my device crashes as soon as I reach Bluefruit.begin().

Any help/guidance please.

Thanks in advance ...

Parents Reply Children
Related