Hello all.
Basically what the title asks. I needed data from another ICM-20948 in my application. I tried connecting a SparkFun ICM-20948 using the Qwiic connector to the OLA. Below is the code that I’m trying to run:
/****************************************************************
* Testing basic functionality of the ICM 20948 on the OpenLog Artemis.
* Select "SparkFun Apollo3" \ SparkFun RedBoard Artemis ATP" as the board.
*
* Based on:
*
* Example1_Basics.ino
* ICM 20948 Arduino Library Demo
* Use the default configuration to stream 9-axis IMU data
* Owen Lyke @ SparkFun Electronics
* Original Creation Date: April 17 2019
*
* This code is beerware; if you see me (or any other SparkFun employee) at the
* local, and you've found our code helpful, please buy us a round!
*
* Distributed as-is; no warranty is given.
***************************************************************/
// OLA Specifics:
const byte PIN_IMU_POWER = 27; // The Red SparkFun version of the OLA (V10) uses pin 27
const byte PIN_IMU_INT = 37;
const byte PIN_IMU_CHIP_SELECT = 44;
const byte PIN_SPI_SCK = 5;
const byte PIN_SPI_CIPO = 6;
const byte PIN_SPI_COPI = 7;
const byte PIN_QWIIC_SCL = 8;
const byte PIN_QWIIC_SDA = 9;
#include "ICM_20948.h" // Click here to get the library: http://librarymanager/All#SparkFun_ICM_20948_IMU
#include <Wire.h>
#define USE_SPI // Uncomment this to use SPI
#define SERIAL_PORT Serial
#define SPI_PORT SPI // Your desired SPI port. Used only when "USE_SPI" is defined
#define CS_PIN PIN_IMU_CHIP_SELECT // Which pin you connect CS to. Used only when "USE_SPI" is defined. OLA uses pin 44.
TwoWire qwiic(PIN_QWIIC_SDA, PIN_QWIIC_SCL);
#define WIRE_PORT qwiic // Your desired Wire port. Used when "USE_SPI" is not defined
#define AD0_VAL 0 // The value of the last bit of the I2C address.
// On the SparkFun 9DoF IMU breakout the default is 1, and when
// the ADR jumper is closed the value becomes 0
ICM_20948_SPI myICM_SPI; // If using SPI create an ICM_20948_SPI object
ICM_20948_I2C myICM_I2C; // Otherwise create an ICM_20948_I2C object
void setup()
{
// ========= Initialise SPI ========
SPI_PORT.begin();
pinMode(PIN_IMU_CHIP_SELECT, OUTPUT);
digitalWrite(PIN_IMU_CHIP_SELECT, HIGH); //Be sure IMU is deselected
enableCIPOpullUp(); // Enable CIPO pull-up on the OLA
//There is a quirk in v2.1 of the Apollo3 mbed core which means that the first SPI transaction will
//disable the pull-up on CIPO. We need to do a fake transaction and then re-enable the pull-up
//to work around this...
#if defined(ARDUINO_ARCH_MBED)
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); // Do a fake transaction
SPI.endTransaction();
enableCIPOpullUp(); // Re-enable the CIPO pull-up
#endif
// ========= Initialise I2C ========
WIRE_PORT.begin();
WIRE_PORT.setClock(400000);
//Reset ICM by power cycling it
imuPowerOff();
delay(10);
imuPowerOn(); // Enable power for the OLA IMU
delay(100); // Wait for the IMU to power up
SERIAL_PORT.begin(115200);
while(!SERIAL_PORT);
bool initialized = false;
while( !initialized )
{
myICM_SPI.begin( CS_PIN, SPI_PORT );
myICM_I2C.begin( WIRE_PORT, AD0_VAL );
SERIAL_PORT.print( F("Initialization of the in-built (SPI) sensor returned: ") );
SERIAL_PORT.println( myICM_SPI.statusString() );
SERIAL_PORT.print( F("Initialization of the external (I2C) sensor returned: ") );
SERIAL_PORT.println( myICM_I2C.statusString() );
if( myICM_SPI.status != ICM_20948_Stat_Ok || myICM_I2C.status != ICM_20948_Stat_Ok ){
SERIAL_PORT.println( "Trying again..." );
delay(500);
}else{
initialized = true;
}
}
}
void loop() {
}
void imuPowerOn()
{
pinMode(PIN_IMU_POWER, OUTPUT);
digitalWrite(PIN_IMU_POWER, HIGH);
}
void imuPowerOff()
{
pinMode(PIN_IMU_POWER, OUTPUT);
digitalWrite(PIN_IMU_POWER, LOW);
}
#if defined(ARDUINO_ARCH_MBED) // updated for v2.1.0 of the Apollo3 core
bool enableCIPOpullUp()
{
//Add 1K5 pull-up on CIPO
am_hal_gpio_pincfg_t cipoPinCfg = g_AM_BSP_GPIO_IOM0_MISO;
cipoPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K;
pin_config(PinName(PIN_SPI_CIPO), cipoPinCfg);
return (true);
}
#else
bool enableCIPOpullUp()
{
//Add CIPO pull-up
ap3_err_t retval = AP3_OK;
am_hal_gpio_pincfg_t cipoPinCfg = AP3_GPIO_DEFAULT_PINCFG;
cipoPinCfg.uFuncSel = AM_HAL_PIN_6_M0MISO;
cipoPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K;
cipoPinCfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
cipoPinCfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
cipoPinCfg.uIOMnum = AP3_SPI_IOM;
padMode(MISO, cipoPinCfg, &retval);
return (retval == AP3_OK);
}
#endif
This is basically the code found in the [OLA_IMU_Basics.ino example sketch. I’m creating two objects for the IMU – the first one using SPI for the in-built IMU and the second one using I2C for the external IMU. However, when I open the serial monitor, this is the output I’m getting:
Initialization of the in-built (SPI) sensor returned: All is well.
Initialization of the external (I2C) sensor returned: Data Underflow"
Trying again...
I also tried using just uploading the [OLA_IMU_Basics.ino example sketch and just made the following change on line 33:
// #define USE_SPI // Uncomment this to use SPI
Basically I tried using I2C for the built-in IMU instead of SPI. However, I’m still getting the same error:
Initialization of the sensor returned: Data Underflow
Could anybody point out why I2C is not working even for the built-in IMU? And if some changes make it work, would it be possible to make use of two IMUs using something similar to what I described above?](OpenLog_Artemis/Firmware/Test Sketches/OLA_IMU_Basics/OLA_IMU_Basics.ino at main · sparkfun/OpenLog_Artemis · GitHub)](OpenLog_Artemis/Firmware/Test Sketches/OLA_IMU_Basics/OLA_IMU_Basics.ino at main · sparkfun/OpenLog_Artemis · GitHub)