Open laurentvm opened 5 years ago
I am using the internal offset registers to store gyro bias. I don;t use these for the accel since the LS bit is a temperature compensation bit that must be preserved and my attempts to do so have produced poor accel offet bias compensation. So I don;t use the accel offset bias registers and correct manually for accel offset bias.
Are you expecting the accel data to be exactly the same?
On Sun, Nov 11, 2018 at 3:59 AM laurentvm notifications@github.com wrote:
Hi Kris,
I'm using a MPU9250 mounted on a Freematics One + https://freematics.com/pages/products/freematics-one-plus/
And I would have 2 questions regarding the calibration of the accelerometer.
First, you calibrate and store the bias in the register. Why do you then substract the bias in the read function? I guess storing bias in the register is for the sensor to take into account the bias ( https://github.com/kriswiner/MPU9250/blob/master/MPU9250_MS5637_AHRS_t3.ino#L479 ).
Second, every time I run my code (using your functions), I get different accelero values while not changing the device at all.
Run 1: MEMS... BIAS 0.10 0.04 -0.03 [13715] MEMS{1}> -0.12 -0.12 0.87 acc(x/y/z): -0.220459/-0.162170/0.902649, gyro(x/y/z): -0.106812,0.122070,0.022888, temp: 331, ori (p/y/r): 13.677728,-128.688858,-10.231514. Run 2: MEMS... BIAS 0.10 0.04 -0.03 [12715] MEMS{1}> -0.13 -0.12 1.00 acc(x/y/z): -0.228394/-0.165344/1.028320, gyro(x/y/z): -0.167847,-0.122070,-0.015259, temp: 334, ori (p/y/r): 12.326733,-129.217880,-9.172193.
The first 3 values are:
Serial.print(" "); Serial.print((float)accelCount[0]aRes); Serial.print(" "); Serial.print((float)accelCount[1]aRes); Serial.print(" "); Serial.print((float)accelCount[2]*aRes); Serial.print(" ");
Then acc[0] = (float)accelCount[0]aRes - accelBias[0]; // get actual g value, this depends on scale being set acc[1] = (float)accelCount[1]aRes - accelBias[1]; acc[2] = (float)accelCount[2]*aRes - accelBias[2];
Any Idea? Comment ?
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/324, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qkXHQznkHwrO1rnDGKgBU4rspy4pks5uuBETgaJpZM4YYcsY .
Hi Kris,
So in this snippet of code, the writeByte should be removed???
// Construct the accelerometer biases for push to the hardware accelerometer bias registers. These registers contain
// factory trim values which must be added to the calculated accelerometer biases; on boot up these registers will hold
// non-zero values. In addition, bit 0 of the lower byte must be preserved since it is used for temperature
// compensation calculations. Accelerometer bias registers expect bias input as 2048 LSB per g, so that
// the accelerometer biases calculated above must be divided by 8.
int32_t accel_bias_reg[3] = {0, 0, 0}; // A place to hold the factory accelerometer trim biases
readBytes(XA_OFFSET_H, 2, &data[0]); // Read factory accelerometer trim values
accel_bias_reg[0] = (int32_t) (((int16_t)data[0] << 8) | data[1]);
readBytes(YA_OFFSET_H, 2, &data[0]);
accel_bias_reg[1] = (int32_t) (((int16_t)data[0] << 8) | data[1]);
readBytes(ZA_OFFSET_H, 2, &data[0]);
accel_bias_reg[2] = (int32_t) (((int16_t)data[0] << 8) | data[1]);
uint32_t mask = 1uL; // Define mask for temperature compensation bit 0 of lower byte of accelerometer bias registers
uint8_t mask_bit[3] = {0, 0, 0}; // Define array to hold mask bit for each accelerometer bias axis
for(ii = 0; ii < 3; ii++) {
if((accel_bias_reg[ii] & mask)) mask_bit[ii] = 0x01; // If temperature compensation bit is set, record that fact in mask_bit
}
// Construct total accelerometer bias, including calculated average accelerometer bias from above
accel_bias_reg[0] -= (accel_bias[0]/8); // Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale)
accel_bias_reg[1] -= (accel_bias[1]/8);
accel_bias_reg[2] -= (accel_bias[2]/8);
data[0] = (accel_bias_reg[0] >> 8) & 0xFF;
data[1] = (accel_bias_reg[0]) & 0xFF;
data[1] = data[1] | mask_bit[0]; // preserve temperature compensation bit when writing back to accelerometer bias registers
data[2] = (accel_bias_reg[1] >> 8) & 0xFF;
data[3] = (accel_bias_reg[1]) & 0xFF;
data[3] = data[3] | mask_bit[1]; // preserve temperature compensation bit when writing back to accelerometer bias registers
data[4] = (accel_bias_reg[2] >> 8) & 0xFF;
data[5] = (accel_bias_reg[2]) & 0xFF;
data[5] = data[5] | mask_bit[2]; // preserve temperature compensation bit when writing back to accelerometer bias registers
// Apparently this is not working for the acceleration biases in the MPU-9250
// Are we handling the temperature correction bit properly?
// Push accelerometer biases to hardware registers
writeByte(XA_OFFSET_H, data[0]);
writeByte(XA_OFFSET_L, data[1]);
writeByte(YA_OFFSET_H, data[2]);
writeByte(YA_OFFSET_L, data[3]);
writeByte(ZA_OFFSET_H, data[4]);
writeByte(ZA_OFFSET_L, data[5]);
// Output scaled accelerometer biases for display in the main program
accelBias[0] = (float)accel_bias[0]/(float)accelsensitivity;
accelBias[1] = (float)accel_bias[1]/(float)accelsensitivity;
accelBias[2] = (float)accel_bias[2]/(float)accelsensitivity;
Serial.print(" ");
Serial.print(accelBias[0]);
Serial.print(" ");
Serial.print(accelBias[1]);
Serial.print(" ");
Serial.print(accelBias[2]);
Serial.println(" ");
Concerning the accel values, yes after calibration I'm expecting to get something like 0,0,1 or quite close. For me, this values -0.12 -0.12 0.87 are not close enough. More than 10 % error is quite a lot no?
Also, the Bias is always the same which is a good thing. How can we have the same Bias and not the same measurement later?
Yes, it's because you are using the accel bias registers, I think.
On Sun, Nov 11, 2018 at 9:36 AM laurentvm notifications@github.com wrote:
Hi Kris,
So this snippet of code, writeByte should be removed???
// Construct the accelerometer biases for push to the hardware accelerometer bias registers. These registers contain // factory trim values which must be added to the calculated accelerometer biases; on boot up these registers will hold // non-zero values. In addition, bit 0 of the lower byte must be preserved since it is used for temperature // compensation calculations. Accelerometer bias registers expect bias input as 2048 LSB per g, so that // the accelerometer biases calculated above must be divided by 8.
int32_t accel_bias_reg[3] = {0, 0, 0}; // A place to hold the factory accelerometer trim biases readBytes(XA_OFFSET_H, 2, &data[0]); // Read factory accelerometer trim values accel_bias_reg[0] = (int32_t) (((int16_t)data[0] << 8) | data[1]); readBytes(YA_OFFSET_H, 2, &data[0]); accel_bias_reg[1] = (int32_t) (((int16_t)data[0] << 8) | data[1]); readBytes(ZA_OFFSET_H, 2, &data[0]); accel_bias_reg[2] = (int32_t) (((int16_t)data[0] << 8) | data[1]);
uint32_t mask = 1uL; // Define mask for temperature compensation bit 0 of lower byte of accelerometer bias registers uint8_t mask_bit[3] = {0, 0, 0}; // Define array to hold mask bit for each accelerometer bias axis
for(ii = 0; ii < 3; ii++) { if((accel_bias_reg[ii] & mask)) mask_bit[ii] = 0x01; // If temperature compensation bit is set, record that fact in mask_bit }
// Construct total accelerometer bias, including calculated average accelerometer bias from above accel_bias_reg[0] -= (accel_bias[0]/8); // Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale) accel_bias_reg[1] -= (accel_bias[1]/8); accel_bias_reg[2] -= (accel_bias[2]/8);
data[0] = (accel_bias_reg[0] >> 8) & 0xFF; data[1] = (accel_bias_reg[0]) & 0xFF; data[1] = data[1] | mask_bit[0]; // preserve temperature compensation bit when writing back to accelerometer bias registers data[2] = (accel_bias_reg[1] >> 8) & 0xFF; data[3] = (accel_bias_reg[1]) & 0xFF; data[3] = data[3] | mask_bit[1]; // preserve temperature compensation bit when writing back to accelerometer bias registers data[4] = (accel_bias_reg[2] >> 8) & 0xFF; data[5] = (accel_bias_reg[2]) & 0xFF; data[5] = data[5] | mask_bit[2]; // preserve temperature compensation bit when writing back to accelerometer bias registers
// Apparently this is not working for the acceleration biases in the MPU-9250 // Are we handling the temperature correction bit properly? // Push accelerometer biases to hardware registers writeByte(XA_OFFSET_H, data[0]); writeByte(XA_OFFSET_L, data[1]); writeByte(YA_OFFSET_H, data[2]); writeByte(YA_OFFSET_L, data[3]); writeByte(ZA_OFFSET_H, data[4]); writeByte(ZA_OFFSET_L, data[5]);
// Output scaled accelerometer biases for display in the main program accelBias[0] = (float)accel_bias[0]/(float)accelsensitivity; accelBias[1] = (float)accel_bias[1]/(float)accelsensitivity; accelBias[2] = (float)accel_bias[2]/(float)accelsensitivity;
Serial.print(" "); Serial.print(accelBias[0]); Serial.print(" "); Serial.print(accelBias[1]); Serial.print(" "); Serial.print(accelBias[2]); Serial.println(" ");
Concerning the accel values, yes after calibration I'm expecting to get something like 0,0,1 are quite close. For me, this values -0.12 -0.12 0.87 are not close enough. More than 10 % error is quite a lot no?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/324#issuecomment-437688978, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qsVCco4r4KplFSWt9RFrgUhJFkk4ks5uuGAOgaJpZM4YYcsY .
Great Kris,
Changing to get your latest code calibration corrected the issue. Thanks Great job!
Hi Kris,
I know where the bug is with the temperature compensation bit. The original code makes no attempt in actually adding back the preserved bit nor adjusting for the fact that the calculated accel_bias[] is actually one bit off. The raw accel offset register value needs to be right shifted by 1 bit before subtracting the calculated accel_bias. To yield the write back value, left shifted the result by one and OR the preserved masked bit.
Here is my python port of that portion. I am sure the subtraction, shifting and OR'ing can all be as oneliners in C. In fact, even in python, see the end of the comment.
mask = 0x01 # Define mask for temperature compensation bit 0 of lower byte of accelerometer bias registers
mask_bit = [0, 0, 0] # Define array to hold mask bit for each accelerometer bias axis
for ii in range(0,3):
if ((accel_bias_reg[ii] & mask)):
mask_bit[ii] = 0x01 # If temperature compensation bit is set, record that fact in mask_bit
print(mask, mask_bit)
# Construct total accelerometer bias, including calculated average accelerometer bias from above
print("Actual Accel Bias values...")
accel_bias_reg[0] >>= 1 # shift away bit0 before calculations
accel_bias_reg[1] >>= 1
accel_bias_reg[2] >>= 1
print(accel_bias_reg)
print("New Accel Bias values...")
accel_bias_reg[0] -= round(accel_bias[0]/8) # Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale)
accel_bias_reg[1] -= round(accel_bias[1]/8)
accel_bias_reg[2] -= round(accel_bias[2]/8)
print(accel_bias_reg)
# preserve temperature compensation bit when writing back to accelerometer bias registers
accel_bias_reg[0] = (accel_bias_reg[0] << 1) | mask_bit[0]
accel_bias_reg[1] = (accel_bias_reg[1] << 1) | mask_bit[1]
accel_bias_reg[2] = (accel_bias_reg[2] << 1) | mask_bit[2]
print("New Accel Bias register values...")
print(accel_bias_reg) `
BTW, thanks for this repo, I am new to IMU in general and this taught me a lot.
The above verbose subtraction and bit preservation can in fact be done all in one line by shifting accel_bias left instead:
accel_bias_reg[0] -= (round(accel_bias[0]/8) << 1) # ready to be written back
accel_bias_reg[1] -= (round(accel_bias[1]/8) << 1) # ready to be written back
accel_bias_reg[2] -= (round(accel_bias[2]/8) << 1) # ready to be written back
Hi Kris,
I'm using a MPU9250 mounted on a Freematics One + https://freematics.com/pages/products/freematics-one-plus/
And I would have 2 questions regarding the calibration of the accelerometer.
First, you calibrate and store the bias in the register. Why do you then substract the bias in the read function? I guess storing bias in the register is for the sensor to take into account the bias (https://github.com/kriswiner/MPU9250/blob/master/MPU9250_MS5637_AHRS_t3.ino#L479).
Second, every time I run my code (using your functions), I get different accelero values while not changing the device at all.
I do not always get 0 on x, y and 1 on the z axis.
The first 3 values are:
Any Idea? Comment ? I am calling read function every 100 ms using a task scheduler.