Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialization of the sensor returned: Data Underflow #7

Closed
limgm opened this issue Jul 9, 2019 · 18 comments
Closed

Initialization of the sensor returned: Data Underflow #7

limgm opened this issue Jul 9, 2019 · 18 comments

Comments

@limgm
Copy link

limgm commented Jul 9, 2019

Thank you for creating this useful library.

I have just bought a new set of SparkFun ICM-20948 and SparkFun Thing Plus - ESP32 WROOM, after successfully compiling and uploading the Example1_Basics, I got the error on the Serial Monitor:

Initialization of the sensor returned: Data Underflow
Trying again... 

Did I miss out anything?

Thank you for your help.

@oclyke
Copy link
Contributor

oclyke commented Jul 9, 2019

@limgm Thanks for reaching out! This question would fit better on the SparkFun forums because it is not necessarily an issue with the software. Here's a link to the Inertial Measurement Units subforum where you can (and should) continue this inquiry.

Please first search that forum to see if there are similar topics, and if there is not please make a new post. When you do it would be useful to know more details about your situation such as:

  1. The exact code you are running,
  2. How you have the Arduino IDE set up (i.e. which board definition are you using?)
  3. How is your ICM-20948 breakout board configured (e.g. have you soldered any jumpers together?)
  4. How is your wiring? Are you using a Qwiic cable or wiring individually? Do you have good contact?

From what I can see ("Initialization of the sensor returned: Data Underflow") I suspect I2C communications trouble. Perhaps wiring or using the wrong I2C address?

I'd be happy to keep helping you on the forums -- that way the information can be easily accessible to all SparkFun customers. If we end up finding out that this is caused by a problem with the library then we can move back here and fix it. Thanks!

@oclyke oclyke closed this as completed Jul 9, 2019
@limgm
Copy link
Author

limgm commented Jul 11, 2019

@oclyke Thank you for your suggestions, I tried to remove and reinstall the board definition for esp32 by espressif and now the sensor is able to output the data correctly.

Thanks for your help!

@EstevesDouglas
Copy link

I am having the same problem described.

Using the correct library and example code.

To use the I2C feature, do I keep the ICM-20948 breakout (original state without touching the jumpers) correct?

eeerror

@svenakis
Copy link

to make it work on an arduino NANO the AD0_VAL has to be 0. AD0_VAL = 1 does not work on an NANO:

#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

@EstevesDouglas
Copy link

thank you very much

I ended up also using the sparkfun esp32 thing plus

9DoF IMU Breakout // Sparkfun ESP32 Thing Plus
SLC >>> 22 SCL
SDA >>> 21 GPIO 21
GND >>> GND
VIN >>> 3v3

Just using the Qwiic cable didn't work

@svenakis
Copy link

svenakis commented Feb 3, 2021

This works to read both, the accel, gyro and calculates roll pitch ... temp
You have to comment out what you need
I use it with processing to visualize this values
Have fun
Sven

// Basic demo for accelerometer readings from Adafruit ICM20948

#include <Adafruit_ICM20X.h>
#include <Adafruit_ICM20948.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_ICM20948 icm;
uint16_t measurement_delay_us = 65535; // Delay between measurements for testing
// 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

float GyroErrorX, GyroErrorY, GyroErrorZ;
float AccErrorX, AccErrorY;
float GyroX, GyroY, GyroZ;
float AccX, AccY, AccZ;
float accAngleX, accAngleY;
unsigned long elapsedTime, currentTime, previousTime;
float gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;

int c = 0;

void setup(void) {

Serial.begin(9600);
//Serial.begin(115200);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens

//Serial.println("Adafruit ICM20948 test!");

// Try to initialize!
// i2c address of cjmcu-20948 board 9 axis accelerometer gyr temp
if (!icm.begin_I2C(0x68)) {
// if (!icm.begin_SPI(ICM_CS)) {
// if (!icm.begin_SPI(ICM_CS, ICM_SCK, ICM_MISO, ICM_MOSI)) {

Serial.println("Failed to find ICM20948 chip");
while (1) {
  delay(10);
  
}

}
//Serial.println("ICM20948 Found!");
icm.setAccelRange(ICM20948_ACCEL_RANGE_16_G);
//Serial.print("Accelerometer range set to: ");
switch (icm.getAccelRange()) {
case ICM20948_ACCEL_RANGE_2_G:
//Serial.println("+-2G");
break;
case ICM20948_ACCEL_RANGE_4_G:
//Serial.println("+-4G");
break;
case ICM20948_ACCEL_RANGE_8_G:
//Serial.println("+-8G");
break;
case ICM20948_ACCEL_RANGE_16_G:
//Serial.println("+-16G");
break;
}
//Serial.println("OK");

// icm.setGyroRange(ICM20948_GYRO_RANGE_2000_DPS);
//Serial.print("Gyro range set to: ");
switch (icm.getGyroRange()) {
case ICM20948_GYRO_RANGE_250_DPS:
//Serial.println("250 degrees/s");
break;
case ICM20948_GYRO_RANGE_500_DPS:
//Serial.println("500 degrees/s");
break;
case ICM20948_GYRO_RANGE_1000_DPS:
//Serial.println("1000 degrees/s");
break;
case ICM20948_GYRO_RANGE_2000_DPS:
//Serial.println("2000 degrees/s");
break;
}

// icm.setAccelRateDivisor(4095);
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(255);
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);

// icm.setMagDataRate(AK09916_MAG_DATARATE_10_HZ);
//Serial.print("Magnetometer data rate set to: ");
switch (icm.getMagDataRate()) {
case AK09916_MAG_DATARATE_SHUTDOWN:
//Serial.println("Shutdown");
break;
case AK09916_MAG_DATARATE_SINGLE:
//Serial.println("Single/One shot");
break;
case AK09916_MAG_DATARATE_10_HZ:
//Serial.println("10 Hz");
break;
case AK09916_MAG_DATARATE_20_HZ:
//Serial.println("20 Hz");
break;
case AK09916_MAG_DATARATE_50_HZ:
//Serial.println("50 Hz");
break;
case AK09916_MAG_DATARATE_100_HZ:
//Serial.println("100 Hz");
break;
}
Serial.println();

// to calculate IMU error
//calculate_IMU_error();
//return;
}

void calculate_IMU_error() {
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t mag;
sensors_event_t temp;
icm.getEvent(&accel, &gyro, &temp, &mag);

// We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
// Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
// Read accelerometer values 200 times
while (c < 200) {

AccX = accel.acceleration.x;
AccY = accel.acceleration.y;
AccZ = accel.acceleration.z;

// Sum all readings
AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
c++;

}
//Divide the sum by 200 to get the error value
AccErrorX = AccErrorX / 200;
AccErrorY = AccErrorY / 200;
c = 0;
// Read gyro values 200 times
while (c < 200) {

GyroX = gyro.gyro.x;
GyroY = gyro.gyro.y;
GyroZ = gyro.gyro.z;

// Sum all readings
GyroErrorX = GyroErrorX + (GyroX / 131.0);
GyroErrorY = GyroErrorY + (GyroY / 131.0);
GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
c++;

}
//Divide the sum by 200 to get the error value
GyroErrorX = GyroErrorX / 200;
GyroErrorY = GyroErrorY / 200;
GyroErrorZ = GyroErrorZ / 200;
// Print the error values on the Serial Monitor
Serial.print("AccErrorX: ");
Serial.println(AccErrorX);
Serial.print("AccErrorY: ");
Serial.println(AccErrorY);
Serial.print("GyroErrorX: ");
Serial.println(GyroErrorX);
Serial.print("GyroErrorY: ");
Serial.println(GyroErrorY);
Serial.print("GyroErrorZ: ");
Serial.println(GyroErrorZ);
}

//////////////////////////// loop ////////////////////////

void loop() {

// Get a new normalized sensor event
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t mag;
sensors_event_t temp;
icm.getEvent(&accel, &gyro, &temp, &mag);

AccX = accel.acceleration.x;
AccY = accel.acceleration.y;
AccZ = accel.acceleration.z;

// Sum all readings
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58;
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58;

// === Read gyroscope data === //
previousTime = currentTime; // Previous time is stored before the actual time read
currentTime = millis(); // Current time actual time read
elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds

// correct the gyro.gyro.x, y and z values
// take Gyro Error from IMU Error
GyroX = (gyro.gyro.x + 0.56); // GyroError x
GyroY = (gyro.gyro.y - 2 ); // GyroError y
GyroZ = (gyro.gyro.z + 0.79); // GyroError z
///Serial.print(GyroX);
//Serial.print(" ");
//Serial.print(GyroZ);
//Serial.print(" ");

// Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
// Fehler =???
//yaw = yaw + GyroZ * elapsedTime;
// Complementary filter - combine acceleromter and gyro angle values
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;

// Print the values on the serial monitor
Serial.print(roll);
Serial.print(" ");
Serial.print(pitch);
Serial.print(" ");
//Serial.println(yaw);
Serial.println(GyroZ);

//Serial.print(" roll: ");
//Serial.print(roll);
//Serial.println();
//Serial.print(" ");
//Serial.print(" pitch: ");
//Serial.print(pitch); // Serial.println(" ");

// Display the results (acceleration is measured in m/s^2)
//
//Serial.print("Accel_X:");
//Serial.print(int(accel.acceleration.x * 100));
//Serial.print(accel.acceleration.x);
//Serial.print(" ");
//Serial.print("Y:");
//Serial.print(int(accel.acceleration.y * 100));
//Serial.print(accel.acceleration.y);
//Serial.print(" ");
//Serial.print("Z:");
//Serial.print(int(accel.acceleration.z * 100));
//Serial.print(accel.acceleration.z);
//Serial.print(" ");
//Serial.println("m/s^2");
//Serial.print("Mag_X:");
//Serial.print(int(mag.magnetic.x * 100));
//Serial.print(mag.magnetic.x);
//Serial.print(" ");
//Serial.print("Y:");
//Serial.print(int(mag.magnetic.y * 100));
//Serial.print(mag.magnetic.y);
//Serial.print(" ");
//Serial.print("Z:");
//Serial.print(int(mag.magnetic.z * 100));
//Serial.print(mag.magnetic.z);
//Serial.print(" ");
//Serial.println("uT");

//Display the results (acceleration is measured in m/s^2)
//Serial.print("\t\tGyro X: ");
//Serial.print(int(gyro.gyro.x * 100));
//Serial.print(gyro.gyro.x);
//Serial.print(" ");
//Serial.print(" \tY: ");
//Serial.print(int(gyro.gyro.y * 100));
//Serial.print(gyro.gyro.y);
//Serial.print(" ");
//Serial.print(" \tZ: ");
//Serial.print(int(gyro.gyro.z * 100));
//Serial.print(gyro.gyro.z);
//Serial.print(" ");
//Serial.println(" radians/s ");

//Serial.println();

// Serial.print("Temperature");
// Serial.print(int(temp.temperature * 100));
//Serial.print(temp.temperature);
//Serial.print(" ");
// Serial.println("degC");

//Serial.println();

//delay(500);
delay(100);

// Serial.print(temp.temperature);
//
// Serial.print(",");
//
// Serial.print(accel.acceleration.x);
// Serial.print(","); Serial.print(accel.acceleration.y);
// Serial.print(","); Serial.print(accel.acceleration.z);
//
// Serial.print(",");
// Serial.print(gyro.gyro.x);
// Serial.print(","); Serial.print(gyro.gyro.y);
// Serial.print(","); Serial.print(gyro.gyro.z);
//
// Serial.print(",");
// Serial.print(mag.magnetic.x);
// Serial.print(","); Serial.print(mag.magnetic.y);
// Serial.print(","); Serial.print(mag.magnetic.z);

// Serial.println();
//
// delayMicroseconds(measurement_delay_us);
}

/*
*
void loop() {

// Get a new normalized sensor event
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t mag;
sensors_event_t temp;
icm.getEvent(&accel, &gyro, &temp, &mag);

Serial.print("\t\tTemperature ");
Serial.print(temp.temperature);
Serial.println(" deg C");

// Display the results (acceleration is measured in m/s^2)
//Serial.print("\t\tAccel_X: ");
Serial.print("\t\tAccel_X: ");
Serial.print(accel.acceleration.x);
Serial.print(" \tY: ");
Serial.print(accel.acceleration.y);
Serial.print(" \tZ: ");
Serial.print(accel.acceleration.z);
Serial.println(" m/s^2 ");

Serial.print("\t\tMag X: ");
Serial.print(mag.magnetic.x);
Serial.print(" \tY: ");
Serial.print(mag.magnetic.y);
Serial.print(" \tZ: ");
Serial.print(mag.magnetic.z);
Serial.println(" uT");

//Display the results (acceleration is measured in m/s^2)
Serial.print("\t\tGyro X: ");
Serial.print(gyro.gyro.x);
Serial.print(" \tY: ");
Serial.print(gyro.gyro.y);
Serial.print(" \tZ: ");
Serial.print(gyro.gyro.z);
Serial.println(" radians/s ");
Serial.println();

//delay(500);
delay(100);

// Serial.print(temp.temperature);
//
// Serial.print(",");
//
// Serial.print(accel.acceleration.x);
// Serial.print(","); Serial.print(accel.acceleration.y);
// Serial.print(","); Serial.print(accel.acceleration.z);
//
// Serial.print(",");
// Serial.print(gyro.gyro.x);
// Serial.print(","); Serial.print(gyro.gyro.y);
// Serial.print(","); Serial.print(gyro.gyro.z);
//
// Serial.print(",");
// Serial.print(mag.magnetic.x);
// Serial.print(","); Serial.print(mag.magnetic.y);
// Serial.print(","); Serial.print(mag.magnetic.z);

// Serial.println();
//
// delayMicroseconds(measurement_delay_us);
}
*/

@jonra1993
Copy link

the board definition for esp32 by espressif

Hello, @limgm I am facing the same similar issue on esp32. What you mean with "remove and reinstall the board definition for esp32"

@tvp14ss
Copy link

tvp14ss commented Aug 3, 2021

Hey, @jonra1993. Did you solve your problem? I am also having a similar issue on esp32.

@Fabryz
Copy link

Fabryz commented Nov 24, 2022

Same issue on Lilygo T-Display S3 (ESP32), I guess it will be just a cry in the void...

@PaulZC
Copy link
Contributor

PaulZC commented Nov 24, 2022

Please give us a few more details... Are you using I2C or SPI? Which 20948 board are you using? If you are using I2C, it could be pull-up related. The ICM-20948 works really well with ESP32, but you do need pull-ups on the I2C bus. And I don't see any on the T-Display schematic...

@Fabryz
Copy link

Fabryz commented Nov 24, 2022

@PaulZC

I have a "SparkFun 9DoF IMU Breakout - ICM-20948" connected to the device via Qwiic on I2C, I uploaded the basic example code on my device, but it keeps giving me errors:

22:49:09.008 -> ICM_20948::checkID: ICM_20948_check_id returned: Data Underflow
22:49:09.008 -> ICM_20948::startupDefault: checkID returned: Data Underflow
22:49:09.008 -> ICM_20948_I2C::begin: startupDefault returned: Data Underflow
22:49:09.008 -> Initialization of the sensor returned: Data Underflow
22:49:09.008 -> Trying again...

Some info about the T-Display S3:

@PaulZC
Copy link
Contributor

PaulZC commented Nov 24, 2022

OK. Thanks.

This is probably an I2C pin definition issue.

The ESP32S3 module defines the I2C pins as 8 and 9:

https://github.com/espressif/arduino-esp32/blob/93a7f4e0db2c189836f85c0a75a7fcd8fad838cd/variants/esp32s3/pins_arduino.h#L30

But LilyGO seem to use 17 and 18:

https://github.com/Xinyuan-LilyGO/T-Display-S3/blob/876badcbff8e5c9a09d3bb7672334c930b833247/example/factory/pin_config.h#L47

You will - I think - need to define a custom Wire port using the correct pin numbers.

I hope this helps,
Paul

@PaulZC
Copy link
Contributor

PaulZC commented Nov 25, 2022

Hi Fabrizio (@Fabryz ),

It might be as simple as changing line 43 from WIRE_PORT.begin(); to WIRE_PORT.begin(18, 17, (uint32_t)400000); . Please let me know if this works.

Best wishes,
Paul

@Fabryz
Copy link

Fabryz commented Nov 25, 2022

Hi @PaulZC thanks for your help, I've just learned that I can find some useful information just by giving a look at the headers files inside the libraries, this will be helpful to debug stuff in the future.

I've changed that line with the initialization on SDA and SCL pins, but nothing changed, I still have the same error.

@PaulZC
Copy link
Contributor

PaulZC commented Nov 25, 2022

Hi @Fabryz ,

OK. Thanks for the feedback.

Which board definition are you using? ESP32S3 Dev Module?

A logic analyzer would help you debug this. Just to make sure you see correct activity on the SDA and SCL pins.

Do you have a different I2C device you can try? Again that would help confirm you are using the correct port / pin definitions.

Best wishes,
Paul

@Fabryz
Copy link

Fabryz commented Nov 25, 2022

@PaulZC Yes, I'm using "ESP32S3 Dev Module" with all the settings suggested by the official docs for this device.

I don't have a logic analyzer, I'm just a beginner on this.

I also have a "SparkFun Qwiic Haptic Driver - DA7280", again I've already used its basic example, I've just tried to set the pins for SDA and SCL, here actually I don't even get any output on the serial monitor.

I've created a thread on sparkfun's forums for both sensors, but so far there were no answers, I will update with your suggestions, just to keep track also there for the posterity
https://forum.sparkfun.com/viewtopic.php?f=83&t=58663&p=237235#p237235

Thanks for your time

@Fabryz
Copy link

Fabryz commented Nov 26, 2022

@PaulZC I've managed to find the solution!

Thanks to this guy https://github.com/VolosR/TemperatureTDisplay/blob/main/TemperatureTDisplay.ino#L43

The correct settings are:

WIRE_PORT.begin(43, 44);

But why? As we saw here: #7 (comment)
They're actually the TX and RX pins for the ESP32 :/

@PaulZC
Copy link
Contributor

PaulZC commented Nov 26, 2022

Hi Fabrizio (@Fabryz ),

Excellent detective work!

This does all make sense... On the T-Display pinout diagram, they do show 43 and 44 next to the Qwiic connector:

image

And looking closely at the schematic, they have used U0RXD and U0TXD:

image

It's puzzling as I would have expected them to connect using 18 and 17 (I2C SDA and SCL) like they do on the breakout pins:

image

Anyway, problem solved! Glad that's working for you,
Paul

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants