Increase sample rate (frequency) ICM 20948.

This is my code below and actually with the settings I have implemented, I should achieve a sample rate of 560 Hz according to the data sheet, but I am only recording an update rate of only 320 Hz… I have spent weeks on fixing it but it is still not working. Could anyone tell me what I am doing wrong? Thank you in advance :smiley: .

const int FIRMWARE_VERSION_MAJOR = 1;
const int FIRMWARE_VERSION_MINOR = 7;
// OLA Specifics:
const byte PIN_IMU_POWER = 27; // The Red SparkFun version of the OLA (V10) uses pin 27
//const byte PIN_IMU_POWER = 22; // The Black SparkX version of the OLA (X04) uses pin 22
const byte PIN_IMU_INT = 37;
const byte PIN_IMU_CHIP_SELECT = 44;
const byte PIN_PWR_LED = 29;
const byte PIN_STAT_LED = 19;
const byte PIN_TRIGGER = 11;
#define OLA_IDENTIFIER 0x117
#define HARDWARE_VERSION_MAJOR 1
#define HARDWARE_VERSION_MINOR 0

uint8_t count = 0;
uint8_t csum;
uint8_t imu_id = 1;

unsigned long start = micros();
uint32_t baudrate = 115200;



#define MISO 6
#include "ICM_20948.h"  // Click here to get the library: http://librarymanager/All#SparkFun_ICM_20948_IMU

#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.

#define WIRE_PORT Wire  // Your desired Wire port.      Used when "USE_SPI" is not defined
#define AD0_VAL   1     // 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

#ifdef USE_SPI
  ICM_20948_SPI myICM;  // If using SPI create an ICM_20948_SPI object
#else
  ICM_20948_I2C myICM;  // Otherwise create an ICM_20948_I2C object
#endif

// Some vars to control or respond to interrupts
volatile bool isrFired = false;
volatile bool sensorSleep = false;


void setup() {
  
  powerLEDOn(); // Turn the power LED on - if the hardware supports it
  pinMode(PIN_STAT_LED, OUTPUT);
  digitalWrite(PIN_STAT_LED, HIGH);

  Serial.begin(baudrate); //Default for initial debug messages if necessary
  Serial.println();

  
#ifdef USE_SPI
    SPI_PORT.begin();
#else
    WIRE_PORT.begin();
    WIRE_PORT.setClock(400000);
#endif
  
  enableCIPOpullUp(); // Enable CIPO pull-up on the OLA

  pinMode(PIN_IMU_INT, INPUT_PULLUP);   // Using a pullup b/c ICM-20948 Breakout board has an onboard pullup as well and we don't want them to compete
  attachInterrupt(digitalPinToInterrupt(PIN_IMU_INT), icmISR, FALLING); // Set up a falling interrupt

  //beginIMU();
  pinMode(PIN_IMU_POWER, OUTPUT);
  pinMode(PIN_IMU_CHIP_SELECT, OUTPUT);
  digitalWrite(PIN_IMU_CHIP_SELECT, HIGH); //Be sure IMU is deselected
  Serial.println("HELLO");

  //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(baudrate);
  while(!SERIAL_PORT){};

  bool initialized = false;
  while( !initialized ){

#ifdef USE_SPI
    myICM.begin( CS_PIN, SPI_PORT ); 
#else
    myICM.begin( WIRE_PORT, AD0_VAL );
#endif
    
  if( myICM.status != ICM_20948_Stat_Ok ){
  SERIAL_PORT.println( "Trying again..." );
  delay(500);
  }else{
   initialized = true;
  }
 }
  digitalWrite(PIN_STAT_LED, LOW); // Turn the STAT LED off now that everything is configured
  
  // Here we are doing a SW reset to make sure the device starts in a known state
  myICM.swReset( );
  if( myICM.status != ICM_20948_Stat_Ok){
    SERIAL_PORT.print(F("Software Reset returned: "));
    SERIAL_PORT.println(myICM.statusString());
  }
  delay(250);

  // Now wake the sensor up
  myICM.sleep( sensorSleep );
  myICM.lowPower( false );

  // The next few configuration functions accept a bit-mask of sensors for which the settings should be applied.

  // Set Gyro and Accelerometer to a particular sample mode
  // options: ICM_20948_Sample_Mode_Continuous
  //          ICM_20948_Sample_Mode_Cycled
  myICM.setSampleMode( (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), ICM_20948_Sample_Mode_Cycled );
  
  ICM_20948_smplrt_t mySmplrt;
  mySmplrt.a = 1;  // specify the accel sample rate to maximum: see Table 19 in datasheet DS-000189-ICM-20948-v1.3.pdf - as
  mySmplrt.g = 1;  // specify the gyro sample rate to maximum: see Table 17 in datasheet DS-000189-ICM-20948-v1.3.pdf  - as 
  myICM.setSampleRate( ICM_20948_Internal_Acc, mySmplrt );
  myICM.setSampleRate( ICM_20948_Internal_Gyr, mySmplrt );

  ICM_20948_dlpcfg_t myDLPcfg; 
  myDLPcfg.a = acc_d473bw_n499bw;
  myDLPcfg.g = gyr_d361bw4_n376bw5;
  myICM.setDLPFcfg( (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), myDLPcfg );
  /*
  if( myICM.status != ICM_20948_Stat_Ok){
    SERIAL_PORT.print(F("setDLPcfg returned: "));
    SERIAL_PORT.println(myICM.statusString());
  }
  */
  // Choose whether or not to use DLPF
  // Here we're also showing another way to access the status values, and that it is OK to supply individual sensor masks to these functions
  ICM_20948_Status_e accDLPEnableStat = myICM.enableDLPF( ICM_20948_Internal_Acc, true );
  ICM_20948_Status_e gyrDLPEnableStat = myICM.enableDLPF( ICM_20948_Internal_Gyr, true );

  
  myICM.cfgIntActiveLow(true);                      // Active low to be compatible with the breakout board's pullup resistor
  myICM.cfgIntOpenDrain(false);                     // Push-pull, though open-drain would also work thanks to the pull-up resistors on the breakout
  myICM.cfgIntLatch(true);                          // Latch the interrupt until cleared
  myICM.intEnableRawDataReady(true);                // enable interrupts on raw data ready

}


void loop() {


    
//  Check for a trigger event
  if( isrFired ){                       // If our isr flag is set then clear the interrupts on the ICM
    isrFired = false;
    getData(count);
    myICM.clearInterrupts();
  }
//   //Compute the time it took
//   unsigned long endtime = nanos();
//   Serial.println(endtime);
//   Serial.println(start);
//   double delta = 1000000/(double(endtime - start));
//   start = micros();
//   Serial.print("Sample rate = :");
//   
//   Serial.println(delta);
    
}


//Query each enabled sensor for its most recent data
void getData(uint8_t count)
{
  
  //count++;
  csum=0;
  uint16_t header = (0xFFFF);
  //Serial.write(0x0A);
  //Serial.write(imu_id);
  //Serial.write(count);
  uint16_t imu_id_count = imu_id | ((uint16_t)count)<<8;  //This combines the imu_id and the  counter to one 2 Byte value
  myICM.getAGMT(); //Update values
  //csum = (imu_id + count);
  uint16_t data[9]= {header, imu_id_count,(uint16_t)myICM.agmt.gyr.axes.x,(uint16_t)myICM.agmt.gyr.axes.y,(uint16_t)myICM.agmt.gyr.axes.z,(uint16_t)myICM.agmt.acc.axes.x,(uint16_t)myICM.agmt.acc.axes.y,(uint16_t)myICM.agmt.acc.axes.z, csum};
  byte *buf;
  buf = (byte *) data;

  for (int i = 0; i < 18 ; i++)
  {
    csum += *(buf+i);
    //Serial.println(buf[i]);
  }

  //Here the header is subtracted from csum... Because the header takes 2 Byte, we substract each byte value from csum
  csum = csum - 255; 
  csum = csum - 255;
  buf[16] = csum;
  Serial.write(buf,18);
  //Serial.println(buf[16]);
  //Serial.println(csum);
  //Serial.write(csum);
}


void imuPowerOn()
{
  pinMode(PIN_IMU_POWER, OUTPUT);
  digitalWrite(PIN_IMU_POWER, HIGH);
}
void imuPowerOff()
{
  pinMode(PIN_IMU_POWER, OUTPUT);
  digitalWrite(PIN_IMU_POWER, LOW);
}

void powerLEDOn()
{
#if(HARDWARE_VERSION_MAJOR >= 1)
  pinMode(PIN_PWR_LED, OUTPUT);
  digitalWrite(PIN_PWR_LED, HIGH); // Turn the Power LED on
#endif
}

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.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
  cipoPinCfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
  cipoPinCfg.uIOMnum = AP3_SPI_IOM;
  cipoPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K;
  padMode(MISO, cipoPinCfg, &retval);
  return (retval == AP3_OK);
}
//Trigger Pin ISR
void icmISR( void ){
  isrFired = true; 
  count++;                    // Can't use I2C within ISR on 328p, so just set a flag to know that data is available
}
void powerLEDOff()
{
#if(HARDWARE_VERSION_MAJOR >= 1)
  pinMode(PIN_PWR_LED, OUTPUT);
  digitalWrite(PIN_PWR_LED, LOW); // Turn the Power LED off
#endif
}

Perhaps create an issue here https://github.com/sparkfun/OpenLog_Artemis/issues where the engineers might be able to help out :slight_smile:

Hi @jamessukah,

Apologies for the slow reply. I have posted an answer on the OpenLog Artemis GitHub Issue:

https://github.com/sparkfun/OpenLog_Art … -959118556

Best wishes,

Paul