accelerometer-calibration.ino 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // This program can be used to get the offsets and scaling factors for the gyro and accelerometer. This cannot be done
  2. // automatically. The cube must be placed in six different orientations, corresponding to each axis facing up and down.
  3. // Calibration offsets should initially be set to zero. Use the methodology as described in Analog Devices AN-1057,
  4. // which may be found here: https://www.analog.com/en/app-notes/an-1057.html. In particular, equations 17 and 18.
  5. #include <Wire.h>
  6. #include <ICM20948_WE.h>
  7. #define ICM20948_ADDR 0x68
  8. TwoWire wirePort = TwoWire(0);
  9. ICM20948_WE myIMU = ICM20948_WE(&wirePort);
  10. void setup() {
  11. // Set up serial
  12. Serial.begin(921600);
  13. // Set up I2C on pins 47 (SDA) and 21 (SCL) at 400 kHz
  14. wirePort.begin(47, 21, 400000);
  15. // Initialize IMU
  16. if(!myIMU.init()){
  17. Serial.println("ICM20948 does not respond");
  18. }
  19. else{
  20. Serial.println("ICM20948 is connected");
  21. }
  22. // Set accelerometer and gyroscope ranges
  23. myIMU.setAccRange(ICM20948_ACC_RANGE_2G);
  24. myIMU.setGyrRange(ICM20948_GYRO_RANGE_2000);
  25. // Set digital low pass filter setting such that noise is minimized (lowest cut-off frequency)
  26. myIMU.setAccDLPF(ICM20948_DLPF_6);
  27. myIMU.setGyrDLPF(ICM20948_DLPF_6);
  28. // Disable sample rate divider
  29. myIMU.setAccSampleRateDivider(0);
  30. myIMU.setGyrSampleRateDivider(0);
  31. }
  32. unsigned long timer;
  33. xyzFloat acc, gyr;
  34. float ax, ay, az, gx, gy, gz;
  35. // Calibration offsets
  36. const float b_gyr_x = 0.74;
  37. const float b_gyr_y = 0.66;
  38. const float b_gyr_z = -0.45;
  39. // IMU accelerator offsets and gain
  40. const float b_acc_x = -6;
  41. const float b_acc_y = -215;
  42. const float b_acc_z = 161;
  43. const float f_acc_x = 1672.7;
  44. const float f_acc_y = 1673.3;
  45. const float f_acc_z = 1691.5;
  46. void loop() {
  47. // Start a timer
  48. timer = millis();
  49. // Measure 1000 samples and average them
  50. for(int i = 0; i < 1000; i++) {
  51. myIMU.readSensor();
  52. acc = myIMU.getAccRawValues();
  53. gyr = myIMU.getGyrValues();
  54. ax += acc.x / 1000;
  55. ay += acc.y / 1000;
  56. az += acc.z / 1000;
  57. gx += gyr.x / 1000;
  58. gy += gyr.y / 1000;
  59. gz += gyr.z / 1000;
  60. // Print raw and calibrated values in last cycle
  61. if(i == 999) {
  62. Serial.print("Raw: Acc: ");
  63. Serial.print(ax);
  64. Serial.print(", ");
  65. Serial.print(ay);
  66. Serial.print(", ");
  67. Serial.print(az);
  68. Serial.print(", ");
  69. Serial.print("gyr: ");
  70. Serial.print(gx);
  71. Serial.print(", ");
  72. Serial.print(gy);
  73. Serial.print(", ");
  74. Serial.println(gz);
  75. // Equation 19 in AD AN-1057 is used here
  76. Serial.print("Calibrated: Acc: ");
  77. Serial.print((ax - b_acc_x) / f_acc_x);
  78. Serial.print(", ");
  79. Serial.print((ay - b_acc_y) / f_acc_y);
  80. Serial.print(", ");
  81. Serial.print((az - b_acc_z) / f_acc_z);
  82. Serial.print(", ");
  83. Serial.print("gyr: ");
  84. Serial.print(gx - b_gyr_x);
  85. Serial.print(", ");
  86. Serial.print(gy - b_gyr_y);
  87. Serial.print(", ");
  88. Serial.println(gz - b_gyr_z);
  89. }
  90. }
  91. // Print how long it took to get 1000 measurements
  92. Serial.print("Took "); Serial.print(millis() - timer); Serial.println(" ms.");
  93. // Reset averages
  94. ax = 0;
  95. ay = 0;
  96. az = 0;
  97. gx = 0;
  98. gy = 0;
  99. gz = 0;
  100. }