Hey there, I am currently working on a project, where I want to measure the vibration of an object using the ICM-20649 board from Adafruit. The problem I am currently running into is that I can only get up to roughly 230 Hz or 4.2 ms per dataset when transmitting even though the sensor should go higher (datasheet page 13).
Here is the code I am currently using to calibrate the sensor and print the data:
#include <Adafruit_ICM20649.h>
#include <Adafruit_ICM20X.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
// Adafruit_ICM20X icm;
Adafruit_ICM20649 icm;
Adafruit_Sensor *icm_temp, *icm_accel, *icm_gyro;
// For SPI mode, we need a CS pin
#define ICM_CS 10
// For software-SPI mode we need SCK/MOSI/MISO pins
#define ICM_SCK 13
#define ICM_MISO 12
#define ICM_MOSI 11
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t temp;
//for calibration
float a_mid_x, a_mid_y, a_mid_z;
float g_mid_x, g_mid_y, g_mid_z;
void setup(void) {
Serial.begin(230400);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens
Serial.println("Adafruit ICM20649 test!");
// Try to initialize!
if (!icm.begin_I2C()) {
// if (!icm.begin_SPI(ICM_CS)) {
// if (!icm.begin_SPI(ICM_CS, ICM_SCK, ICM_MISO, ICM_MOSI)) {
Serial.println("Failed to find ICM20649 chip");
while (1) {
delay(10);
}
}
Serial.println("ICM20649 Found!");
icm.setAccelRange(ICM20649_ACCEL_RANGE_4_G); // Set Accelerometer range: +-4G, +-8G, +-16G, +-32G
Serial.print("Accelerometer range set to: ");
switch (icm.getAccelRange()) {
case ICM20649_ACCEL_RANGE_4_G:
Serial.println("+-4G");
break;
case ICM20649_ACCEL_RANGE_8_G:
Serial.println("+-8G");
break;
case ICM20649_ACCEL_RANGE_16_G:
Serial.println("+-16G");
break;
case ICM20649_ACCEL_RANGE_30_G:
Serial.println("+-30G");
break;
}
icm.setGyroRange(ICM20649_GYRO_RANGE_500_DPS);
Serial.print("Gyro range set to: ");
switch (icm.getGyroRange()) {
case ICM20649_GYRO_RANGE_500_DPS:
Serial.println("500 degrees/s");
break;
case ICM20649_GYRO_RANGE_1000_DPS:
Serial.println("1000 degrees/s");
break;
case ICM20649_GYRO_RANGE_2000_DPS:
Serial.println("2000 degrees/s");
break;
case ICM20649_GYRO_RANGE_4000_DPS:
Serial.println("4000 degrees/s");
break;
}
// icm.setAccelRateDivisor(4095);
icm.setAccelRateDivisor(0);
uint16_t accel_divisor = icm.getAccelRateDivisor();
float accel_rate = 1125 / (1.0 + accel_divisor);
Serial.print("Accelerometer data rate divisor set to: ");
Serial.println(accel_divisor);
Serial.print("Accelerometer data rate (Hz) is approximately: ");
Serial.println(accel_rate);
icm.setGyroRateDivisor(0);
uint8_t gyro_divisor = icm.getGyroRateDivisor();
float gyro_rate = 1100 / (1.0 + gyro_divisor);
Serial.print("Gyro data rate divisor set to: ");
Serial.println(gyro_divisor);
Serial.print("Gyro data rate (Hz) is approximately: ");
Serial.println(gyro_rate);
Serial.println();
icm_temp = icm.getTemperatureSensor();
icm_temp->printSensorDetails();
icm_accel = icm.getAccelerometerSensor();
icm_accel->printSensorDetails();
icm_gyro = icm.getGyroSensor();
icm_gyro->printSensorDetails();
// calibration
Serial.println("Calibrating...");
// weird data after startup
delay(1000);
for (int i = 1; i <= 1000; i++){
icm.getEvent(&accel, &gyro, &temp);
a_mid_x = (a_mid_x * (i - 1) + accel.acceleration.x ) / i;
a_mid_y = (a_mid_y * (i - 1) + accel.acceleration.y ) / i;
a_mid_z = (a_mid_z * (i - 1) + accel.acceleration.z ) / i;
g_mid_x = (g_mid_x * (i - 1) + gyro.gyro.x ) / i;
g_mid_y = (g_mid_y * (i - 1) + gyro.gyro.y ) / i;
g_mid_z = (g_mid_z * (i - 1) + gyro.gyro.z ) / i;
}
}
void loop() {
/* Get a new normalized sensor event */
// icm.getEvent(&accel, &gyro, &temp);
icm_accel->getEvent(&accel);
// delay(5);
Serial.print(millis());Serial.print(",");
// Serial.print(temp.temperature); Serial.print(",");
Serial.print(accel.acceleration.x - a_mid_x);
Serial.print(",");
Serial.print(accel.acceleration.y - a_mid_y);
Serial.print(",");
Serial.print(accel.acceleration.z - a_mid_z - 9.81); // Gravity
// Serial.print(",");
// Serial.print(gyro.gyro.x - g_mid_x);
// Serial.print(","); Serial.print(gyro.gyro.y - g_mid_y);
// Serial.print(","); Serial.print(gyro.gyro.z - g_mid_z);
Serial.println();
}
I do not know whether this is a code or a sensor problem. Any help would be appreciated.
I have figured out, that there is a function in the Adafruit Library to change the register however i am unsure about how to use it and if I should use it.
There also seems to be a low-noise mode for the accelerometer, if anyone knows how t turn that on that would be helpful as well.