{"action":"created","issue":{"url":"https://api.github.com/repos/kriswiner/MPU9250/issues/323","repository_url":"https://api.github.com/repos/kriswiner/MPU9250","labels_url":"https://api.github.com/repos/kriswiner/MPU9250/issues/323/labels{/name}","comments_url":"https://api.github.com/repos/kriswiner/MPU9250/issues/323/comments","events_url":"https://api.github.com/repos/kriswiner/MPU9250/issues/323/events","html_url":"https://github.com/kriswiner/MPU9250/issues/323","id":379228114,"node_id":"MDU6SXNzdWUzNzkyMjgxMTQ=","number":323,"title":"MPU9250 Arduino Pro Mini calibration","user":{"login":"gojunnyo","id":18816265,"node_id":"MDQ6VXNlcjE4ODE2MjY1","avatar_url":"https://avatars2.githubusercontent.com/u/18816265?v=4","gravatar_id":"","url":"https://api.github.com/users/gojunnyo","html_url":"https://github.com/gojunnyo","followers_url":"https://api.github.com/users/gojunnyo/followers","following_url":"https://api.github.com/users/gojunnyo/following{/other_user}","gists_url":"https://api.github.com/users/gojunnyo/gists{/gist_id}","starred_url":"https://api.github.com/users/gojunnyo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gojunnyo/subscriptions","organizations_url":"https://api.github.com/users/gojunnyo/orgs","repos_url":"https://api.github.com/users/gojunnyo/repos","events_url":"https://api.github.com/users/gojunnyo/events{/privacy}","received_events_url":"https://api.github.com/users/gojunnyo/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":32,"created_at":"2018-11-09T16:21:45Z","updated_at":"2018-11-12T00:18:59Z","closed_at":null,"author_association":"NONE","body":"Hi Kris!\r\nI am honestly tired due to 5 days and night of straight browsing, reading and basically doing anything to calibrate my MPU9250, I have read the 0x73 \"issue\" and that my sensor is MPU9255, I am new to these sensors and knew basics in Arduino. I had read somewhere that MPU6050 code \"theoretically\" is the same with MPU9250 but without the magnetometer, so what I did is I used MPU6050 calibration sketches. Although it says MPU6050 connection failed, the sketch managed to spit out data which confuses me (it failed so it shouldn't continue but why did it? or it says it failed because I used MPU9250). The problem is, it takes literally forever to calibrate as if it doesn't want to calibrate at all. I tried modifying your MPU9250_AHRS sketch and got it working but I have no idea what to do with the data. From what I observed on the serial plotter, the graph seems back and forth; more like a triangle wave. And still, I have no idea what was happening, although I observed changes if I move the sensors (obviously). Any help is much appreciated!\r\n\r\nMPU6050 CALIBRATION SOURCE:\r\nhttp://wired.chillibasket.com/2015/01/calibrating-mpu6050/\r\n\r\n``\r\n#include \"I2Cdev.h\"\r\n#include \"MPU6050.h\"\r\n#include \"Wire.h\"\r\n\r\n///////////////////////////////////   CONFIGURATION   /////////////////////////////\r\n//Change this 3 variables if you want to fine tune the skecth to your needs.\r\nint buffersize=1000;     //Amount of readings used to average, make it higher to get more precision but sketch will be slower  (default:1000)\r\nint acel_deadzone=8;     //Acelerometer error allowed, make it lower to get more precision, but sketch may not converge  (default:8)\r\nint giro_deadzone=1;     //Giro error allowed, make it lower to get more precision, but sketch may not converge  (default:1)\r\n\r\n// default I2C address is 0x68\r\n// specific I2C addresses may be passed as a parameter here\r\n// AD0 low = 0x68 (default for InvenSense evaluation board)\r\n// AD0 high = 0x69\r\n//MPU6050 accelgyro;\r\nMPU6050 accelgyro(0x68); // <-- use for AD0 high\r\n\r\nint16_t ax, ay, az,gx, gy, gz;\r\n\r\nint mean_ax,mean_ay,mean_az,mean_gx,mean_gy,mean_gz,state=0;\r\nint ax_offset,ay_offset,az_offset,gx_offset,gy_offset,gz_offset;\r\n\r\n///////////////////////////////////   SETUP   ////////////////////////////////////\r\nvoid setup() {\r\n  // join I2C bus (I2Cdev library doesn't do this automatically)\r\n  Wire.begin();\r\n  // COMMENT NEXT LINE IF YOU ARE USING ARDUINO DUE\r\n  TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz). Leonardo measured 250kHz.\r\n\r\n  // initialize serial communication\r\n  Serial.begin(115200);\r\n\r\n  // initialize device\r\n  accelgyro.initialize();\r\n\r\n  // wait for ready\r\n  while (Serial.available() && Serial.read()); // empty buffer\r\n  while (!Serial.available()){\r\n    Serial.println(F(\"Send any character to start sketch.\\n\"));\r\n    delay(1500);\r\n  }                \r\n  while (Serial.available() && Serial.read()); // empty buffer again\r\n\r\n  // start message\r\n  Serial.println(\"\\nMPU6050 Calibration Sketch\");\r\n  delay(2000);\r\n  Serial.println(\"\\nYour MPU6050 should be placed in horizontal position, with package letters facing up. \\nDon't touch it until you see a finish message.\\n\");\r\n  delay(3000);\r\n  // verify connection\r\n  Serial.println(accelgyro.testConnection() ? \"MPU6050 connection successful\" : \"MPU6050 connection failed\");\r\n  delay(1000);\r\n  // reset offsets\r\n  accelgyro.setXAccelOffset(0);\r\n  accelgyro.setYAccelOffset(0);\r\n  accelgyro.setZAccelOffset(0);\r\n  accelgyro.setXGyroOffset(0);\r\n  accelgyro.setYGyroOffset(0);\r\n  accelgyro.setZGyroOffset(0);\r\n}\r\n\r\n///////////////////////////////////   LOOP   ////////////////////////////////////\r\nvoid loop() {\r\n  if (state==0){\r\n    Serial.println(\"\\nReading sensors for first time...\");\r\n    meansensors();\r\n    state++;\r\n    delay(1000);\r\n  }\r\n\r\n  if (state==1) {\r\n    Serial.println(\"\\nCalculating offsets...\");\r\n    calibration();\r\n    state++;\r\n    delay(1000);\r\n  }\r\n\r\n  if (state==2) {\r\n    meansensors();\r\n    Serial.println(\"\\nFINISHED!\");\r\n    Serial.print(\"\\nSensor readings with offsets:\\t\");\r\n    Serial.print(mean_ax); \r\n    Serial.print(\"\\t\");\r\n    Serial.print(mean_ay); \r\n    Serial.print(\"\\t\");\r\n    Serial.print(mean_az); \r\n    Serial.print(\"\\t\");\r\n    Serial.print(mean_gx); \r\n    Serial.print(\"\\t\");\r\n    Serial.print(mean_gy); \r\n    Serial.print(\"\\t\");\r\n    Serial.println(mean_gz);\r\n    Serial.print(\"Your offsets:\\t\");\r\n    Serial.print(ax_offset); \r\n    Serial.print(\"\\t\");\r\n    Serial.print(ay_offset); \r\n    Serial.print(\"\\t\");\r\n    Serial.print(az_offset); \r\n    Serial.print(\"\\t\");\r\n    Serial.print(gx_offset); \r\n    Serial.print(\"\\t\");\r\n    Serial.print(gy_offset); \r\n    Serial.print(\"\\t\");\r\n    Serial.println(gz_offset); \r\n    Serial.println(\"\\nData is printed as: acelX acelY acelZ giroX giroY giroZ\");\r\n    Serial.println(\"Check that your sensor readings are close to 0 0 16384 0 0 0\");\r\n    Serial.println(\"If calibration was succesful write down your offsets so you can set them in your projects using something similar to mpu.setXAccelOffset(youroffset)\");\r\n    while (1);\r\n  }\r\n}\r\n\r\n///////////////////////////////////   FUNCTIONS   ////////////////////////////////////\r\nvoid meansensors(){\r\n  long i=0,buff_ax=0,buff_ay=0,buff_az=0,buff_gx=0,buff_gy=0,buff_gz=0;\r\n\r\n  while (i<(buffersize+101)){\r\n    // read raw accel/gyro measurements from device\r\n    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);\r\n    \r\n    if (i>100 && i<=(buffersize+100)){ //First 100 measures are discarded\r\n      buff_ax=buff_ax+ax;\r\n      buff_ay=buff_ay+ay;\r\n      buff_az=buff_az+az;\r\n      buff_gx=buff_gx+gx;\r\n      buff_gy=buff_gy+gy;\r\n      buff_gz=buff_gz+gz;\r\n    }\r\n    if (i==(buffersize+100)){\r\n      mean_ax=buff_ax/buffersize;\r\n      mean_ay=buff_ay/buffersize;\r\n      mean_az=buff_az/buffersize;\r\n      mean_gx=buff_gx/buffersize;\r\n      mean_gy=buff_gy/buffersize;\r\n      mean_gz=buff_gz/buffersize;\r\n    }\r\n    i++;\r\n    delay(2); //Needed so we don't get repeated measures\r\n  }\r\n}\r\n\r\nvoid calibration(){\r\n  ax_offset=-mean_ax/8;\r\n  ay_offset=-mean_ay/8;\r\n  az_offset=(16384-mean_az)/8;\r\n\r\n  gx_offset=-mean_gx/4;\r\n  gy_offset=-mean_gy/4;\r\n  gz_offset=-mean_gz/4;\r\n  while (1){\r\n    int ready=0;\r\n    accelgyro.setXAccelOffset(ax_offset);\r\n    accelgyro.setYAccelOffset(ay_offset);\r\n    accelgyro.setZAccelOffset(az_offset);\r\n\r\n    accelgyro.setXGyroOffset(gx_offset);\r\n    accelgyro.setYGyroOffset(gy_offset);\r\n    accelgyro.setZGyroOffset(gz_offset);\r\n\r\n    meansensors();\r\n    Serial.println(\"...\");\r\n\r\n    if (abs(mean_ax)<=acel_deadzone) ready++;\r\n    else ax_offset=ax_offset-mean_ax/acel_deadzone;\r\n\r\n    if (abs(mean_ay)<=acel_deadzone) ready++;\r\n    else ay_offset=ay_offset-mean_ay/acel_deadzone;\r\n\r\n    if (abs(16384-mean_az)<=acel_deadzone) ready++;\r\n    else az_offset=az_offset+(16384-mean_az)/acel_deadzone;\r\n\r\n    if (abs(mean_gx)<=giro_deadzone) ready++;\r\n    else gx_offset=gx_offset-mean_gx/(giro_deadzone+1);\r\n\r\n    if (abs(mean_gy)<=giro_deadzone) ready++;\r\n    else gy_offset=gy_offset-mean_gy/(giro_deadzone+1);\r\n\r\n    if (abs(mean_gz)<=giro_deadzone) ready++;\r\n    else gz_offset=gz_offset-mean_gz/(giro_deadzone+1);\r\n\r\n    if (ready==6) break;\r\n  }\r\n}\r\n``\r\n\r\nI also tried Jeff Rowberg's MPU6050 Library - IMU_Zero Sketch and ran it for 30 minutes, no offset were shown on my serial monitor :'(\r\n\r\nIMU_Zero Sketch\r\n``\r\n#include \"I2Cdev.h\"\r\n#include \"MPU6050.h\"\r\n\r\n// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation\r\n// is used in I2Cdev.h\r\n#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE\r\n    #include \"Wire.h\"\r\n#endif\r\n\r\n// class default I2C address is 0x68\r\n// specific I2C addresses may be passed as a parameter here\r\n// AD0 low = 0x68 (default for InvenSense evaluation board)\r\n// AD0 high = 0x69\r\nMPU6050 accelgyro;\r\n//MPU6050 accelgyro(0x69); // <-- use for AD0 high\r\n\r\n\r\nconst char LBRACKET = '[';\r\nconst char RBRACKET = ']';\r\nconst char COMMA    = ',';\r\nconst char BLANK    = ' ';\r\nconst char PERIOD   = '.';\r\n\r\nconst int iAx = 0;\r\nconst int iAy = 1;\r\nconst int iAz = 2;\r\nconst int iGx = 3;\r\nconst int iGy = 4;\r\nconst int iGz = 5;\r\n\r\nconst int usDelay = 3150;   // empirical, to hold sampling to 200 Hz\r\nconst int NFast =  1000;    // the bigger, the better (but slower)\r\nconst int NSlow = 10000;    // ..\r\nconst int LinesBetweenHeaders = 5;\r\n      int LowValue[6];\r\n      int HighValue[6];\r\n      int Smoothed[6];\r\n      int LowOffset[6];\r\n      int HighOffset[6];\r\n      int Target[6];\r\n      int LinesOut;\r\n      int N;\r\n      \r\nvoid ForceHeader()\r\n  { LinesOut = 99; }\r\n    \r\nvoid GetSmoothed()\r\n  { int16_t RawValue[6];\r\n    int i;\r\n    long Sums[6];\r\n    for (i = iAx; i <= iGz; i++)\r\n      { Sums[i] = 0; }\r\n//    unsigned long Start = micros();\r\n\r\n    for (i = 1; i <= N; i++)\r\n      { // get sums\r\n        accelgyro.getMotion6(&RawValue[iAx], &RawValue[iAy], &RawValue[iAz], \r\n                             &RawValue[iGx], &RawValue[iGy], &RawValue[iGz]);\r\n        if ((i % 500) == 0)\r\n          Serial.print(PERIOD);\r\n        delayMicroseconds(usDelay);\r\n        for (int j = iAx; j <= iGz; j++)\r\n          Sums[j] = Sums[j] + RawValue[j];\r\n      } // get sums\r\n//    unsigned long usForN = micros() - Start;\r\n//    Serial.print(\" reading at \");\r\n//    Serial.print(1000000/((usForN+N/2)/N));\r\n//    Serial.println(\" Hz\");\r\n    for (i = iAx; i <= iGz; i++)\r\n      { Smoothed[i] = (Sums[i] + N/2) / N ; }\r\n  } // GetSmoothed\r\n\r\nvoid Initialize()\r\n  {\r\n    // join I2C bus (I2Cdev library doesn't do this automatically)\r\n    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE\r\n        Wire.begin();\r\n    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE\r\n        Fastwire::setup(400, true);\r\n    #endif\r\n\r\n    Serial.begin(9600);\r\n\r\n    // initialize device\r\n    Serial.println(\"Initializing I2C devices...\");\r\n    accelgyro.initialize();\r\n\r\n    // verify connection\r\n    Serial.println(\"Testing device connections...\");\r\n    Serial.println(accelgyro.testConnection() ? \"MPU6050 connection successful\" : \"MPU6050 connection failed\");\r\n  } // Initialize\r\n\r\nvoid SetOffsets(int TheOffsets[6])\r\n  { accelgyro.setXAccelOffset(TheOffsets [iAx]);\r\n    accelgyro.setYAccelOffset(TheOffsets [iAy]);\r\n    accelgyro.setZAccelOffset(TheOffsets [iAz]);\r\n    accelgyro.setXGyroOffset (TheOffsets [iGx]);\r\n    accelgyro.setYGyroOffset (TheOffsets [iGy]);\r\n    accelgyro.setZGyroOffset (TheOffsets [iGz]);\r\n  } // SetOffsets\r\n\r\nvoid ShowProgress()\r\n  { if (LinesOut >= LinesBetweenHeaders)\r\n      { // show header\r\n        Serial.println(\"\\tXAccel\\t\\t\\tYAccel\\t\\t\\t\\tZAccel\\t\\t\\tXGyro\\t\\t\\tYGyro\\t\\t\\tZGyro\");\r\n        LinesOut = 0;\r\n      } // show header\r\n    Serial.print(BLANK);\r\n    for (int i = iAx; i <= iGz; i++)\r\n      { Serial.print(LBRACKET);\r\n        Serial.print(LowOffset[i]),\r\n        Serial.print(COMMA);\r\n        Serial.print(HighOffset[i]);\r\n        Serial.print(\"] --> [\");\r\n        Serial.print(LowValue[i]);\r\n        Serial.print(COMMA);\r\n        Serial.print(HighValue[i]);\r\n        if (i == iGz)\r\n          { Serial.println(RBRACKET); }\r\n        else\r\n          { Serial.print(\"]\\t\"); }\r\n      }\r\n    LinesOut++;\r\n  } // ShowProgress\r\n\r\nvoid PullBracketsIn()\r\n  { boolean AllBracketsNarrow;\r\n    boolean StillWorking;\r\n    int NewOffset[6];\r\n  \r\n    Serial.println(\"\\nclosing in:\");\r\n    AllBracketsNarrow = false;\r\n    ForceHeader();\r\n    StillWorking = true;\r\n    while (StillWorking) \r\n      { StillWorking = false;\r\n        if (AllBracketsNarrow && (N == NFast))\r\n          { SetAveraging(NSlow); }\r\n        else\r\n          { AllBracketsNarrow = true; }// tentative\r\n        for (int i = iAx; i <= iGz; i++)\r\n          { if (HighOffset[i] <= (LowOffset[i]+1))\r\n              { NewOffset[i] = LowOffset[i]; }\r\n            else\r\n              { // binary search\r\n                StillWorking = true;\r\n                NewOffset[i] = (LowOffset[i] + HighOffset[i]) / 2;\r\n                if (HighOffset[i] > (LowOffset[i] + 10))\r\n                  { AllBracketsNarrow = false; }\r\n              } // binary search\r\n          }\r\n        SetOffsets(NewOffset);\r\n        GetSmoothed();\r\n        for (int i = iAx; i <= iGz; i++)\r\n          { // closing in\r\n            if (Smoothed[i] > Target[i])\r\n              { // use lower half\r\n                HighOffset[i] = NewOffset[i];\r\n                HighValue[i] = Smoothed[i];\r\n              } // use lower half\r\n            else\r\n              { // use upper half\r\n                LowOffset[i] = NewOffset[i];\r\n                LowValue[i] = Smoothed[i];\r\n              } // use upper half\r\n          } // closing in\r\n        ShowProgress();\r\n      } // still working\r\n   \r\n  } // PullBracketsIn\r\n\r\nvoid PullBracketsOut()\r\n  { boolean Done = false;\r\n    int NextLowOffset[6];\r\n    int NextHighOffset[6];\r\n\r\n    Serial.println(\"expanding:\");\r\n    ForceHeader();\r\n \r\n    while (!Done)\r\n      { Done = true;\r\n        SetOffsets(LowOffset);\r\n        GetSmoothed();\r\n        for (int i = iAx; i <= iGz; i++)\r\n          { // got low values\r\n            LowValue[i] = Smoothed[i];\r\n            if (LowValue[i] >= Target[i])\r\n              { Done = false;\r\n                NextLowOffset[i] = LowOffset[i] - 1000;\r\n              }\r\n            else\r\n              { NextLowOffset[i] = LowOffset[i]; }\r\n          } // got low values\r\n      \r\n        SetOffsets(HighOffset);\r\n        GetSmoothed();\r\n        for (int i = iAx; i <= iGz; i++)\r\n          { // got high values\r\n            HighValue[i] = Smoothed[i];\r\n            if (HighValue[i] <= Target[i])\r\n              { Done = false;\r\n                NextHighOffset[i] = HighOffset[i] + 1000;\r\n              }\r\n            else\r\n              { NextHighOffset[i] = HighOffset[i]; }\r\n          } // got high values\r\n        ShowProgress();\r\n        for (int i = iAx; i <= iGz; i++)\r\n          { LowOffset[i] = NextLowOffset[i];   // had to wait until ShowProgress done\r\n            HighOffset[i] = NextHighOffset[i]; // ..\r\n          }\r\n     } // keep going\r\n  } // PullBracketsOut\r\n\r\nvoid SetAveraging(int NewN)\r\n  { N = NewN;\r\n    Serial.print(\"averaging \");\r\n    Serial.print(N);\r\n    Serial.println(\" readings each time\");\r\n   } // SetAveraging\r\n\r\nvoid setup()\r\n  { Initialize();\r\n    for (int i = iAx; i <= iGz; i++)\r\n      { // set targets and initial guesses\r\n        Target[i] = 0; // must fix for ZAccel \r\n        HighOffset[i] = 0;\r\n        LowOffset[i] = 0;\r\n      } // set targets and initial guesses\r\n    Target[iAz] = 16384;\r\n    SetAveraging(NFast);\r\n    \r\n    PullBracketsOut();\r\n    PullBracketsIn();\r\n    \r\n    Serial.println(\"-------------- done --------------\");\r\n  } // setup\r\n \r\nvoid loop()\r\n  {\r\n  } // loop\r\n``\r\n"},"comment":{"url":"https://api.github.com/repos/kriswiner/MPU9250/issues/comments/437719514","html_url":"https://github.com/kriswiner/MPU9250/issues/323#issuecomment-437719514","issue_url":"https://api.github.com/repos/kriswiner/MPU9250/issues/323","id":437719514,"node_id":"MDEyOklzc3VlQ29tbWVudDQzNzcxOTUxNA==","user":{"login":"gojunnyo","id":18816265,"node_id":"MDQ6VXNlcjE4ODE2MjY1","avatar_url":"https://avatars2.githubusercontent.com/u/18816265?v=4","gravatar_id":"","url":"https://api.github.com/users/gojunnyo","html_url":"https://github.com/gojunnyo","followers_url":"https://api.github.com/users/gojunnyo/followers","following_url":"https://api.github.com/users/gojunnyo/following{/other_user}","gists_url":"https://api.github.com/users/gojunnyo/gists{/gist_id}","starred_url":"https://api.github.com/users/gojunnyo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gojunnyo/subscriptions","organizations_url":"https://api.github.com/users/gojunnyo/orgs","repos_url":"https://api.github.com/users/gojunnyo/repos","events_url":"https://api.github.com/users/gojunnyo/events{/privacy}","received_events_url":"https://api.github.com/users/gojunnyo/received_events","type":"User","site_admin":false},"created_at":"2018-11-12T00:18:59Z","updated_at":"2018-11-12T00:18:59Z","author_association":"NONE","body":"Lastly, any tips on how to make the sensor know absolute horizon?\r\nIn which, I do not have to do runtime calibration.\r\n\r\nI might have missed it from the sketch, but it would be a great help if you'll give me a hint on how to achieve it."}}
{"actor":{"display_login":"gojunnyo"}}