sparkfun / SparkFun_ICM-20948_ArduinoLibrary

Arduino support for ICM_20948 w/ portable C backbone
Other
160 stars 69 forks source link

wrong accelerometer scaling? #90

Closed camelator closed 2 years ago

camelator commented 2 years ago

I don't know how to submit a change, but maybe the following function is not correct. I think it should be 16384 instead of 16.384, 8192 instead of 8.192, etc...

float ICM_20948::getAccMG(int16_t axis_val) { switch (agmt.fss.a) { case 0: return (((float)axis_val) / 16.384); break; case 1: return (((float)axis_val) / 8.192); break; case 2: return (((float)axis_val) / 4.096); break; case 3: return (((float)axis_val) / 2.048); break; default: return 0; break; } }

then I not sure where it comes from but there is a gap between the mindset of this code and what we found in the imucal.ino code: Serial.print("Raw:"); Serial.print(int(accel_event.acceleration.x8192/9.8)); Serial.print(","); Serial.print(int(accel_event.acceleration.y8192/9.8)); Serial.print(","); Serial.print(int(accel_event.acceleration.z8192/9.8)); Serial.print(","); Serial.print(int(gyro_event.gyro.xAdafruit_SensorLab::DEGREES_PER_RADIAN16)); Serial.print(","); Serial.print(int(gyro_event.gyro.yAdafruit_SensorLab::DEGREES_PER_RADIAN16)); Serial.print(","); Serial.print(int(gyro_event.gyro.zAdafruit_SensorLab::DEGREES_PER_RADIAN16)); Serial.print(","); Serial.print(int(mag_event.magnetic.x10)); Serial.print(","); Serial.print(int(mag_event.magnetic.y10)); Serial.print(","); Serial.print(int(mag_event.magnetic.z10)); Serial.println("");

Please note in this code to convert imu to raw we have to multiply by scale and divide by gravity

so maybe to convert raw to imu we have to divide by scale and multiply by gravity instead of simply divide by scale ?????

PaulZC commented 2 years ago

Hi @camelator ,

Walking through this:

getAGMT requests and returns the latest accel, gyro, mag and temperature readings from the 20948. It calls ICM_20948_get_agmt to do that. ICM_20948_get_agmt reads 23 bytes from the 20948 register bank 0, starting with ACCEL_XOUT_H. So agmt ends up containing a faithful copy of the contents of the 20948 registers.

There is a note in the datasheet for ACCEL_XOUT_L which says "To convert the output of the accelerometer to acceleration measurement use the formula below: X_acceleration = ACCEL_XOUT/Accel_Sensitivity".

The Accel_Sensitivity is defined by ACCEL_FS (Accel Full Scale) which is set in the ACCEL_CONFIG register:

image

image

So the important things to note are that:

So, in 2g mode, we need to divide the accel reading by 16384 to get to g. But to get to milli-g we need to divide by 16.384.

accX calls getAccMG to convert the accel value into milli-g:

https://github.com/sparkfun/SparkFun_ICM-20948_ArduinoLibrary/blob/d5ae1eba1ecbf808fca9bff0b0b6dc4e571e947c/src/ICM_20948.cpp#L168-L171

When the accel is in 2g mode, agmt.fss.a is 0. To convert to milli-g we need to divide by 16.384 and, looking at the code, we do:

https://github.com/sparkfun/SparkFun_ICM-20948_ArduinoLibrary/blob/d5ae1eba1ecbf808fca9bff0b0b6dc4e571e947c/src/ICM_20948.cpp#L183-L188

To my eyes, the code looks correct. Are you getting g and milli-g mixed up?

In the Adafruit code, I'm guessing they have previously converted the accel reading into m/s^2 and then need to divide by 9.8 to convert back into g? I don't know. I've never delved into their code...

Please think more about this and let me know if you still think it is an issue.

Best wishes, Paul

camelator commented 2 years ago

I don't agree with you. if we have same version of the document, the picture you provide is from page 12. On page 12 "," separates thousands "." separates the decimal part of a number (you can see it in the number below the part you capture) => 16,384 means 16 384. And it is relevant with what is written on page 1 in the list of features. It is written "3-axis Accelerometer with programmable FSR of +/-2g,+/-4g,+/-8g,+/-16g" It means the entire value range covers 2g, 4g, 8g or 16g 16 bits means 32 768 positive and 32767 negative values it also means +2G and -2G 32 768 / 2 = 16 384 and not 16,384.

you also can see it by unit testing the UC with the function you list. Dividing by only 16,384 make getAccMG returns value higher than gravity without moving anything...

PaulZC commented 2 years ago

Hi @camelator ,

I still think you are getting g and milli-g mixed up. When I run the examples, I see accelerations due to gravity of approximately 1000. 1000 milli-g. 1000 milli-g = 1g.

Also, I think you have misunderstood the scaling:

Paul

camelator commented 2 years ago

Ha ok... Well, you are talking in mG instead of G. This is not verry common. I'll do the scaling by myself :) sorry for that