{"id":11361,"date":"2021-04-05T21:58:41","date_gmt":"2021-04-05T21:58:41","guid":{"rendered":"https:\/\/wolles-elektronikkiste.de\/mpu9250-9-axis-sensor-module-part-1"},"modified":"2024-10-29T13:56:55","modified_gmt":"2024-10-29T13:56:55","slug":"mpu9250-9-axis-sensor-module-part-1","status":"publish","type":"post","link":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1","title":{"rendered":"MPU9250 &#8211; 9-Axis Sensor Module &#8211; Part 1"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">About this post<\/h2>\n\n<p>In previous articles, I have introduced the accelerometers <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/mma7361-analog-accelerometer\" target=\"_blank\" rel=\"noopener\">MMA7361<\/a> and <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/adxl345-the-universal-accelerometer-part-1\" target=\"_blank\" rel=\"noopener\">ADXL345.<\/a> I also reported on the <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/mpu6050-accelerometer-and-gyroscope\" target=\"_blank\" rel=\"noopener\">MPU6050<\/a> gyroscope and accelerometer sensor module. This time I would like to focus on the 9-axis sensor module MPU9250. It combines four functions:<\/p>\r\n<ul>\r\n \t<li>Gyroscope<\/li>\r\n \t<li>Accelerometer<\/li>\r\n \t<li>Magnetometer<\/li>\r\n \t<li>Thermometer<\/li>\r\n<\/ul>\r\n<p>During my research, I was looking for a library that on the one hand implemented the many functions and setting parameters of the MPU9250, but on the other hand can be operated without having to go into the depths of the data sheet. Since I didn&#8217;t really find what I was looking for, I wrote a library myself, which I will present in this article.<\/p>\r\n<p><strong>Update 25th of March 2022<\/strong>: The library now also works with the MPU6500, which is basically an MPU9250 without a magnetometer. Moreover I have implemented SPI control. Example sketches are attached to the library.  <\/p>\r\n<p><strong>Update 30th of July: I am getting more and more comments and e-mails that the magnetometer does not work and\/or that the sketches report back &#8220;MPU9250\/MPU6500 does not respond&#8221;. Please read <a href=\"https:\/\/github.com\/wollewald\/MPU9250_WE#readme\" target=\"_blank\" rel=\"noopener\">readme<\/a> on GitHub and check your module with the example sketch MPU9250_who_am_I.<\/strong><\/p>\n\n<p>Because of the size of the topic, I have decided to split the post. In this first part, I deal with:<\/p>\r\n<ul>\r\n<li>Features \/ Technical specifications of the MPU9250<\/li>\r\n<li>Wiring<\/li>\r\n<li>Introduction to my library MPU9250:\r\n<ul>\r\n<li>Getting the basic data:\r\n<ul>\r\n<li>Acceleration<\/li>\r\n<li>Gyroscope<\/li>\r\n<li>Magnetometer<\/li>\r\n<li>All basic data and temperature<\/li>\r\n<\/ul>\r\n<\/li>\r\n<li>Calibration<\/li>\r\n<\/ul>\r\n<\/li>\r\n<\/ul>\r\n<p>In <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-2\" target=\"_blank\" rel=\"noopener\">part 2<\/a>, I will continue the introduction to my library:<\/p>\r\n<ul>\r\n<li>Measuring angles<\/li>\r\n<li>Set up interrupts<\/li>\r\n<li>Low-power \/ cycle mode<\/li>\r\n<li>Using the FIFO<\/li>\r\n<\/ul>\r\n\n<h2 class=\"wp-block-heading\">Features and specifications of the MPU9250<\/h2>\n\n<p>How a gyroscope and an accelerometer works, I have already described in my <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/mpu6050-accelerometer-and-gyroscope\" target=\"_blank\" rel=\"noopener\">article about the MPU6050<\/a>. The magnetometer works based on the Hall effect. You find a good animation <a href=\"https:\/\/www.youtube.com\/watch?v=Scpi91e1JKc\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\r\n\n<p>The MPU9250 is actually a discontinued model. On the <a href=\"https:\/\/invensense.tdk.com\/products\/motion-tracking\/9-axis\/mpu-9250\/\" target=\"_blank\" rel=\"noopener\">manufacturer&#8217;s pages<\/a> it is marked as &#8220;EoL&#8221; (End of Life). But I assume that you can buy the modules for a few more years. On Amazon and eBay, the selection of stores that offer the MPU9250 is huge. The successor model is the ICM-20948, which I will report on soon. However, the modules are still relatively expensive (\u20ac15). You can get the MPU9250 for half the price.<\/p>\r\n<div class=\"wp-block-image\">\n<figure class=\"alignright size-large is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/MPU9250-701x1024.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"701\" height=\"1024\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/MPU9250-701x1024.jpg\" alt=\"\" class=\"wp-image-11304\" style=\"width:351px;height:512px\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/MPU9250-701x1024.jpg 701w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/MPU9250-205x300.jpg 205w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/MPU9250-768x1122.jpg 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/MPU9250-1052x1536.jpg 1052w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/MPU9250.jpg 1079w\" sizes=\"auto, (max-width: 701px) 100vw, 701px\" \/><\/a><\/figure>\n<\/div>\n<p>Since the MPU9250 combines four sensors, a complete list of technical data would be beyond the scope. The essential key data is:<\/p>\r\n<ul>\r\n<li><strong>Power supply<\/strong>: 3.0 &#8211; 5.0 volts (module)\r\n<ul>\r\n<li>for the actual IC it is 2.4 &#8211; 3.6 volts<\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><strong>Communication via I2C<\/strong>, the addresses are:\r\n<ul>\r\n<li>AD0 unconnected or LOW: 0x68<\/li>\r\n<li>AD0 to HIGH: 0x69<\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><strong>Communication via SPI<\/strong><\/li>\r\n<li><strong>Gyroscope<\/strong>\r\n<ul>\r\n<li>Ranges: +\/-250, +\/-500, +\/-1000, +\/-2000 \u00b0\/s<\/li>\r\n<li>Data rate: 3.91 &#8211; 32000 Hz<\/li>\r\n<li>Resolution: 16 bits<\/li>\r\n<li>Power consumption: 3.2 mA (normal mode) \/ 8 \u00b5A (sleep mode)<\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><strong>Accelerometer<\/strong>:\r\n<ul>\r\n<li>Ranges: +\/- 2, +\/-4, +\/-8, +\/-16 g<\/li>\r\n<li>Data rate: 0.24 Hz (in cycle mode) to 4000 Hz<\/li>\r\n<li>Resolution: 16 bits<\/li>\r\n<li>Power consumption: 450 \u00b5A (normal mode) \/ 8.4 \u00b5A in low-power mode (0.98 Hz cycle) \/ 19.8 \u00b5A in low-power mode (31.25 Hz cycle)<\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><strong>Magnetometer<\/strong>:\r\n<ul>\r\n<li>Measuring range: +\/- 4800 \u00b5T<\/li>\r\n<li>Data rate: 8 Hz or 100 Hz<\/li>\r\n<li>Resolution: 14 or 16 bits (I only implemented 16 bit resolution)<\/li>\r\n<li>Power consumption: 280 A at 8 Hz data rate<\/li>\r\n<\/ul>\r\n<\/li>\r\n<li><strong>FIFO<\/strong> (First in, first out) data storage: 512 bytes = 256 single values = 85 x,y,z data triple<\/li>\r\n<li><strong>Interrupts<\/strong>: FIFO Overflow, data ready and wake-on-motion (acceleration) interrupt<\/li>\r\n<li>Integrated <strong>thermometer <br><\/strong> <\/li>\r\n<\/ul>\r\n<p>The MPU9250 allows you to control five additional sensors via I2C in a subnet, to store and read the data in the MPU9250, or store it in the FIFO. But I have only implemented that for the magnetometer.<\/p>\r\n<p>Further information can be found in the <a href=\"https:\/\/invensense.tdk.com\/wp-content\/uploads\/2015\/02\/PS-MPU-9250A-01-v1.1.pdf\" target=\"_blank\" rel=\"noopener\">technical data sheet<\/a>, in the <a href=\"https:\/\/cdn.sparkfun.com\/assets\/learn_tutorials\/5\/5\/0\/MPU-9250-Register-Map.pdf\" target=\"_blank\" rel=\"noopener\">register map<\/a> and in the data sheet of the magnetic sensor <a href=\"https:\/\/download.mikroe.com\/documents\/datasheets\/ak8963c-datasheet.pdf\" target=\"_blank\" rel=\"noopener\">AK8963<\/a>.<\/p>\r\n\n<h2 class=\"wp-block-heading\">Control of the MPU9250 with Arduino UNO &amp; Co<\/h2>\n\n<h3 class=\"wp-block-heading\">Wiring<\/h3>\n\n<p>Pull-up resistors for the I2C lines are not needed. You may need to use a level converter or voltage divider for the inputs and outputs if you are using a 5V board. Even though the MPU9250 module has a voltage regulator for VCC, this does not necessarily mean that the other inputs are also regulated down.<\/p>\r\n\r\n<p>The connection of the interrupt pin is needed for some example ketches. Since I set it active-high, I don&#8217;t need a voltage regulator for it.\u00a0<\/p>\r\n<ul>\r\n<li>EDA\/ECL are the I2C connectors for external sensors &#8211; I have not (yet) implemented this option as mentioned<\/li>\r\n<li>AD0: connected to HIGH, the I2C address is changed from 0x68 to 0x69<\/li>\r\n<li>NCS: Chip select for SPI operation (not implemented in my library)<\/li>\r\n<li>FSYNC (&#8220;frame synchronization&#8221;): can be used as an interrupt input for other sensors &#8211; I have not (yet) implemented this.<\/li>\r\n<\/ul>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/03\/MPU9250__I2C_Arduino_Wiring-1024x397.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"397\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/03\/MPU9250__I2C_Arduino_Wiring-1024x397.png\" alt=\"Connecting the MPU9250 to an Arduino Nano\" class=\"wp-image-14048\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/03\/MPU9250__I2C_Arduino_Wiring-1024x397.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/03\/MPU9250__I2C_Arduino_Wiring-300x116.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/03\/MPU9250__I2C_Arduino_Wiring-768x298.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/03\/MPU9250__I2C_Arduino_Wiring-1320x512.png 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/03\/MPU9250__I2C_Arduino_Wiring.png 1350w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Connecting the MPU9250 to an Arduino Nano<\/figcaption><\/figure>\n\n<h3 class=\"wp-block-heading\">Libraries for the MPU9250<\/h3>\n\n<p>There are a number of libraries available for the MPU9250. Check out the Arduino Library Manager or GitHub for this. As I mentioned at the beginning, I wasn&#8217;t happy with the available libraries, but that&#8217;s a matter of taste.<\/p>\r\n<p>You can download my library MPU9250_WE <a href=\"https:\/\/github.com\/wollewald\/MPU9250_WE\" target=\"_blank\" rel=\"noopener\">here<\/a> from GitHub or you install it directly via the Arduino IDE Library Manager.<\/p>\r\n<p>The problem with the MPU9250 is that it has an incredible amount of setting options due to its 4 sensors plus I2C subnet control. In such cases, &nbsp;the question arises whether everything that is possible should be implemented. And although I didn&#8217;t, my library contains fifty-nine public features. To explain the use of these functions, I have attached eleven example sketches.<\/p>\r\n\n<h2 class=\"wp-block-heading\">Introduction to the library MPU9250_WE <\/h2>\n\n<h3 class=\"wp-block-heading\">The basic data<\/h3>\n\n<p>To get to know the library and the MPU9250, I recommend trying out the sketches in the order used here. We start with the basic data for acceleration, gyroscope, magnetometer and thermometer. This is a pretty dry read! If I were you, I would get an MPU9250 and try out the example sketches in parallel in practice.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Example sketch 1: MPU9250_acceleration_data<\/h4>\n\n<p>This first sketch is the one I go into most intensively. Many functions are also used in other sketches.<\/p>\r\n<p>First, a comment about the data format &#8220;xyzFloat&#8221;. This is a structure (struct) consisting of three float values. I use xyzFloat for all data that has an x, y, and z component. <\/p>\r\n\n<div class=\"scroll-paragraph-long\">\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"MPU9250_acceleration_data.ino\" data-enlighter-title=\"MPU9250_acceleration_data.ino\">#include &lt;MPU9250_WE.h&gt;\r\n#include &lt;Wire.h&gt;\r\n#define MPU9250_ADDR 0x68\r\n\r\n\/* There are several ways to create your MPU9250 object:\r\n * MPU9250_WE myMPU9250 = MPU9250_WE()              -&gt; uses Wire \/ I2C Address = 0x68\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(MPU9250_ADDR)  -&gt; uses Wire \/ MPU9250_ADDR\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(&amp;wire2)        -&gt; uses the TwoWire object wire2 \/ MPU9250_ADDR\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(&amp;wire2, MPU9250_ADDR) -&gt; all together\r\n * Successfully tested with two I2C busses on an ESP32\r\n *\/\r\nMPU9250_WE myMPU9250 = MPU9250_WE(MPU9250_ADDR);\r\n\r\nvoid setup() {\r\n  Serial.begin(115200);\r\n  Wire.begin();\r\n  if(!myMPU9250.init()){\r\n    Serial.println(\"MPU9250 does not respond\");\r\n  }\r\n  else{\r\n    Serial.println(\"MPU9250 is connected\");\r\n  }\r\n  \r\n  \/* The slope of the curve of acceleration vs measured values fits quite well to the theoretical \r\n   * values, e.g. 16384 units\/g in the +\/- 2g range. But the starting point, if you position the \r\n   * MPU9250 flat, is not necessarily 0g\/0g\/1g for x\/y\/z. The autoOffset function measures offset \r\n   * values. It assumes your MPU9250 is positioned flat with its x,y-plane. The more you deviate \r\n   * from this, the less accurate will be your results.\r\n   * The function also measures the offset of the gyroscope data. The gyroscope offset does not   \r\n   * depend on the positioning.\r\n   * This function needs to be called at the beginning since it can overwrite your settings!\r\n   *\/\r\n  Serial.println(\"Position you MPU9250 flat and don't move it - calibrating...\");\r\n  delay(1000);\r\n  myMPU9250.autoOffsets();\r\n  Serial.println(\"Done!\");\r\n  \r\n  \/*  This is a more accurate method for calibration. You have to determine the minimum and maximum \r\n   *  raw acceleration values of the axes determined in the range +\/- 2 g. \r\n   *  You call the function as follows: setAccOffsets(xMin,xMax,yMin,yMax,zMin,zMax);\r\n   *  Use either autoOffset or setAccOffsets, not both.\r\n   *\/\r\n  \/\/myMPU9250.setAccOffsets(-14240.0, 18220.0, -17280.0, 15590.0, -20930.0, 12080.0);\r\n\r\n  \/*  Sample rate divider divides the output rate of the gyroscope and accelerometer.\r\n   *  Sample rate = Internal sample rate \/ (1 + divider) \r\n   *  It can only be applied if the corresponding DLPF is enabled and 0&lt;DLPF&lt;7!\r\n   *  Divider is a number 0...255\r\n   *\/\r\n  myMPU9250.setSampleRateDivider(5);\r\n  \r\n  \/*  MPU9250_ACC_RANGE_2G      2 g   \r\n   *  MPU9250_ACC_RANGE_4G      4 g\r\n   *  MPU9250_ACC_RANGE_8G      8 g   \r\n   *  MPU9250_ACC_RANGE_16G    16 g\r\n   *\/\r\n  myMPU9250.setAccRange(MPU9250_ACC_RANGE_2G);\r\n\r\n  \/*  Enable\/disable the digital low pass filter for the accelerometer \r\n   *  If disabled the the bandwidth is 1.13 kHz, delay is 0.75 ms, output rate is 4 kHz\r\n   *\/\r\n  myMPU9250.enableAccDLPF(true);\r\n\r\n  \/*  Digital low pass filter (DLPF) for the accelerometer, if enabled \r\n   *  MPU9250_DPLF_0, MPU9250_DPLF_2, ...... MPU9250_DPLF_7 \r\n   *   DLPF     Bandwidth [Hz]      Delay [ms]    Output rate [kHz]\r\n   *     0           460               1.94           1\r\n   *     1           184               5.80           1\r\n   *     2            92               7.80           1\r\n   *     3            41              11.80           1\r\n   *     4            20              19.80           1\r\n   *     5            10              35.70           1\r\n   *     6             5              66.96           1\r\n   *     7           460               1.94           1\r\n   *\/\r\n  myMPU9250.setAccDLPF(MPU9250_DLPF_6);\r\n\r\n  \/*  Set accelerometer output data rate in low power mode (cycle enabled)\r\n   *   MPU9250_LP_ACC_ODR_0_24          0.24 Hz\r\n   *   MPU9250_LP_ACC_ODR_0_49          0.49 Hz\r\n   *   MPU9250_LP_ACC_ODR_0_98          0.98 Hz\r\n   *   MPU9250_LP_ACC_ODR_1_95          1.95 Hz\r\n   *   MPU9250_LP_ACC_ODR_3_91          3.91 Hz\r\n   *   MPU9250_LP_ACC_ODR_7_81          7.81 Hz\r\n   *   MPU9250_LP_ACC_ODR_15_63        15.63 Hz\r\n   *   MPU9250_LP_ACC_ODR_31_25        31.25 Hz\r\n   *   MPU9250_LP_ACC_ODR_62_5         62.5 Hz\r\n   *   MPU9250_LP_ACC_ODR_125         125 Hz\r\n   *   MPU9250_LP_ACC_ODR_250         250 Hz\r\n   *   MPU9250_LP_ACC_ODR_500         500 Hz\r\n   *\/\r\n  \/\/myMPU9250.setLowPowerAccDataRate(MPU9250_LP_ACC_ODR_500);\r\n\r\n  \/* sleep() sends the MPU9250 to sleep or wakes it up. \r\n   * Please note that the gyroscope needs 35 milliseconds to wake up.\r\n   *\/\r\n  \/\/myMPU9250.sleep(true);\r\n\r\n \/* If cycle is set, and standby or sleep are not set, the module will cycle between\r\n   *  sleep and taking a sample at a rate determined by setLowPowerAccDataRate().\r\n   *\/\r\n  \/\/myMPU9250.enableCycle(true);\r\n\r\n  \/* You can enable or disable the axes for gyrometer and\/or accelerometer measurements.\r\n   * By default all axes are enabled. Parameters are:  \r\n   * MPU9250_ENABLE_XYZ  \/\/all axes are enabled (default)\r\n   * MPU9250_ENABLE_XY0  \/\/ X, Y enabled, Z disabled\r\n   * MPU9250_ENABLE_X0Z   \r\n   * MPU9250_ENABLE_X00\r\n   * MPU9250_ENABLE_0YZ\r\n   * MPU9250_ENABLE_0Y0\r\n   * MPU9250_ENABLE_00Z\r\n   * MPU9250_ENABLE_000  \/\/ all axes disabled\r\n   *\/\r\n  \/\/myMPU9250.enableAccAxes(MPU9250_ENABLE_XYZ);\r\n  \r\n}\r\n\r\nvoid loop() {\r\n  xyzFloat accRaw = myMPU9250.getAccRawValues();\r\n  xyzFloat accCorrRaw = myMPU9250.getCorrectedAccRawValues();\r\n  xyzFloat gValue = myMPU9250.getGValues();\r\n  float resultantG = myMPU9250.getResultantG(gValue);\r\n  \r\n  Serial.println(\"Raw acceleration values (x,y,z):\");\r\n  Serial.print(accRaw.x);\r\n  Serial.print(\"   \");\r\n  Serial.print(accRaw.y);\r\n  Serial.print(\"   \");\r\n  Serial.println(accRaw.z);\r\n\r\n  Serial.println(\"Corrected ('calibrated') acceleration values (x,y,z):\");\r\n  Serial.print(accCorrRaw.x);\r\n  Serial.print(\"   \");\r\n  Serial.print(accCorrRaw.y);\r\n  Serial.print(\"   \");\r\n  Serial.println(accCorrRaw.z);\r\n\r\n  Serial.println(\"g values (x,y,z):\");\r\n  Serial.print(gValue.x);\r\n  Serial.print(\"   \");\r\n  Serial.print(gValue.y);\r\n  Serial.print(\"   \");\r\n  Serial.println(gValue.z);\r\n\r\n  Serial.print(\"Resultant g: \");\r\n  Serial.println(resultantG); \/\/ should always be 1 g if only gravity acts on the sensor.\r\n  Serial.println();\r\n  \r\n  delay(1000);\r\n}<\/pre>\r\n<p>&nbsp;<\/p>\r\n<\/div>\r\n\n<h5 class=\"wp-block-heading\">Initialization and offsets<\/h5>\n\n<p>The function <code>init()<\/code> first performs a reset of the MPU9250 and writes default values to some registers. <code>init()<\/code> returns <code>false<\/code> if the MPU9250 should not be responsive, otherwise it returns <code>true<\/code>.<\/p>\r\n<p>If the MPU9250 is positioned flat, i.e. horizontal x,y-plane, only the acceleration due to gravity acts on it. Accordingly, the g-values for the x- and y-axis should be zero and for the z-axis it should be one. However, these values are more or less shifted. The function <code>autoOffset()<\/code> measures the offset values which are subtracted from future measured values. The slope, on the other hand, had not to be corrected for the modules I tried out. In the 2g range, the difference between the minimum and maximum raw acceleration values was quite close to the expected 2 x 16348 (i.e. 2x 10<sup>15<\/sup>). <code>autoOffset()<\/code> only works reliably if:<\/p>\r\n<ul>\r\n<li>the module is positioned flat with its x,y-plane,<\/li>\r\n<li>is not moved, and<\/li>\r\n<li>the function is called as the first function in the setup (because it changes some settings)<\/li>\r\n<\/ul>\r\n<p>Alternatively, you can use the <code>setAccOffsets()<\/code> function. It results in less good zero values, but is more accurate with larger angles, and you don&#8217;t have to position the module when the program starts.<\/p>\r\n\n<h5 class=\"wp-block-heading\">Other settings<\/h5>\n\n<p>The function <code>setAccRange()<\/code> sets the range for the acceleration measurements.<\/p>\r\n\n<p>To control the data rate, you use the function <code>setSampleRateDivider(divider)<\/code>.<\/p>\r\n\n<p><\/p>\r\n<p><p class=\"ql-center-displayed-equation\" style=\"line-height: 41px;\"><span class=\"ql-right-eqno\"> &nbsp; <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/ql-cache\/quicklatex.com-72b7e7a426b482335e6c5496c54aef80_l3.png\" height=\"41\" width=\"243\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#91; &#92;&#116;&#101;&#120;&#116;&#123;&#100;&#97;&#116;&#97;&#32;&#114;&#97;&#116;&#101;&#125;&#61;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#49;&#43;&#100;&#105;&#118;&#105;&#100;&#101;&#114;&#125;&#92;&#59;&#91;&#92;&#116;&#101;&#120;&#116;&#123;&#107;&#72;&#122;&#125;&#93; &#92;&#93;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p><\/p>\r\n\n<p>However, this only works if the digital low pass filter (DLPF) is activated and its mode is 1 to 6. The DLPF is (de-)activated done with <code>enableAccDLPF(true\/false)<\/code>. You choose the level with <code>setAccDLPF()<\/code>. The higher the level, the lower the noise. Only level 7 does not fit in this series in this respect. The disadvantage of high smoothing is reduced response time. This means that when the acceleration changes, it takes a while for the MPU9250 to output the correct value. Details of these delay times can be found in the sketch.<\/p>\r\n<p>With <code>sleep()<\/code>, you put the accelerometer and the gyroscope to sleep. However, this does not apply to the magnetometer, as it has a certain life of its own (not sure if this translates well).<\/p>\r\n<p>If you don&#8217;t want to activate all axes, you can use <code>enableAccAxes()<\/code> to change the default setting. The parameters are explained in the sketch.<\/p>\r\n<p>I explain the functions <code>setCycle()<\/code> and <code>setLowPowerAccDataRate()<\/code> elsewhere.<\/p>\r\n\n<h5 class=\"wp-block-heading\">The results<\/h5>\n\n<p>You can query the measurement results with the following functions:<\/p>\r\n<ul>\r\n<li><code>getAccRawValues()<\/code> returns the raw values of acceleration as they are in the MPU9250 data registers<\/li>\r\n<li><code>getCorrectedAccRawValues()<\/code> reads the raw values and corrects them by the offsets<\/li>\r\n<li><code>getGValues()<\/code> returns the acceleration values in g (based on the corrected raw data)<\/li>\r\n<li><code>getResultantG(gValue)<\/code> calculates the resulting acceleration from a g-value triple, i.e. the magnitude of the sum of the three vectors<\/li>\r\n<\/ul>\r\n\n<p><p class=\"ql-center-displayed-equation\" style=\"line-height: 23px;\"><span class=\"ql-right-eqno\"> &nbsp; <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/ql-cache\/quicklatex.com-a87dbed8bcf2105182e1391b0b949ae7_l3.png\" height=\"23\" width=\"500\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#91; &#92;&#116;&#101;&#120;&#116;&#123;&#114;&#101;&#115;&#117;&#108;&#116;&#97;&#110;&#116;&#71;&#125;&#61;&#92;&#115;&#113;&#114;&#116;&#123;&#40;&#103;&#86;&#97;&#108;&#117;&#101;&#46;&#120;&#41;&#94;&#50;&#43;&#40;&#103;&#86;&#97;&#108;&#117;&#101;&#46;&#121;&#41;&#94;&#50;&#43;&#40;&#103;&#86;&#97;&#108;&#117;&#101;&#46;&#122;&#41;&#94;&#50;&#125;&#32;&#92;&#59;&#92;&#59;&#92;&#116;&#101;&#120;&#116;&#123;&#91;&#103;&#93;&#125; &#92;&#93;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p><\/p>\r\n\n<p>If only gravity affects the MPU9250, the resultant should always be 1. With the resultant function, you can easily measure accelerations without having to align the movement to an axis. Simply subtract 1 to exclude the earth&#8217;s acceleration.<\/p>\r\n\n<h5 class=\"wp-block-heading\">The output of MPU9250_acceleration_data.ino<\/h5>\n\n<p>And this is the output on the serial monitor:<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_acceleration-data.png\"><img loading=\"lazy\" decoding=\"async\" width=\"769\" height=\"375\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_acceleration-data.png\" alt=\"MPU9250 Example sketch: Output of MPU9250_acceleration_data.ino\" class=\"wp-image-11317\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_acceleration-data.png 769w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_acceleration-data-300x146.png 300w\" sizes=\"auto, (max-width: 769px) 100vw, 769px\" \/><\/a><figcaption class=\"wp-element-caption\">Output of MPU9250_acceleration_data.ino<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Example sketch 2: MPU9250_gyroscope_data<\/h4>\n\n<p>Since you already know some functions, the explanation of the gyroscope functions can be much shorter.<\/p>\r\n\n<div class=\"scroll-paragraph-long\">\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"MPU9250_gyroscope_data.ino\">#include &lt;MPU9250_WE.h&gt;\r\n#include &lt;Wire.h&gt;\r\n#define MPU9250_ADDR 0x68\r\n\r\n\/* There are several ways to create your MPU9250 object:\r\n * MPU9250_WE myMPU9250 = MPU9250_WE()              -&gt; uses Wire \/ I2C Address = 0x68\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(MPU9250_ADDR)  -&gt; uses Wire \/ MPU9250_ADDR\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(&amp;wire2)        -&gt; uses the TwoWire object wire2 \/ MPU9250_ADDR\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(&amp;wire2, MPU9250_ADDR) -&gt; all together\r\n * Successfully tested with two I2C busses on an ESP32\r\n *\/\r\nMPU9250_WE myMPU9250 = MPU9250_WE(MPU9250_ADDR);\r\n\r\nvoid setup() {\r\n  Serial.begin(115200);\r\n  Wire.begin();\r\n  if(!myMPU9250.init()){\r\n    Serial.println(\"MPU9250 does not respond\");\r\n  }\r\n  else{\r\n    Serial.println(\"MPU9250 is connected\");\r\n  }\r\n\r\n  \/* The slope of the curve of acceleration vs measured values fits quite well to the theoretical \r\n   * values, e.g. 16384 units\/g in the +\/- 2g range. But the starting point, if you position the \r\n   * MPU9250 flat, is not necessarily 0g\/0g\/1g for x\/y\/z. The autoOffset function measures offset \r\n   * values. It assumes your MPU9250 is positioned flat with its x,y-plane. The more you deviate \r\n   * from this, the less accurate will be your results.\r\n   * The function also measures the offset of the gyroscope data. The gyroscope offset does not   \r\n   * depend on the positioning.\r\n   * This function needs to be called at the beginning since it can overwrite your settings!\r\n   *\/\r\n  Serial.println(\"Position you MPU9250 flat and don't move it - calibrating...\");\r\n  delay(1000);\r\n  myMPU9250.autoOffsets();\r\n  Serial.println(\"Done!\");\r\n  \r\n  \/*  The gyroscope data is not zero, even if you don't move the MPU9250. \r\n   *  To start at zero, you can apply offset values. These are the gyroscope raw values you obtain\r\n   *  using the +\/- 250 degrees\/s range. \r\n   *  Use either autoOffset or setGyrOffsets, not both.\r\n   *\/\r\n  \/\/myMPU9250.setGyrOffsets(45.0, 145.0, -105.0);\r\n  \r\n \/*  You can enable or disable the digital low pass filter (DLPF). If you disable the DLPF, you \r\n   *  need to select the bandwidth, which can be either 8800 or 3600 Hz. 8800 Hz has a shorter delay,\r\n   *  but higher noise level. If DLPF is disabled, the output rate is 32 kHz.\r\n   *  MPU9250_BW_WO_DLPF_3600 \r\n   *  MPU9250_BW_WO_DLPF_8800\r\n   *\/\r\n  myMPU9250.enableGyrDLPF();\r\n  \/\/myMPU9250.disableGyrDLPF(MPU9250_BW_WO_DLPF_8800); \/\/ bandwidth without DLPF\r\n  \r\n  \/*  Digital Low Pass Filter for the gyroscope must be enabled to choose the level. \r\n   *  MPU9250_DPLF_0, MPU9250_DPLF_2, ...... MPU9250_DPLF_7 \r\n   *  \r\n   *  DLPF    Bandwidth [Hz]   Delay [ms]   Output Rate [kHz]\r\n   *    0         250            0.97             8\r\n   *    1         184            2.9              1\r\n   *    2          92            3.9              1\r\n   *    3          41            5.9              1\r\n   *    4          20            9.9              1\r\n   *    5          10           17.85             1\r\n   *    6           5           33.48             1\r\n   *    7        3600            0.17             8\r\n   *    \r\n   *    You achieve lowest noise using level 6  \r\n   *\/\r\n  myMPU9250.setGyrDLPF(MPU9250_DLPF_6);\r\n\r\n  \/*  Sample rate divider divides the output rate of the gyroscope and accelerometer.\r\n   *  Sample rate = Internal sample rate \/ (1 + divider) \r\n   *  It can only be applied if the corresponding DLPF is enabled and 0&lt;DLPF&lt;7!\r\n   *  Divider is a number 0...255\r\n   *\/\r\n  myMPU9250.setSampleRateDivider(99);\r\n\r\n\r\n  \/*  MPU9250_GYRO_RANGE_250       250 degrees per second (default)\r\n   *  MPU9250_GYRO_RANGE_500       500 degrees per second\r\n   *  MPU9250_GYRO_RANGE_1000     1000 degrees per second\r\n   *  MPU9250_GYRO_RANGE_2000     2000 degrees per second\r\n   *\/\r\n  myMPU9250.setGyrRange(MPU9250_GYRO_RANGE_250);\r\n  \r\n  \/* sleep() sends the MPU9250 to sleep or wakes it up. \r\n   * Please note that the gyroscope needs 35 milliseconds to wake up.\r\n   *\/\r\n  \/\/myMPU9250.sleep(true);\r\n\r\n  \/* This is a low power standby mode for the gyro function, which allows quick enabling. \r\n   * (see data sheet for further information)\r\n   *\/\r\n  \/\/myMPU9250.enableGyrStandby(true);\r\n\r\n  \r\n  \/* You can enable or disable the axes for gyroscope and\/or accelerometer measurements.\r\n   * By default all axes are enabled. Parameters are:  \r\n   * MPU9250_ENABLE_XYZ  \/\/all axes are enabled (default)\r\n   * MPU9250_ENABLE_XY0  \/\/ X, Y enabled, Z disabled\r\n   * MPU9250_ENABLE_X0Z   \r\n   * MPU9250_ENABLE_X00\r\n   * MPU9250_ENABLE_0YZ\r\n   * MPU9250_ENABLE_0Y0\r\n   * MPU9250_ENABLE_00Z\r\n   * MPU9250_ENABLE_000  \/\/ all axes disabled\r\n   *\/\r\n  \/\/myMPU9250.enableGyrAxes(MPU9250_ENABLE_000);  \r\n}\r\n\r\nvoid loop() {\r\n  xyzFloat gyrRaw = myMPU9250.getGyrRawValues();\r\n  xyzFloat corrGyrRaw = myMPU9250.getCorrectedGyrRawValues();\r\n  xyzFloat gyr = myMPU9250.getGyrValues();\r\n  \r\n  Serial.println(\"Gyroscope raw values (x,y,z):\");\r\n  Serial.print(gyrRaw.x);\r\n  Serial.print(\"   \");\r\n  Serial.print(gyrRaw.y);\r\n  Serial.print(\"   \");\r\n  Serial.println(gyrRaw.z);\r\n\r\n  Serial.println(\"Corrected gyroscope raw values (x,y,z):\");\r\n  Serial.print(corrGyrRaw.x);\r\n  Serial.print(\"   \");\r\n  Serial.print(corrGyrRaw.y);\r\n  Serial.print(\"   \");\r\n  Serial.println(corrGyrRaw.z);\r\n\r\n  Serial.println(\"Gyroscope Data in degrees\/s (x,y,z):\");\r\n  Serial.print(gyr.x);\r\n  Serial.print(\"   \");\r\n  Serial.print(gyr.y);\r\n  Serial.print(\"   \");\r\n  Serial.println(gyr.z);\r\n\r\n  Serial.println(\"*********************************\");\r\n\r\n  delay(1000);\r\n}<\/pre>\r\n<p>&nbsp;<\/p>\r\n<\/div>\r\n\n<h5 class=\"wp-block-heading\">The setting options for the gyroscope<\/h5>\n\n<p>Again, you can use the <code>autoOffsets()<\/code> function. The gyroscope should return zero for all axes in the non-moving state, or at least fluctuate around zero. However, you will notice some offset that is independent of the positioning (tilt). Alternatively, use the values determined in the +\/-250 \u00b0\/s measuring range for <code>setGyrOffsets()<\/code>. I&#8217;ll come back to that when we talk about the calibration sketch. <\/p>\r\n<p>You activate the low-pass filter (DLPF) with <code>enableGyrDLPF()<\/code>. If you disable the DLPF, you can still choose between the two bandwidths 8800 and 3600 Hz. Therefore, you have to pass the corresponding parameters to the <code>disableGyrDLPF()<\/code> function. You choose the level of the low-pass filter with <code>setGyrDLPF()<\/code>. Here, too, a stronger filter leads to greater delays. Similarly, level 7 does not fit in the series. Level 6 provides the lowest noise.<\/p>\r\n<p>Other features:<\/p>\r\n<ul>\r\n<li><code>setSampleRateDivider()<\/code> works like the accelerometer<\/li>\r\n<li><code>setGyrRange()<\/code> sets the range<\/li>\r\n<li><code>enableGyrStandby()<\/code> sends the gyroscope into a kind of half-sleep, which allows a faster wake-up than from sleep mode (unfortunately I didn&#8217;t find concrete data)<\/li>\r\n<li><code>enableGyrAxes()<\/code> activates or deactivates the axes<\/li>\r\n<li><code>getGyrRawValues()<\/code> provides the currently available raw data<\/li>\r\n<li><code>getCorrectedGyrRawValues()<\/code> subtracts the offsets from the raw data and provides the corrected data<\/li>\r\n<li><code>getGyrValues()<\/code> provides the gyroscope data in degrees\/second, based on the corrected raw data<\/li>\r\n<\/ul>\r\n\n<h5 class=\"wp-block-heading\">Output of MPU9250_gyroscope_data.ino<\/h5>\n\n<p>The first values in the output below were determined without moving the MPU9250. For the second set of values, I rotated the module around its x-axis.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_gyrscope_data.png\"><img loading=\"lazy\" decoding=\"async\" width=\"769\" height=\"349\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_gyrscope_data.png\" alt=\"MPU9250 Example sketch: Output of MPU9250_gyroscope_data.ino\" class=\"wp-image-11325\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_gyrscope_data.png 769w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_gyrscope_data-300x136.png 300w\" sizes=\"auto, (max-width: 769px) 100vw, 769px\" \/><\/a><figcaption class=\"wp-element-caption\">Output of MPU9250_gyroscope_data.ino<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Example sketch 3: MPU9250_magnetometer_data.ino<\/h4>\n\n<p>The magnetometer (AK8963) behaves like a separate device. It has its own I2C address (0x0C) and own registers. Thus, it has to be initialized separately. If you check the MPU9250 with an I2C scanner, it will only detect the MPU9250 address. The magnetometer is not directly accessible behind the MPU9250. It is controlled via a kind of I2C subnet which is provided by the MPU9250. However, you won&#8217;t notice that complexity since the library manages all that in the background. <\/p>\r\n\n<div class=\"scroll-paragraph-long\">\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"MPU9250_magnetometer_data.ino\" data-enlighter-title=\"MPU9250_magnetometer_data.ino\">#include &lt;MPU9250_WE.h&gt;\r\n#include &lt;Wire.h&gt;\r\n#define MPU9250_ADDR 0x68\r\n\r\n\/* There are several ways to create your MPU9250 object:\r\n * MPU9250_WE myMPU9250 = MPU9250_WE()              -&gt; uses Wire \/ I2C Address = 0x68\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(MPU9250_ADDR)  -&gt; uses Wire \/ MPU9250_ADDR\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(&amp;wire2)        -&gt; uses the TwoWire object wire2 \/ MPU9250_ADDR\r\n * MPU9250_WE myMPU9250 = MPU9250_WE(&amp;wire2, MPU9250_ADDR) -&gt; all together\r\n * Successfully tested with two I2C busses on an ESP32\r\n *\/\r\nMPU9250_WE myMPU9250 = MPU9250_WE(MPU9250_ADDR);\r\n\r\nvoid setup() {\r\n  Serial.begin(115200);\r\n  Wire.begin();\r\n  if(!myMPU9250.init()){\r\n    Serial.println(\"MPU9250 does not respond\");\r\n  }\r\n  else{\r\n    Serial.println(\"MPU9250 is connected\");\r\n  }\r\n  if(!myMPU9250.initMagnetometer()){\r\n    Serial.println(\"Magnetometer does not respond\");\r\n  }\r\n  else{\r\n    Serial.println(\"Magnetometer is connected\");\r\n  }\r\n\r\n  \/* You can choose the following operational modes\r\n   * AK8963_PWR_DOWN            power down (default)\r\n   * AK8963_CONT_MODE_8HZ       continuous at 8Hz sample rate\r\n   * AK8963_CONT_MODE_100HZ     continuous at 100Hz sample rate \r\n   * \r\n   * In trigger mode the AK8963 goes into power down after the measurement\r\n   *\/\r\n  myMPU9250.setMagOpMode(AK8963_CONT_MODE_100HZ);\r\n  \r\n  \/* In continuous mode you need to wait for the first data to be available. If you \r\n   * comment the line below you will probably obtain zero. \r\n   *\/\r\n  delay(200);\r\n}\r\n\r\nvoid loop() {\r\n  xyzFloat magValue = myMPU9250.getMagValues(); \/\/ returns magnetic flux density [\u00b5T] \r\n\r\n  Serial.println(\"Magnetometer Data in \u00b5Tesla: \");\r\n  Serial.print(magValue.x);\r\n  Serial.print(\"   \");\r\n  Serial.print(magValue.y);\r\n  Serial.print(\"   \");\r\n  Serial.println(magValue.z);\r\n\r\n  delay(1000);\r\n}<\/pre>\r\n<p> <\/p>\r\n<\/div>\r\n\r\n\n<h5 class=\"wp-block-heading\">The settings for the magnetometer<\/h5>\n\n<p>The magnetometer has a power-down mode and two continuous modes. The continuous modes differ in the data rate, namely 8 or 100 Hz. You&#8217;re setting the mode with <code>setMagOpMode()<\/code>.<\/p>\r\n<p>You can query magnetometer values with <code>getMagValues()<\/code>. The result is output in microtesla. The function returns the values that are currently in the data store. In 8 Hz mode the data can be up to 125 ms &#8220;old&#8221;. Accordingly, after initialization the first value could be zero. To avoid that I have added a <code>delay()<\/code>.<\/p>\r\n\n<h5 class=\"wp-block-heading\">Output of MPU9250_magnetometer_data.ino<\/h5>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_magnetometer_data.png\"><img loading=\"lazy\" decoding=\"async\" width=\"769\" height=\"349\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_magnetometer_data.png\" alt=\"MPU9250 example sketch: Output of MPU9250_magnetometer_data.ino\" class=\"wp-image-11328\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_magnetometer_data.png 769w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_magnetometer_data-300x136.png 300w\" sizes=\"auto, (max-width: 769px) 100vw, 769px\" \/><\/a><figcaption class=\"wp-element-caption\">Output of MPU9250_gyroscope_data.ino<\/figcaption><\/figure>\n\n<p>The results were a little sobering at first. I expected to be able to use the MPU9250 as a compass without any problems.<\/p>\r\n<p>In Central Europe, the magnetic flux density of the Earth&#8217;s magnetic field is about 20 microns in the horizontal and around 44 \u00b5T in the vertical (source: <a href=\"https:\/\/de.wikipedia.org\/wiki\/Erdmagnetfeld\" target=\"_blank\" rel=\"noopener\">German Wikipedia<\/a>). Accordingly, the difference between the maximum and minimum values when rotating the module horizontally and vertically should be 40 and 88 micrometers, respectively. You, like me, probably won&#8217;t measure that because:<\/p>\r\n<ol>\r\n<li>Again, there are offsets.<\/li>\r\n<li>You are probably measuring inside, and depending on the design of the house, the geomagnetic field is shielded.<\/li>\r\n<li>When measuring on the breadboard, the jumper cables and metal inside the breadboard can influence the measurements.<\/li>\r\n<\/ol>\r\n<p>I had also played around with strong magnets and magnetized my breadboard. Only when connecting with jumper cables only from below and without breadboard the results made more sense.<\/p>\r\n<p>I haven&#8217;t (yet) pursued using the magnetometer as a compass. According to what I have read in other articles for other magnetometers, this seems to be a science in itself. At least if you don&#8217;t just want to find north and south. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Example sketch 4: MPU9250_all_data.ino<\/h4>\n\n<p>This sketch provides acceleration, gyroscope data, magnetometer data and the temperature. You query the temperature with <code>getTemperature()<\/code>. The other functions have been introduced before. You find the sketch in the examples.<\/p>\r\n<p>The thermometer is not really to measure the ambient temperature. It is more to control the temperature within the MPU9250. It is higher than the ambient temperature and rises dependent on the parameters you set.<\/p>\r\n\n<h3 class=\"wp-block-heading\">Setting offsets permanently<\/h3>\n\n<h4 class=\"wp-block-heading\">Example sketch 5: MPU9250_calibration<\/h4>\n\n<p>This sketch is designed to help you determine the offsets for the accelerometer and gyroscope. For this purpose, the lowest measuring range and the maximum low-pass filter are set first. This ensures high resolution and low noise.<\/p>\r\n<p>For the offset determination of the accelerometer, you turn the MPU9250 slowly (!) around its axes and note the maximum and minimum raw values. It is best to have your elbows on the table when doing this, as any shaking will result in additional acceleration. You then use this data for the <code>setAccOffsets()<\/code> function. Internally, the offsets are determined from this. When you change the measuring range, the offsets are automatically adjusted. With this method, you no longer need to position the MPU9250 flat when starting the program. However, I would still recommend the function <code>autoOffsets()<\/code> to determine precise small tilt angles precisely.<\/p>\r\n<p>For the gyroscope offsets you don&#8217;t have to rotate the MPU9250 because the offset is independent of the inclination. You take the values for the x-, y- and z-axis as parameters in <code>setGyrOffsets()<\/code>.<\/p>\r\n<p>You can find the sketch in the examples. I don&#8217;t show it here.<\/p>\r\n\n<h5 class=\"wp-block-heading\">Output of MPU9250_calibration.ino<\/h5>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_calibration_sketch.png\"><img loading=\"lazy\" decoding=\"async\" width=\"769\" height=\"454\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_calibration_sketch.png\" alt=\"Example sketch MPU9250:&#13;&#10;Output of MPU9250_calibration.ino\" class=\"wp-image-11340\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_calibration_sketch.png 769w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Output_calibration_sketch-300x177.png 300w\" sizes=\"auto, (max-width: 769px) 100vw, 769px\" \/><\/a><figcaption class=\"wp-element-caption\">Output of MPU9250_calibration.ino<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Update 2024: Reusing autoOffsets() data<\/h4>\n\n<p>I have added the functions <code>getAccOffsets()<\/code> and <code>getGyrOffsets()<\/code>, with which you can query the calibration data of the <code>autoOffset()<\/code> function. This means you don&#8217;t have to run <code>autoOffset()<\/code> every time you start the program. The example sketch MPU9250_reusing_autocalib_data.ino shows how it works.<\/p>\r\n\n<h2 class=\"wp-block-heading\">Outlook<\/h2>\n\n<p>The <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-2\" target=\"_blank\" rel=\"noopener\">second part<\/a> of the article is about angles, interrupts, the low-power mode and the FIFO buffer. Of course, you don&#8217;t have to wait since you can try the example sketches now.<\/p>\r\n\n<h2 class=\"wp-block-heading\">Acknowledgement<\/h2>\n\n<p>I found the MPU9250 as a Fritzing component <a href=\"https:\/\/fritzing38.rssing.com\/chan-67186887\/all_p455.html\" target=\"_blank\" rel=\"noopener\">here<\/a> &#8211; thanks to Randy!<\/p>\r\n<p>I found the parts for the post picture as usual on <a href=\"https:\/\/pixabay.com\/de\/\" target=\"_blank\" rel=\"noopener\">Pixabay.<\/a> The compass, the space shuttle and the thermometer are taken from <a href=\"https:\/\/pixabay.com\/de\/users\/openclipart-vectors-30363\/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=148214\" target=\"_blank\" rel=\"noopener\">OpenClipart-Vectors<\/a>. The gyro is from <a href=\"https:\/\/pixabay.com\/de\/users\/inspiredimages-57296\/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1312052\" target=\"_blank\" rel=\"noopener\">InspiredImages (Anthony)<\/a>. <\/p>\r\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The MPU9250 is an accelerometer, gyroscope, magnetometer and thermometer. I present its technical characteristics and give an introduction to my library.<\/p>\n","protected":false},"author":1,"featured_media":11345,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[919,572],"tags":[1337,556,697,1351,1338,558,1414,1720,1415],"class_list":["post-11361","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-acceleration","category-sensors","tag-accelerometer-en-2","tag-arduino-en-2","tag-circuit-en","tag-fifo-en","tag-gyroscope","tag-library-en-2","tag-magnetometer-en","tag-mpu6500-en","tag-mpu9250-en"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>MPU9250 - 9-Axis Sensor Module - Part 1 &#8226; Wolles Elektronikkiste<\/title>\n<meta name=\"description\" content=\"The MPU9250 is an accelerometer, gyroscope, magnetometer and thermometer. I present its properties and my library.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"MPU9250 - 9-Axis Sensor Module - Part 1 &#8226; Wolles Elektronikkiste\" \/>\n<meta property=\"og:description\" content=\"The MPU9250 is an accelerometer, gyroscope, magnetometer and thermometer. I present its properties and my library.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1\" \/>\n<meta property=\"og:site_name\" content=\"Wolles Elektronikkiste\" \/>\n<meta property=\"article:published_time\" content=\"2021-04-05T21:58:41+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-10-29T13:56:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Beitragsbild.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Wolfgang Ewald\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Wolfgang Ewald\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1\"},\"author\":{\"name\":\"Wolfgang Ewald\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"headline\":\"MPU9250 &#8211; 9-Axis Sensor Module &#8211; Part 1\",\"datePublished\":\"2021-04-05T21:58:41+00:00\",\"dateModified\":\"2024-10-29T13:56:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1\"},\"wordCount\":2549,\"commentCount\":84,\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2021\\\/04\\\/Beitragsbild.png\",\"keywords\":[\"accelerometer\",\"Arduino\",\"circuit\",\"FIFO\",\"gyroscope\",\"Library\",\"Magnetometer\",\"MPU6500\",\"MPU9250\"],\"articleSection\":[\"Acceleration\",\"Sensors\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1\",\"name\":\"MPU9250 - 9-Axis Sensor Module - Part 1 &#8226; Wolles Elektronikkiste\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2021\\\/04\\\/Beitragsbild.png\",\"datePublished\":\"2021-04-05T21:58:41+00:00\",\"dateModified\":\"2024-10-29T13:56:55+00:00\",\"description\":\"The MPU9250 is an accelerometer, gyroscope, magnetometer and thermometer. I present its properties and my library.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1#primaryimage\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2021\\\/04\\\/Beitragsbild.png\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2021\\\/04\\\/Beitragsbild.png\",\"width\":1100,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/mpu9250-9-axis-sensor-module-part-1#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"MPU9250 &#8211; 9-Axis Sensor Module &#8211; Part 1\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\",\"name\":\"Wolles Elektronikkiste\",\"description\":\"Die wunderbare Welt der Elektronik\",\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\",\"name\":\"Wolfgang Ewald\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"width\":512,\"height\":512,\"caption\":\"Wolfgang Ewald\"},\"logo\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"MPU9250 - 9-Axis Sensor Module - Part 1 &#8226; Wolles Elektronikkiste","description":"The MPU9250 is an accelerometer, gyroscope, magnetometer and thermometer. I present its properties and my library.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1","og_locale":"en_US","og_type":"article","og_title":"MPU9250 - 9-Axis Sensor Module - Part 1 &#8226; Wolles Elektronikkiste","og_description":"The MPU9250 is an accelerometer, gyroscope, magnetometer and thermometer. I present its properties and my library.","og_url":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1","og_site_name":"Wolles Elektronikkiste","article_published_time":"2021-04-05T21:58:41+00:00","article_modified_time":"2024-10-29T13:56:55+00:00","og_image":[{"width":1100,"height":1100,"url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Beitragsbild.png","type":"image\/png"}],"author":"Wolfgang Ewald","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Wolfgang Ewald","Est. reading time":"21 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1#article","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1"},"author":{"name":"Wolfgang Ewald","@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"headline":"MPU9250 &#8211; 9-Axis Sensor Module &#8211; Part 1","datePublished":"2021-04-05T21:58:41+00:00","dateModified":"2024-10-29T13:56:55+00:00","mainEntityOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1"},"wordCount":2549,"commentCount":84,"publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Beitragsbild.png","keywords":["accelerometer","Arduino","circuit","FIFO","gyroscope","Library","Magnetometer","MPU6500","MPU9250"],"articleSection":["Acceleration","Sensors"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1","url":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1","name":"MPU9250 - 9-Axis Sensor Module - Part 1 &#8226; Wolles Elektronikkiste","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#website"},"primaryImageOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1#primaryimage"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Beitragsbild.png","datePublished":"2021-04-05T21:58:41+00:00","dateModified":"2024-10-29T13:56:55+00:00","description":"The MPU9250 is an accelerometer, gyroscope, magnetometer and thermometer. I present its properties and my library.","breadcrumb":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1#primaryimage","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Beitragsbild.png","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2021\/04\/Beitragsbild.png","width":1100,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/wolles-elektronikkiste.de\/en"},{"@type":"ListItem","position":2,"name":"MPU9250 &#8211; 9-Axis Sensor Module &#8211; Part 1"}]},{"@type":"WebSite","@id":"https:\/\/wolles-elektronikkiste.de\/en#website","url":"https:\/\/wolles-elektronikkiste.de\/en","name":"Wolles Elektronikkiste","description":"Die wunderbare Welt der Elektronik","publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wolles-elektronikkiste.de\/en?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46","name":"Wolfgang Ewald","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","width":512,"height":512,"caption":"Wolfgang Ewald"},"logo":{"@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png"}}]}},"_links":{"self":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/11361","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/comments?post=11361"}],"version-history":[{"count":0,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/11361\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media\/11345"}],"wp:attachment":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media?parent=11361"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/categories?post=11361"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/tags?post=11361"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}