Skip to content

Commit 0e4c037

Browse files
authored
Merge pull request #273 from RobertRFenichel/master
Add IMU_Zero example for MPU-6050 zero calibration
2 parents 35de59b + 9ee8ffa commit 0e4c037

File tree

2 files changed

+526
-0
lines changed

2 files changed

+526
-0
lines changed
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
// MPU6050 offset-finder, based on Jeff Rowberg's MPU6050_RAW
2+
// 2016-10-19 by Robert R. Fenichel ([email protected])
3+
4+
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
5+
// 10/7/2011 by Jeff Rowberg <[email protected]>
6+
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
7+
//
8+
// Changelog:
9+
// 2016-10-19 - initial release
10+
// 2013-05-08 - added multiple output formats
11+
// - added seamless Fastwire support
12+
// 2011-10-07 - initial release
13+
14+
/* ============================================
15+
I2Cdev device library code is placed under the MIT license
16+
Copyright (c) 2011 Jeff Rowberg
17+
18+
Permission is hereby granted, free of charge, to any person obtaining a copy
19+
of this software and associated documentation files (the "Software"), to deal
20+
in the Software without restriction, including without limitation the rights
21+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22+
copies of the Software, and to permit persons to whom the Software is
23+
furnished to do so, subject to the following conditions:
24+
25+
The above copyright notice and this permission notice shall be included in
26+
all copies or substantial portions of the Software.
27+
28+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34+
THE SOFTWARE.
35+
36+
Put the MPU6050 in a flat and horizontal surface.
37+
- Leave it operating for 5-10 minutes so temperature gets stabilized.
38+
- Run this program. A "----- done -----" line will indicate that it has done its best.
39+
- For each of the 6 offsets, you'll see 2 adjacent values to choose between, together
40+
with their respective IMU outputs. One of the choices may be a little better than
41+
the other.
42+
===============================================
43+
*/
44+
45+
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
46+
// for both classes must be in the include path of your project
47+
#include "I2Cdev.h"
48+
#include "MPU6050.h"
49+
50+
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
51+
// is used in I2Cdev.h
52+
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
53+
#include "Wire.h"
54+
#endif
55+
56+
// class default I2C address is 0x68
57+
// specific I2C addresses may be passed as a parameter here
58+
// AD0 low = 0x68 (default for InvenSense evaluation board)
59+
// AD0 high = 0x69
60+
MPU6050 accelgyro;
61+
//MPU6050 accelgyro(0x69); // <-- use for AD0 high
62+
63+
64+
const char LBRACKET = '[';
65+
const char RBRACKET = ']';
66+
const char COMMA = ',';
67+
68+
const int iAx = 0;
69+
const int iAy = 1;
70+
const int iAz = 2;
71+
const int iGx = 3;
72+
const int iGy = 4;
73+
const int iGz = 5;
74+
75+
const int N = 1000; // the bigger, the smoother (and slower)
76+
const int LinesBetweenHeaders = 5;
77+
int LowValue[6];
78+
int HighValue[6];
79+
int Smoothed[6];
80+
int LowOffset[6];
81+
int HighOffset[6];
82+
int Target[6];
83+
int LinesOut;
84+
85+
void ForceHeader()
86+
{ LinesOut = 99; }
87+
88+
void GetSmoothed()
89+
{ int RawValue[6];
90+
long Sums[6];
91+
for (int i = iAx; i <= iGz; i++)
92+
{ Sums[i] = 0; }
93+
94+
for (int i = 1; i <= N; i++)
95+
{ // get sums
96+
accelgyro.getMotion6(&RawValue[0], &RawValue[1], &RawValue[2],
97+
&RawValue[3], &RawValue[4], &RawValue[5]);
98+
for (int j = iAx; j <= iGz; j++)
99+
Sums[j] = Sums[j] + RawValue[j];
100+
} // get sums
101+
for (int i = iAx; i <= iGz; i++)
102+
{ Smoothed[i] = (Sums[i] + N/2) / N ; }
103+
} // GetSmoothed
104+
105+
void Initialize()
106+
{
107+
// join I2C bus (I2Cdev library doesn't do this automatically)
108+
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
109+
Wire.begin();
110+
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
111+
Fastwire::setup(400, true);
112+
#endif
113+
114+
Serial.begin(9600);
115+
116+
// initialize device
117+
Serial.println("Initializing I2C devices...");
118+
accelgyro.initialize();
119+
120+
// verify connection
121+
Serial.println("Testing device connections...");
122+
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
123+
} // Initialize
124+
125+
void SetOffsets(int TheOffsets[6])
126+
{ accelgyro.setXAccelOffset(TheOffsets [iAx]);
127+
accelgyro.setYAccelOffset(TheOffsets [iAy]);
128+
accelgyro.setZAccelOffset(TheOffsets [iAz]);
129+
accelgyro.setXGyroOffset (TheOffsets [iGx]);
130+
accelgyro.setYGyroOffset (TheOffsets [iGy]);
131+
accelgyro.setZGyroOffset (TheOffsets [iGz]);
132+
} // SetOffsets
133+
134+
void ShowProgress()
135+
{ if (LinesOut >= LinesBetweenHeaders)
136+
{ // show header
137+
Serial.println("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro");
138+
LinesOut = 0;
139+
} // show header
140+
for (int i = iAx; i <= iGz; i++)
141+
{ Serial.print(LBRACKET);
142+
Serial.print(LowOffset[i]),
143+
Serial.print(COMMA);
144+
Serial.print(HighOffset[i]);
145+
Serial.print("] --> [");
146+
Serial.print(LowValue[i]);
147+
Serial.print(COMMA);
148+
Serial.print(HighValue[i]);
149+
if (i == iGz)
150+
{ Serial.println(RBRACKET); }
151+
else
152+
{ Serial.print("]\t"); }
153+
}
154+
ForceHeader();
155+
} // ShowProgress
156+
157+
void PullBracketsOut()
158+
{ boolean Done = false;
159+
int NextLowOffset[6];
160+
int NextHighOffset[6];
161+
162+
SetOffsets(HighOffset);
163+
GetSmoothed();
164+
for (int i = iAx; i <= iGz; i++)
165+
{ HighValue[i] = Smoothed[i]; // needed for ShowProgress
166+
}
167+
168+
while (!Done)
169+
{ Done = true;
170+
SetOffsets(LowOffset);
171+
GetSmoothed();
172+
for (int i = iAx; i <= iGz; i++)
173+
{ // got low values
174+
LowValue[i] = Smoothed[i];
175+
if (LowValue[i] > Target[i])
176+
{ Done = false;
177+
NextLowOffset[i] = LowOffset[i] - 1000;
178+
}
179+
else
180+
{ NextLowOffset[i] = LowOffset[i]; }
181+
} // got low values
182+
ShowProgress();
183+
for (int i = iAx; i <= iGz; i++)
184+
{ LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done
185+
}
186+
} // keep going
187+
188+
Done = false;
189+
while (!Done)
190+
{ Done = true;
191+
SetOffsets(HighOffset);
192+
GetSmoothed();
193+
for (int i = iAx; i <= iGz; i++)
194+
{ // got high values
195+
HighValue[i] = Smoothed[i];
196+
if (HighValue[i] < Target[i])
197+
{ Done = false;
198+
NextHighOffset[i] = HighOffset[i] + 1000;
199+
}
200+
else
201+
{ NextHighOffset[i] = HighOffset[i]; }
202+
} // got high values
203+
ShowProgress();
204+
for (int i = iAx; i <= iGz; i++)
205+
{ HighOffset[i] = NextHighOffset[i]; // had to wait until ShowProgress done
206+
}
207+
} // keep going
208+
} // PullBracketOut
209+
210+
void setup()
211+
{ boolean StillWorking;
212+
int NewOffset[6];
213+
214+
Initialize();
215+
for (int i = iAx; i <= iGz; i++)
216+
{ // set targets and initial guesses
217+
Target[i] = 0; // must fix for ZAccel
218+
HighOffset[i] = 0;
219+
LowOffset[i] = 0;
220+
} // set targets and initial guesses
221+
Target[iAz] = 16384;
222+
223+
Serial.println("expanding:");
224+
ForceHeader();
225+
PullBracketsOut();
226+
227+
Serial.println("\nclosing in:");
228+
ForceHeader();
229+
StillWorking = true;
230+
while (StillWorking)
231+
{ StillWorking = false;
232+
for (int i = iAx; i <= iGz; i++)
233+
{ if (HighOffset[i] <= (LowOffset[i]+1))
234+
{ NewOffset[i] = LowOffset[i]; }
235+
else
236+
{ // binary search
237+
StillWorking = true;
238+
NewOffset[i] = (LowOffset[i] + HighOffset[i]) /2;
239+
} // binary search
240+
}
241+
SetOffsets(NewOffset);
242+
GetSmoothed();
243+
for (int i = iAx; i <= iGz; i++)
244+
{ // closing in
245+
if (Smoothed[i] > Target[i])
246+
{ // use lower half
247+
HighOffset[i] = NewOffset[i];
248+
HighValue[i] = Smoothed[i];
249+
} // use lower half
250+
else
251+
{ // use upper half
252+
LowOffset[i] = NewOffset[i];
253+
LowValue[i] = Smoothed[i];
254+
} // use upper half
255+
} // closing in
256+
ShowProgress();
257+
} // still working
258+
Serial.println("-------------- done --------------");
259+
} // setup
260+
261+
void loop()
262+
{
263+
} // loop

0 commit comments

Comments
 (0)