MPU9250 Library for Proteus V1.0: the GY-9250 module with its STATUS panel and the Advance pop-up

MPU9250 Library for Proteus V1.0: GY-9250 9-Axis IMU for Arduino

2.5K Views
40
700
60
25
60
PCBWay

Hello friends, I hope you all are doing great. Today, I am going to share the new MPU9250 Library for Proteus V1.0. The MPU-9250 is the 9-axis motion sensor on the purple GY-9250 module: a 3-axis accelerometer, a 3-axis gyroscope and a 3-axis magnetometer in one small package. Drones, self-balancing robots, gimbals and head trackers use it to know their roll, pitch and yaw. Now you can build and test those projects in Proteus.

Behind the part sits our own model, not a part that shows three angles. The MPU-9250 answers the Arduino exactly as its register map says: the sample rate, the ranges, the offset registers, the FIFO and the INT pin, and the AK8963 magnetometer hidden behind the I2C bypass. You turn the board in 15 degree steps, rotate it, wave it in a figure eight or put a magnet on it, and the gyro sees every turn. You get two devices: a Simple device with a live STATUS panel and the board's controls, and an Advance device with a pop-up window and the test tools. The demo runs the MPU9250 library by hideakitai with its Madgwick filter on our Arduino UNO V4.0.

NOTICE: an IMU is easy to fake: hand the Arduino three angles from a property. We wanted more. Our MPU-9250 turns the board's attitude into gravity, rotation and the Earth's field on each chip's own axes, in each chip's own registers, so the hideakitai library and its Madgwick filter work out the angles exactly as on your desk, and a missing magnetometer, a slow loop or a magnet next to the board fails exactly as it does there. It took our team a lot of hard work. Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the MPU9250 board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the MPU9250 Library for Proteus V1.0:

MPU9250 Library for Proteus V1.0: the GY-9250 module with its STATUS panel and the Advance pop-up
Figure: The MPU9250 demo in Proteus 8.5: the GY-9250 of node 1 with its STATUS panel, the nose up by 30 degrees, and the pop-up of node 2 pitched and rolled, with its attitude ball and compass rose.

What is the MPU9250?

The MPU-9250 from InvenSense (now TDK) is a 9-axis motion sensor: inside one package sit an MPU-6500, with a 3-axis accelerometer and a 3-axis gyroscope, and the AK8963 3-axis magnetometer from AKM. The accelerometer feels gravity, so it knows how the board is tilted. The gyroscope measures how fast the board turns. The magnetometer feels the Earth's field, so it knows where north is. For a 6-axis sensor, see our Introduction to MPU6050 and our MPU6050 Library for Proteus; another inertial module is the LSM6DSL iNEMO inertial module. If you need only one of the three, try our ADXL345 Accelerometer Library for Proteus or our HMC5883L / QMC5883L Compass Library for Proteus. The GY-9250 module adds a 3.3 V regulator and the I2C pull-ups, so it works from 5 V too.

The MPU-9250 (the datasheet and register map values the model uses)
MPU-9250
Accelerometer+-2, +-4, +-8 or +-16 g (16384 to 2048 counts a g)
Gyroscope+-250, +-500, +-1000 or +-2000 dps (131 to 16.4 counts a dps)
Magnetometerthe AK8963: 14 bits (0.6 uT a count) or 16 bits (0.15 uT a count), 8 or 100 Hz
I2C addressesthe MPU at 0x68 (AD0 low) or 0x69 (AD0 high); the AK8963 at 0x0C behind the bypass
IdentityWHO_AM_I (0x75) = 0x71; the AK8963's WIA = 0x48
Extrasa 512-byte FIFO, an INT pin, offset registers, self-test, wake on motion, a thermometer
DevicesMPU9250TEP (Simple) and MPU9250ADVTEP (Advance)

The Magnetometer Behind the Bypass

The AK8963 does not sit on the Arduino's bus. It hangs on the MPU's own auxiliary I2C bus, and the Arduino reaches it in one of two ways: set BYPASS_EN in INT_PIN_CFG (0x37), and the AK8963 appears at 0x0C on the main bus; or let the MPU's own I2C master read it into the EXT_SENS_DATA registers. The hideakitai library uses the bypass. Its data comes low byte first, its X and Y axes are the MPU's Y and X, and a read must end with the ST2 register, or the chip keeps its old data. Each chip also stores three sensitivity adjustments (ASA) in a fuse ROM, which the sketch reads once.

MPU-9250 or MPU-6500? The Classic Trap

The MPU-9250 has been out of production for years, and many boards sold as GY-9250 carry an MPU-6500 instead: the same accelerometer and gyroscope, but no magnetometer. WHO_AM_I reads 0x70 instead of 0x71, the hideakitai library's setup() fails at the AK8963 (with its verbose mode on, it prints "Could not connect to AK8963"), and there is no yaw. The chip itself tells you: MP92 on an MPU-9250, MP65 on an MPU-6500. The model's CHIP property switches it, so you can see this trap in Proteus.

From Nine Numbers to Roll, Pitch and Yaw

With the board still, the accelerometer gives the pitch and the roll from gravity. The gyroscope is fast and smooth, but its small bias makes any angle it integrates drift. The magnetometer gives the heading, once it is turned level with the pitch and the roll. A Madgwick filter mixes all three into one attitude, and that is what the hideakitai library does in update(). Two things pull the yaw off: a magnet or steel on the board (hard iron, removed by turning the board through every direction) and the declination, the angle between magnetic and true north. The library starts with -7.51 degrees, the value for Japan, so set yours.

What's New in MPU9250 Library for Proteus V1.0

  • The real module: the purple GY-9250 with the MPU-9250, its regulator, the pull-ups and the X / Y / Z marks, drawn at about three times its real size, with the header VCC, GND, SCL, SDA, EDA, ECL, AD0, INT, NCS and FSYNC.
  • Two styles: a Simple device with a STATUS panel and an Advance device with a pop-up window; the PWR, I2C and INT LEDs and the panel button sit on the board itself.
  • The real MPU-9250: the sample rate and the DLPF, the four accelerometer and four gyro ranges, cycle mode, the offset registers, self-test, the FIFO, INT_STATUS and the INT pin, wake on motion, the internal I2C master.
  • The real AK8963: behind the bypass at 0x0C, power-down, single and continuous modes, 14 and 16 bits, DRDY, DOR, the data protection until ST2, the fuse ROM and self-test.
  • The board on the panel: yaw, pitch and roll in 15 degree steps, eight attitudes from N to FLIPPED, and three actions: ROTATE 360, FIGURE 8 and MAGNET. Every turn is smooth, so the gyro sees it.
  • The classic traps: an MPU-6500 sold as an MPU-9250, 0x0C called before BYPASS_EN, the other MPU address, and a loop too slow for the 100 Hz magnetometer.
  • Four test tools on the Advance device: I2C, Readings, Attitude & calibration, and Registers.
  • A two-node demo on our Arduino UNO V4.0 with the hideakitai library: RAW, CALIB, CALMAG, DECL and WHO.
  • A compact package: about 1.35 MB, without the C++ source code of the model.

Two Devices: Simple and Advance

MPU9250 Library for Proteus device: the GY-9250 module with the MPU-9250
Figure: The GY-9250 module as the library draws it, here as an Advance device, with the PWR, I2C and INT LEDs lit for the picture.

The module carries the MPU-9250 in the middle, marked MP92, the 662K regulator, the pull-ups R1 and R2 (472, 4.7 kohm), R3 on AD0, the capacitors and the axis marks: X to the right, Y up and Z out of the board. The header on the left has all ten pins of the real GY-9250.

GY-9250 MPU9250 module in Proteus as a Simple device with its STATUS panel and as an Advance device
Figure: The module as a Simple device with its STATUS panel, and as an Advance device with OPEN PANEL on the board.
The two devices (search "MPU9250" in Pick Devices; both in TEPMPU9250.LIB)
SimpleAdvance
DeviceMPU9250TEPMPU9250ADVTEP
On the schematicThe module and the STATUS panelThe module
The board's attitude and actionsOn the STATUS panelIn the pop-up
StatusBanner, 10 readouts, the last 4 eventsA pop-up: Sensor, Event log, Tests

Download MPU9250 Library for Proteus

Click the button below to download MPU9250-Library-for-Proteus-v1.0.zip (about 1.35 MB, without the C++ source code of the model):

MPU9250 Library for Proteus V1.0: GY-9250 9-Axis IMU for Arduino
  • README.txt: the devices, installation, the demo, wiring, the test tools and real hardware.
  • Proteus Library Files: TEPMPU9250.LIB and ArduinoV4TEP.LIB from our Arduino Library for Proteus V4.0.
  • Proteus Model Files: TEPMPU9250.DLL and TEPARDUINO.DLL.
  • Proteus Simulation: GY-9250-MPU9250-ArduinoUnoV4.pdsprj, GY9250_IMU_Demo.hex and copies of the two DLLs.
  • Arduino Code: GY9250_IMU_Demo.ino. It needs the MPU9250 library by hideakitai from the Library Manager of the Arduino IDE, only if you want to change the sketch.

No Proteus yet? Read How to Download and Install Proteus 7 and 8. New to libraries? Follow How to Install a New Library in Proteus.

How to Install MPU9250 Library for Proteus

  1. Close Proteus and extract the whole zip file, for example to your Desktop.
  2. Copy the two files from Proteus Library Files into the LIBRARY folder of Proteus (usually C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY).
  3. Copy TEPMPU9250.DLL and TEPARDUINO.DLL from Proteus Model Files into the MODELS folder.
  4. Delete TEPMPU9250.IDX from the LIBRARY folder if it is there.
  5. Start Proteus, press P and search for MPU9250.

Tip: keep the Proteus Simulation folder together, because the project needs its .hex file and the DLLs beside it. The library is tested in Proteus 8.5; Proteus 7 is not supported.

The GY-9250 Parts in Proteus

GY-9250 MPU9250 module in Proteus with its STATUS panel: the board flat, facing north
Figure: Node 1 up close: U1, the GY-9250 with its PWR, I2C and INT LEDs and its STATUS panel, the board flat and facing north.

Three LEDs sit on the module's board: PWR while VCC is there, I2C, which flashes when the Arduino talks to the module, and INT, which follows the MPU's INT pin. Next to the SIMPLE or ADVANCE badge is the panel button. The LEDs, the badge, the button and the panels are TEP additions; the real module has none of them.

The Simple device adds the STATUS panel. Its banner shows what the sketch read from all three sensors next to the board's real attitude; it turns amber while the board turns and red for a trap or a warning. Below it are the board's controls: YAW, PITCH and ROLL with - and + (15 degrees a click), eight attitudes (N, E, S, W, FLAT, NOSE UP, ON SIDE and FLIPPED) and three actions: ROTATE 360, FIGURE 8 and MAGNET. Ten readouts follow - the state, the chip, the accelerometer, the gyro and the magnetometer as read, the temperature, the tilt and the heading from the reading, the ranges and the reads - and the last four events.

The red X closes the STATUS panel, and the PANEL button on the board opens it again:

GY-9250 MPU9250 module in Proteus with its STATUS panel closed by the red X
Figure: The STATUS panel closed with its red X: only the module stays, with PANEL: OFF on its board.

The Advance device keeps the schematic clean: only the module. Its live data opens in a pop-up window at Run, and the OPEN PANEL button on the board brings the window back. The properties set the start: CHIP (MPU9250, MPU9255 or MPU6500), YAW, PITCH and ROLL, FIELD and INCLINATION (the Earth's field, 50 uT, 60 degrees down), TEMP (25 degrees C) and NOISE.

The Demo Circuit

MPU9250 Proteus simulation: two Arduino UNO V4.0 boards, each with a GY-9250 module
Figure: The demo project running: node 1 with the Simple module and its STATUS panel; node 2 with the Advance module.

The demo project has two nodes. Each one is an Arduino UNO V4.0 from our Arduino UNO Library for Proteus V4.0 with a GY-9250 on its SDA and SCL pins, which are A4 and A5. Node 1 starts flat and facing north; node 2 starts flat and facing east. Both UNOs run the same GY9250_IMU_Demo.hex.

MPU9250 demo project in Proteus edit mode: the two nodes before the simulation runs
Figure: The same project before Run: the panel waiting for the simulation.

Wiring

The wiring (in Proteus and on a real board)
ModuleArduino UNO
VCC5V (the regulator gives the chip 3.3 V)
GNDGND
SCLA5 (the SCL pin)
SDAA4 (the SDA pin)
AD0open or GND: 0x68 (VCC: 0x69)
INTopen (or an input for data ready)
NCSopen (I2C)
EDA, ECL, FSYNCopen

In Proteus, SDA and SCL reach their UNO through net labels, SDA_1 and SCL_1 for node 1 and the same with _2 for node 2. The Wire library turns on the UNO's internal pull-ups, which hold the I2C bus HIGH in the simulation. The serial monitor needs no wires at all, because it is built into the UNO V4.0.

GY-9250 MPU9250 module in Proteus as an Advance device with OPEN PANEL on the board
Figure: Node 2 up close: U2, the Advance module, with SDA_2 and SCL_2 going up to their labels.

The Arduino Code

The demo sketch uses the MPU9250 library by hideakitai (version 0.4.8), which is a single header. New to Arduino? Start with Arduino Tutorial for Beginners and Introduction to Arduino UNO. The sketch begins with Wire and the library:

#include <Wire.h>
#include "MPU9250.h"

In setup(), mpu.setup() reads WHO_AM_I, resets and configures the MPU (200 Hz, plus or minus 16 g and 2000 dps), sets BYPASS_EN, reads the AK8963's fuse ROM and starts it at 100 Hz. Then the sketch sets the declination to 0, because the library starts with Japan's -7.51 degrees:

void setup() {
  Serial.begin(9600);
  Wire.begin();
  Serial.println(F("TEP GY-9250 IMU - demo (MPU-9250 + AK8963)"));
  Serial.println(F("SDA on A4, SCL on A5"));
  delay(100);
  ok = mpu.setup(MPU_ADDR);
  if (ok) {
    mpu.setMagneticDeclination(0);               // the library starts at -7.51 (Japan): set yours with DECL
    Serial.println(F("found the MPU-9250 at 0x68 and its AK8963 - the hideakitai library"));
  } else {
    Serial.println(F("setup() failed:"));
    who();
  }
  help();
  nextAt = millis() + 500;
}

When setup() fails, who() reads WHO_AM_I itself and names the chip, so an MPU-6500 is caught at once:

void who() {
  const uint8_t w = readReg(MPU_ADDR, 0x75);
  Serial.print(F("WHO: WHO_AM_I "));
  printHex(w);
  if (w == 0x71) Serial.println(F(" = MPU-9250"));
  else if (w == 0x73) Serial.println(F(" = MPU-9255"));
  else if (w == 0x70) Serial.println(F(" = MPU-6500: no magnetometer inside"));
  else Serial.println(F(" = no MPU at 0x68 - check the wiring and AD0"));
  if (w == 0x71 || w == 0x73) {
    Serial.print(F("WHO: AK8963 WIA "));
    printHex(readReg(0x0C, 0x00));
    Serial.println(F(" (0x48 - behind the I2C bypass)"));
  }
}

The loop calls update() as often as it can. This matters: the AK8963 measures 100 times a second, and when the sketch reads it more slowly, ST1 shows a skipped sample (DOR) and the library drops that reading. Twice a second the sketch prints the roll, the pitch and the yaw:

void loop() {
  while (Serial.available()) {
    const char c = Serial.read();
    if (c == '\r' || c == '\n') { if (lineLen) { line[lineLen] = 0; command(line); lineLen = 0; } }
    else if (lineLen < sizeof line - 1) line[lineLen++] = c;
  }
  // update() as often as the loop runs: it reads the magnetometer only when new data is there (100 Hz)
  if (ok && mpu.update() && running && (long)(millis() - nextAt) >= 0) { printReading(); nextAt += 500; }
}
void printReading() {
  Serial.print('#'); Serial.print(++count);
  Serial.print(F("  roll ")); Serial.print(mpu.getRoll(), 1);
  Serial.print(F("  pitch ")); Serial.print(mpu.getPitch(), 1);
  Serial.print(F("  yaw ")); Serial.print(mpu.getYaw(), 1);
  Serial.print(F("  ")); Serial.print(mpu.getTemperature(), 1);
  Serial.println(F(" C"));
}

The HEX file is in the package, so you do not need the Arduino IDE to run the demo. To change the sketch, install "MPU9250" by hideakitai from the Library Manager, open the sketch in the Arduino IDE and export the compiled binary, as in How to get the HEX file from Arduino. It needs 29,252 bytes of flash and 1,241 bytes of RAM.

The Serial Monitor

MPU9250 roll, pitch and yaw in the built-in serial monitor of the Arduino UNO V4.0
Figure: ARD1's monitor: the MPU-9250 and its AK8963 found, then the roll, the pitch and the yaw with the board flat and facing north.

Both UNOs have the serial monitor built in, and it opens at Run. The screenshots use its Simple interface. Node 1 starts like this:

TEP GY-9250 IMU - demo (MPU-9250 + AK8963)
SDA on A4, SCL on A5
found the MPU-9250 at 0x68 and its AK8963 - the hideakitai library
Commands: RUN | STOP | RAW | CALIB | CALMAG | DECL 1.5 | WHO | HELP
#1  roll -0.3  pitch 1.0  yaw 2.5  25.0 C
#2  roll -0.3  pitch 1.0  yaw 3.2  25.0 C
#3  roll -0.8  pitch 0.7  yaw 2.1  25.0 C
#4  roll -0.6  pitch 0.7  yaw 2.1  25.0 C

The board lies flat and faces north, so all three angles sit close to zero. The pitch reads about one degree: the accelerometer has a small offset of its own, as a real one does, and CALIB removes it. Node 2 faces east, and its first lines show the Madgwick filter at work:

MPU9250 yaw turning from 25 to 89 degrees as the Madgwick filter settles
Figure: ARD2's monitor: the yaw climbs from 25.2 to 89.4 degrees in the first four seconds.
#1  roll -7.0  pitch 8.2  yaw 25.2  25.0 C
#2  roll -3.4  pitch 6.7  yaw 50.6  25.0 C
#3  roll -1.6  pitch 4.5  yaw 68.1  25.0 C
#4  roll -0.8  pitch 2.9  yaw 78.8  25.0 C
#5  roll -0.6  pitch 2.1  yaw 84.6  25.0 C
#6  roll -0.6  pitch 1.6  yaw 87.5  25.0 C
#7  roll -0.6  pitch 1.3  yaw 88.9  25.0 C
#8  roll -0.6  pitch 1.3  yaw 89.4  25.0 C

The filter starts at north and corrects itself a little with every update, so the yaw takes about four seconds to reach east. The yaw is the library's aircraft angle: east is +90, and west would be -90.

Turn the Board

Now let's turn the board while the simulation runs. We clicked E on U1's STATUS panel with the mouse:

GY-9250 STATUS panel in Proteus with the board turned east
Figure: Node 1 after E: the panel shows the yaw at 90 deg, and the banner the readings of all three sensors.
MPU9250 yaw turning from 2 to 90 degrees after E
Figure: ARD1's monitor: the yaw follows the turn to 90.5 within a second.
#137  roll -0.4  pitch 0.8  yaw 2.1  25.0 C
#138  roll -0.5  pitch 0.9  yaw 21.6  25.0 C
#139  roll -0.6  pitch 1.0  yaw 64.0  25.0 C
#140  roll -0.5  pitch 1.1  yaw 90.5  25.0 C
#141  roll -0.6  pitch 1.1  yaw 90.4  25.0 C

This time the yaw follows within a second, because the gyro saw the turn: the board turned smoothly, and the filter integrated the rotation instead of waiting for the magnetometer. Then two clicks on the pitch's +:

GY-9250 STATUS panel after two clicks on the pitch: the nose up by 30 degrees
Figure: Node 1 after the clicks: yaw 90, pitch 30 deg.
MPU9250 pitch at 30.4 degrees after the pitch buttons
Figure: ARD1's monitor: the pitch goes to 30.4 while the yaw stays near 88.
#143  roll -0.6  pitch 1.2  yaw 90.0  25.0 C
#144  roll -0.6  pitch 5.6  yaw 89.8  25.0 C
#145  roll -0.6  pitch 30.4  yaw 88.9  25.0 C
#146  roll -0.7  pitch 30.3  yaw 88.4  25.0 C
#147  roll -0.7  pitch 30.3  yaw 88.0  25.0 C

The pitch reads 30.4, the board 30. The yaw moves by about two degrees: with the nose up, the magnetometer has to be turned level before it gives a heading, and every small offset shows a little more. Then ROTATE 360 with the nose still up:

GY-9250 STATUS panel during ROTATE 360 with the nose up
Figure: Node 1 during ROTATE 360: the banner ROTATING, the button highlighted.
MPU9250 readings during a rotation with the nose up: the gyro on X and Z
Figure: ARD1's monitor: the yaw grows by about 22 degrees a line, and RAW shows the turn shared by the gyro's X and Z.
#151  roll -0.6  pitch 30.5  yaw 87.5  25.0 C
#152  roll -0.5  pitch 30.6  yaw 108.1  25.0 C
#153  roll -0.5  pitch 30.4  yaw 130.2  25.0 C
#154  roll -0.4  pitch 30.4  yaw 152.4  25.0 C
#155  roll -0.3  pitch 30.4  yaw 174.4  25.0 C
#156  roll -0.2  pitch 30.3  yaw -163.4  25.0 C
RAW
RAW: acc 0.52 -0.01 0.89 g, gyro -21.2 -1.0 -38.4 dps
RAW: mag -105 -416 294 mG

The board turns about the vertical at 45 degrees a second. With the nose up by 30 degrees, that turn is not about the gyro's own Z axis any more: it splits into about 39 degrees a second on Z and 22 on X. The filter puts it back together, and the yaw grows by about 22 degrees on every line, half a second apart. Note the wrap from 174.4 to -163.4: the library keeps the yaw between -180 and +180.

The Advance Pop-Up Window

At Run, the Advance module opens its own window, MPU9250 IMU, with the look of our TEP Serial Monitor Advance for Proteus. It has three tabs, Sensor, Event log and Tests, plus Settings and Help behind the gear and question mark icons. The status bar at the bottom always shows the board's attitude, the pitch and the roll from the reading, and the state.

MPU9250 Advance pop-up Sensor page in Proteus: the board, the reading, the attitude ball and the compass rose
Figure: The Sensor page of U2 at the start: the board facing east, the nine axes as read, the registers with the chip check and the last I2C transaction.

The toolbar carries the eight attitudes. The top card is the board: the yaw, the pitch and the roll with -15, -5, +5 and +15 degrees, the Earth's field and the three actions. What the sketch read draws an attitude ball and a compass rose, green for the board and amber for the reading, next to the accelerometer, the gyroscope, the magnetometer and the pitch, roll and heading worked out from them. The registers card shows PWR_MGMT_1, the rate, the ranges, INT_PIN_CFG with the bypass, WHO_AM_I and the AK8963's mode, and the chip check. The last card draws the last I2C transaction byte by byte. We clicked the pitch's +15 twice:

MPU9250 pop-up with the pitch at 30 degrees
Figure: U2 after +15 twice: the nose up by 30 deg, the horizon lower in the attitude ball.

Then the roll's -15 twice. The monitor shows both steps:

MPU9250 roll at -29.7 and pitch at 30.4 degrees
Figure: ARD2's monitor: the pitch at 30.4, then the roll down to -29.7.
#14  roll -0.7  pitch 30.4  yaw 87.6  25.0 C
#15  roll -0.7  pitch 30.5  yaw 87.6  25.0 C
#16  roll -18.9  pitch 30.4  yaw 87.5  25.0 C
#17  roll -29.8  pitch 30.4  yaw 87.4  25.0 C
#18  roll -29.7  pitch 30.4  yaw 87.2  25.0 C
MPU9250 pop-up pitched and rolled: the attitude ball tilted
Figure: U2 pitched up by 30 deg and rolled left by 30 deg: the horizon tilted, the reading P 30.0 R -30.1.

A negative roll is the left side down, so the horizon's right end drops in the ball, as in an aircraft. Then we clicked FLAT and typed RAW, which prints the nine values the library holds:

MPU9250 raw values in the built-in serial monitor: acceleration, rotation and field
Figure: ARD2's monitor: RAW with the board flat and still.
#26  roll -0.6  pitch 1.2  yaw 89.9  25.0 C
RAW
RAW: acc 0.02 -0.01 1.03 g, gyro 1.3 -0.8 0.5 dps
RAW: mag 262 0 449 mG

Z carries gravity, 1.03 g with the chip's small offset. The gyro is not zero although the board is still: 1.3, -0.8 and 0.5 dps is its bias. The filter copes with it, but an angle integrated from the gyro alone would drift by more than a degree a second. The field is in milligauss (10 mG = 1 uT) on the AK8963's axes.

ROTATE 360

Now the gyro at work. We clicked ROTATE 360, a full turn in 8 seconds:

MPU9250 pop-up during ROTATE 360: the gyro reads -44.5 dps on Z
Figure: U2 during ROTATE 360: the banner ROTATING, the board at 205 deg, the gyroscope at -44.5 dps on Z.
MPU9250 yaw growing by 22 degrees a line during ROTATE 360
Figure: ARD2's monitor: the yaw grows by about 22 degrees a line, and RAW shows -44.4 dps on the gyro's Z.
#28  roll -0.6  pitch 1.2  yaw 89.9  25.0 C
#29  roll -0.5  pitch 1.0  yaw 112.2  25.0 C
#30  roll -0.6  pitch 1.1  yaw 134.1  25.0 C
#31  roll -0.6  pitch 1.1  yaw 156.1  25.0 C
#32  roll -0.5  pitch 1.1  yaw 178.1  25.0 C
#33  roll -0.4  pitch 1.0  yaw -159.7  25.0 C
RAW
RAW: acc 0.02 -0.01 1.02 g, gyro 1.4 -0.9 -44.4 dps
RAW: mag -128 -223 453 mG

The board turns clockwise seen from above, 45 degrees a second. The gyro's Z axis points up, so a clockwise turn is negative: -44.4 dps, the 45 degrees a second plus the 0.6 of bias.

A Magnet on the Board

Now the thing that pulls a magnetometer off. With the board flat at east, we clicked MAGNET: a small magnet that sits on the board and turns with it.

MPU9250 pop-up with MAGNET on: the heading from the reading pulled to 106 degrees
Figure: U2 with the magnet: the board at 90 deg, the heading from the reading at 106 deg.
MPU9250 yaw pulled from 90 to 105 degrees by a magnet on the board
Figure: ARD2's monitor: the yaw drifts from 89.9 to 105.1 although the board does not move.
#45  roll -0.5  pitch 1.1  yaw 90.1  25.0 C
#46  roll -0.6  pitch 1.1  yaw 89.9  25.0 C
#47  roll -0.2  pitch 2.9  yaw 97.1  25.0 C
#48  roll -0.3  pitch 2.1  yaw 101.1  25.0 C
#49  roll -0.4  pitch 1.7  yaw 103.1  25.0 C
#50  roll -0.4  pitch 1.5  yaw 104.2  25.0 C
#51  roll -0.4  pitch 1.3  yaw 104.7  25.0 C
#52  roll -0.5  pitch 1.3  yaw 105.1  25.0 C

The yaw does not jump: the filter trusts the gyro, which says the board is still, and lets the magnetometer pull it over a few seconds. It ends 15 degrees off. Note the short bump in the pitch: the filter tried to explain the new field with a tilt.

CALMAG and FIGURE 8

The magnet turns with the board, so it shifts every reading by the same amount: hard iron. The library's calibrateMag() finds it from the minimum and the maximum of each axis while the board turns through every direction. We typed CALMAG and clicked FIGURE 8, 20 seconds of turning and tilting:

void calmag() {
  Serial.println(F("CALMAG: press FIGURE 8 now - 4 s, then 15 s of turning"));
  mpu.calibrateMag();
  Serial.print(F("CALMAG: bias "));
  Serial.print(mpu.getMagBiasX(), 0); Serial.print(' '); Serial.print(mpu.getMagBiasY(), 0); Serial.print(' '); Serial.print(mpu.getMagBiasZ(), 0);
  Serial.print(F(" mG, scale "));
  Serial.print(mpu.getMagScaleX(), 2); Serial.print(' '); Serial.print(mpu.getMagScaleY(), 2); Serial.print(' '); Serial.println(mpu.getMagScaleZ(), 2);
}
MPU9250 pop-up during FIGURE 8: the board turning and tilting for the magnetometer calibration
Figure: U2 during FIGURE 8: the banner counting down, the board at yaw 271, pitch 60, roll -88.

During the calibration the library reads only the magnetometer, so the accelerometer and gyro tiles keep the values from before. After about 25 seconds:

MPU9250 CALMAG result: the magnetometer bias and scale, the yaw back at 90
Figure: ARD2's monitor: the bias and the scale, then the yaw back near 90 with the magnet still on the board.
CALMAG
CALMAG: press FIGURE 8 now - 4 s, then 15 s of turning
CALMAG: bias 278 -161 205 mG, scale 1.00 0.99 1.01
#54  roll -0.6  pitch -0.0  yaw 94.7  25.0 C
#55  roll -0.6  pitch 0.7  yaw 90.4  25.0 C
#56  roll -0.6  pitch 0.9  yaw 88.6  25.0 C
#57  roll -0.6  pitch 1.0  yaw 87.9  25.0 C
#58  roll -0.6  pitch 1.0  yaw 87.6  25.0 C

The bias is in milligauss: 278, -161 and 205 mG, the magnet's X +26, Y -15 and Z +20 uT plus the AK8963's own small offset. The scale stays close to 1, because the board went everywhere. With the bias subtracted, the yaw settles back near 88 to 90 degrees, magnet or not. The Attitude & calibration tool shows the same arithmetic:

MPU9250 Attitude and calibration test tool in Proteus: the hard iron and the corrected heading
Figure: The Attitude and calibration tool on U2: the gyro's bias, the magnet, the hard-iron offsets X +27.9, Y -16.1, Z +20.6 uT and the corrected heading 87.6 deg.

It checks the pitch and the roll from the accelerometer, the 1 g of gravity, the gyro at rest, the heading tilt-compensated from the reading, the magnet and the ASA values. From the minimum and the maximum since the last turn it works out the offsets - X +27.9, Y -16.1 and Z +20.6 uT - and the heading corrected with them, 87.6 degrees: the same as the library's yaw.

CALIB, RAW and WHO

Last, the accelerometer and the gyro. CALIB calls calibrateAccelGyro(): 40 ms of samples through the FIFO, averaged into the chip's offset registers. The board must be still and flat. Then RAW and WHO:

MPU9250 CALIB result, RAW after it and WHO in the built-in serial monitor
Figure: ARD2's monitor: the offsets, the angles at zero, RAW with 1.00 g and the gyro near 0, and WHO.
CALIB: acc 17.4 -12.8 24.8 mg, gyro 1.37 -0.91 0.64 dps
#62  roll -0.0  pitch -0.1  yaw 90.4  25.0 C
#63  roll 0.1  pitch 0.1  yaw 90.1  25.0 C
RAW
#64  roll 0.0  pitch -0.1  yaw 89.9  25.0 C
RAW: acc -0.00 -0.00 1.00 g, gyro -0.1 -0.1 -0.2 dps
RAW: mag 245 -4 444 mG
#65  roll 0.0  pitch 0.1  yaw 89.9  25.0 C
WHO
WHO: WHO_AM_I 0x71 = MPU-9250
WHO: AK8963 WIA 0x48 (0x48 - behind the I2C bypass)

The offsets match the chip's own: 17.4, -12.8 and 24.8 mg, and 1.37, -0.91 and 0.64 dps. After it, RAW reads exactly 1.00 g, the gyro reads about 0.1 dps, the roll and the pitch sit at 0.0 and 0.1, and the yaw at 90. WHO confirms the chip: WHO_AM_I 0x71, and 0x48 from the AK8963 behind the bypass.

The Trap: an MPU-6500 on the Board

To see the trap, we set U2's CHIP property to MPU6500 and ran the demo again:

MPU9250 demo on an MPU-6500 board: setup() failed, WHO_AM_I 0x70
Figure: ARD2's monitor: setup() fails, and WHO names the chip - an MPU-6500 with no magnetometer.
TEP GY-9250 IMU - demo (MPU-9250 + AK8963)
SDA on A4, SCL on A5
I2C ERROR CODE : 2
setup() failed:
WHO: WHO_AM_I 0x70 = MPU-6500: no magnetometer inside
Commands: RUN | STOP | RAW | CALIB | CALMAG | DECL 1.5 | WHO | HELP

The library accepts the MPU-6500's WHO_AM_I, sets everything up, and then finds nobody at 0x0C: it prints the Wire error 2, a NACK on the address, and setup() returns false. The sketch's own WHO check explains why. The pop-up shows it in red:

MPU9250 pop-up with an MPU-6500: the red banners, no AK8963 inside
Figure: U2 as an MPU-6500: WHO_AM_I 0x70, no AK8963, and the red banners.

The Test Tools

MPU9250 I2C test tool in Proteus: this board, the magnetometer, the chip IDs and the reads
Figure: I2C on U2: this board, where the AK8963 is, the chip IDs, the mode, the reads, DOR and ST2, and the library step by step.

The I2C tool is the one to open for "Could not connect", a magnetometer that reads 0, data that never changes or the wrong address. It names the board and its chip, says where the AK8963 is, counts the calls to 0x0C while it is hidden, the other MPU address, the ID reads and the data reads, the skipped magnetometer samples and the reads without ST2, and shows the library's setup() and update() step by step. In our run it counted 385 magnetometer reads with DOR, a skipped sample now and then, so it shows that line in amber. The Readings tool lists the last 24 transactions:

MPU9250 Readings test tool in Proteus: the last 24 I2C transactions of both chips
Figure: Readings on U2: INT_STATUS, the 14 bytes of the MPU and the AK8963's ST1 and 7 bytes, each decoded.

One update() is four reads: INT_STATUS, 14 bytes from 0x3B with the accelerometer, the temperature and the gyro, ST1, and 7 bytes from 0x03 with ST2 at the end. The Registers tool decodes the settings:

MPU9250 Registers test tool in Proteus: the ranges, the rate, the FIFO, the offsets and the registers
Figure: Registers on U2: the ranges, the rate, the FIFO, the offsets and the MPU's and the AK8963's registers.

The Event Log

MPU9250 Advance pop-up Event log in Proteus: the reads, the writes and the board, newest first
Figure: The Event log of U2 after CALIB: the reads, newest first, and below them CALIB writing the gyro offsets and setting the MPU up again.

The Event log lists everything that happened, newest first: the power, the register writes of both chips, the data reads, the changes to the board with where they came from, notes and warnings. Filter it by I2C, the board or warnings, pause it, or clear it. Here you can see that the library sets the MPU up again after CALIB, starting with a reset; the model keeps the offset registers through that reset, so the calibration stays.

The Simulation Log

MPU9250 Proteus simulation log: power-on and the hideakitai library's setup
Figure: The simulation log of the final run: the modules start, and setup() resets and wakes the MPU.

The modules also write to the simulation log of Proteus, with the exact simulation time. This part shows the start of node 1:

U1: TEP MPU9250 IMU V1.0 - the GY-9250 with the MPU-9250 at 0x68 (the AK8963 at 0x0C behind it); yaw 0, pitch 0, roll 0 deg, the Earth's field 50 uT at 60 deg, 25 C - TEPMPU9250.DLL v1.0
U1: POWER ON - the MPU-9250 at 0x68 (WHO_AM_I 0x71): +-2 g, +-250 dps, DLPF off (8 kHz); the AK8963 behind it in power-down at 0.0000 s
U1: Write PWR_MGMT_1 (0x6B) = 0x80 - H_RESET: the registers back to their defaults, the offsets kept (BYPASS_EN = 0 hides the AK8963) at 0.1676 s
U1: Write PWR_MGMT_1 (0x6B) = 0x00 - awake, clock internal 20 MHz at 0.2679 s
U1: Write PWR_MGMT_1 (0x6B) = 0x01 - awake, clock auto (PLL) at 0.3683 s

The library's setup() resets the MPU, wakes it and picks the clock; each write is decoded. The reset clears BYPASS_EN, so the AK8963 is hidden until setup() sets it again a little later.

How the Model Works

The module is a digital model. VCC and GND power it, and SCL and SDA are the I2C bus: Proteus runs every edge from the Arduino with its exact time, and the model answers as two chips - the MPU at its address, and the AK8963 at 0x0C only while the bypass is on. At its sample rate the MPU takes a sample from the board's attitude: gravity and the rotation turned into its axes, with its own small offsets and noise. The AK8963 measures the Earth's field, the magnet and its own offset on its own axes, 100 times a second. The INT pin changes at the simulation time of each sample.

Troubleshooting

  • "setup() failed:" and "no MPU at 0x68": no power on VCC and GND, SDA and SCL swapped or missing, AD0 high (the MPU is at 0x69) or NCS low; the PWR LED is off or the I2C LED never flashes.
  • "setup() failed:" and WHO_AM_I 0x70: an MPU-6500 - no magnetometer inside.
  • The magnetometer reads 0 or never changes: the loop calls update() too slowly (DOR), the AK8963 is still behind the MPU (BYPASS_EN = 0), or its data was read without ST2.
  • The yaw is off by tens of degrees: a magnet or steel near the board - run CALMAG while it turns every way; and set your declination, the library starts at -7.51.
  • The angles drift slowly: the gyro's bias - run CALIB with the board still.
  • No part or no monitor: TEPMPU9250.DLL or TEPARDUINO.DLL is missing from MODELS and the project folder; a closed monitor opens again with a click on the UNO's USB port.

Things to Know Before Using a Real GY-9250

  • Check the chip first: MP92 is an MPU-9250, MP65 an MPU-6500 without a magnetometer; or read WHO_AM_I (0x71 or 0x70).
  • Keep it away from iron: magnets, motors, speakers and steel screws all pull the yaw.
  • Calibrate where it is mounted: CALMAG with a figure eight, CALIB with the board still and flat - the offsets are lost at power-off, so store them and set them again at start-up.
  • Keep the loop fast: the hideakitai library needs update() faster than 100 times a second for the magnetometer.
  • Set your declination for true north.

Limitations of the Simulation

  • Not modelled: SPI (NCS low only stops I2C), the DMP, FSYNC and the AK8963's external trigger, the DLPF's delay (only its effect on the noise), linear acceleration (the board turns about the chip), soft iron, the chips' scale errors, cross-axis sensitivity and temperature drift, and the clock stretching. The world is simple: one fixed field, one magnet, smooth turns.
  • The LEDs, the badge, the panel button and the panels are TEP additions.
  • The model is our own, written from the MPU-9250 and AK8963 datasheets and register maps. This library is not made or endorsed by InvenSense, TDK, AKM, hideakitai, the makers of the GY-9250 module or Labcenter.
  • Licences: the demo sketch uses the MPU9250 library 0.4.8 by hideakitai (MIT), which is not shipped; install it from the Library Manager. The demo's HEX file contains it and the Arduino AVR core 1.8.6 with LGPL-licensed code; the licence texts and the source links are in the README.
  • Tested in Proteus 8.5 in October 2026 (the demo as shipped on two Arduino UNO V4.0 boards with their built-in monitors: E, the pitch buttons and ROTATE 360 on node 1 with the mouse, the red X and PANEL; the pitch and roll steps, FLAT, RAW, ROTATE 360, MAGNET, CALMAG with FIGURE 8, CALIB and WHO on node 2, the four tools; a second run with an MPU-6500; 98.9 s of simulation took 314 s, about 0.3 x real time with the pop-up and both monitors open). Proteus 7 is not supported.

So, that was all about the MPU9250 Library for Proteus V1.0. I hope the nine axes, the bypass and the calibrations are clear now, and that your drone or robot knows its attitude from the first run. If you use the MPU9250 Library for Proteus in a project, please share it in the comments or in our forum, and if you have any questions, ask in the comments and I will help you out. Till the next tutorial, take care and have fun!


Comments

0

Join the conversation