Hello friends, I hope you all are doing great. Today, I am going to share the new MPU6050 Sensor Library for Proteus V1.1. The MPU6050 is the popular 6-axis motion sensor: a 3-axis accelerometer, a 3-axis gyroscope and a temperature sensor in one small chip, best known on the blue GY-521 board. With this MPU6050 Sensor Library for Proteus, you tilt, turn and shake the sensor with presets, sliders or a click on its artificial horizon, and your Arduino reads it over I2C with the same Adafruit MPU6050 library you use on real hardware.

Updates

MPU6050 Sensor Library for Proteus

Latest version: V1.1 (September 2026, this tutorial)

Other IMU sensors: MPU9250 · ADXL345 · GY-271 Compass

Helping Tools

Version 1.1 replaces the first version of this post. You now get two devices: MPU6050 Simple, with a control panel on the schematic, and MPU6050 Advance, with a pop-up window and four measured sensor test tools. The model now has the digital low-pass filter with its real delay, motion detection with the INT pin, and the data-ready and FIFO interrupts. The new MPU6050 Arduino Proteus demo runs on two Arduino UNOs with a tilt alarm LED, shown in the compact Simple interface of our TEP Serial Monitor. Have you read version 1.0? Then jump to "What's New" below.

NOTICE: This library is very special to our team. Our MPU6050 model has the chip's register map, the four ranges, the digital low-pass filter with its delay, the FIFO, the motion detector and the INT pin, and it speaks I2C to the unmodified Adafruit library. It took our team a lot of hard work, many test runs and many design changes. Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the MPU6050 Library board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the MPU6050 Sensor Library for Proteus:

Figure: The MPU6050 demo in Proteus 8.5: NODE 1 (Simple) and NODE 2 (Advance), U2's Sensor page at TILT 30 (pitch 29.9°), and U4 printing the tilt lines and "Motion detected!".

What is the MPU6050 Sensor?

The MPU-6050, made by InvenSense (today TDK InvenSense), is a 6-axis motion sensor. Its accelerometer measures the acceleration along X, Y and Z, gravity included, and its gyroscope measures how fast the sensor turns about the same three axes. A third sensor reports the temperature of the chip. Your Arduino reads all of it over I2C, the 2-wire bus with a clock line (SCL) and a data line (SDA). For more background, read our Introduction to MPU6050.

Acceleration and rotation are different things. A sensor lying still on a table reads 1 g on its Z axis, because it feels gravity, and 0 deg/s on the gyroscope, because it does not turn. A gyroscope reading of 90 deg/s is a rotation rate, not an angle of 90 degrees.

The MPU6050 at a Glance

MPU6050 in numbers
FeatureValue
MeasuresAcceleration on X, Y, Z (gravity included), rotation rate about X, Y, Z, and the die temperature (our sliders: ±16 g, ±2000 deg/s, -40 to 85 C)
InterfaceI2C, standard and fast mode, at 0x68 (AD0 LOW) or 0x69 (AD0 HIGH)
Chip IDWHO_AM_I = 0x68
Accelerometer ranges±2, ±4, ±8 or ±16 g
Gyroscope ranges±250, ±500, ±1000 or ±2000 deg/s
Digital low-pass filter260, 184, 94, 44, 21, 10 or 5 Hz, with a delay of 0 to 19 ms
Sample rate1 kHz with the filter on (8 kHz gyro with it off), divided by 1 + SMPLRT_DIV
InterruptsData ready, FIFO overflow and motion, on the INT pin
FIFO1024 bytes (accelerometer, temperature, gyro)
SupplyA 3.3 V chip; the GY-521 has a 3.3 V regulator (662K), so it takes 5 V or 3.3 V on VCC

MPU6050 Terms You Will See in This Article

MPU6050 terms
TermMeaning
g9.80665 m/s², the pull of gravity; lying flat, the sensor reads +1 g on Z
deg/sA rotation rate in degrees per second, not an angle
Pitch, rollThe two tilt angles the demo computes from the accelerometer: nose up / down, and sideways
LSB (count)One step of the signed 16-bit register value
DLPFThe digital low-pass filter: it smooths the data and delays it
SMPLRT_DIVThe sample-rate divider: 1 kHz / (1 + SMPLRT_DIV) with the filter on
High-pass filter (HPF)Removes gravity and a steady tilt before the motion detector
MOT_THR, MOT_DURThe motion threshold (2 mg per count in our model) and duration (1 ms per count)
INT pin, INT_STATUSThe interrupt output, and the register that says which event happened
FIFOA 1024-byte buffer that stores samples for later reading
AD0The address pin: LOW = 0x68, HIGH = 0x69

How the MPU6050 Measures: Gravity, Ranges, Filter and Interrupts

Gravity and the Tilt Angles

The accelerometer always feels gravity. Lying flat, the MPU6050 reads 0, 0 and 1 g; upside down, Z reads -1 g; with all three at 0, the sensor is in free fall. Tilt it, and gravity spreads over the axes: rolled 45 degrees, Y and Z each read 0.71 g (cos 45° = 0.707). That is how a still sensor knows its tilt. The demo sketch computes it with atan2:

pitch = atan2(-AX, √(AY² + AZ²)), roll = atan2(AY, AZ)

This only works while the sensor holds still. During a shake, the extra acceleration bends the result, as the SHAKE preset will show.

The Gyroscope Measures a Rate

The gyroscope gives degrees per second. To get an angle, multiply by the time: 90 deg/s for 0.5 s is 45 degrees. A real gyroscope has a small bias and noise, so such a sum drifts; the simulation has neither, which makes it a clean place to check your maths and your signs.

Ranges and Resolution

Every value is a signed 16-bit number. The range your sketch chooses sets how many counts make one g or one deg/s:

MPU6050 ranges (the demo uses ±16 g and ±2000 deg/s)
Accelerometer rangeCounts per gGyroscope rangeCounts per deg/s
±2 g16384±250 deg/s131
±4 g8192±500 deg/s65.5
±8 g4096±1000 deg/s32.8
±16 g2048±2000 deg/s16.4

The demo uses the widest ranges, so 2048 counts are 1 g and 16.4 counts are 1 deg/s; the Adafruit library does the dividing for you. At the very end of the gyro slider, 2000 x 16.4 = 32800 does not fit into 16 bits (32767 at most), so the reading stops at about 1998.0 deg/s. That is the register limit, not a bus error.

The Digital Low-Pass Filter and Its Delay

The MPU6050 can smooth its data with a digital low-pass filter (DLPF), set in the CONFIG register. A narrower filter is smoother, but slower. Version 1.1 models the data sheet's delay as a first-order lag:

DLPF settings (the demo uses 21 Hz)
DLPF_CFGBandwidthAccelerometer delayGyroscope delay
0260 Hz0 ms0.98 ms
1184 Hz2.0 ms1.9 ms
294 Hz3.0 ms2.8 ms
344 Hz4.9 ms4.8 ms
421 Hz8.5 ms8.3 ms
510 Hz13.8 ms13.4 ms
65 Hz19.0 ms18.6 ms

The demo sets 21 Hz, so a change reaches the data registers about 8.5 ms later. Through the 5 Hz filter, a 1 g step reads 0.63 g after 19 ms. Version 1.0 stored the filter setting, but had no filter dynamics.

Sample Rate, Data Ready and the FIFO

With the filter on, the chip makes 1000 samples a second, divided by 1 + SMPLRT_DIV (the gyro runs at 8 kHz with the filter off). Every new sample sets the data-ready flag in INT_STATUS. The demo leaves SMPLRT_DIV at 0, so a new sample comes every 1 ms. The 1024-byte FIFO can collect samples for a sketch that reads them in bursts; the demo does not use it.

Motion Detection and the INT Pin

Motion detection was missing in v1.0. The chip runs the accelerometer data through a high-pass filter (reset, 5, 2.5, 1.25 or 0.63 Hz, or hold), so gravity and a steady tilt drop out and only changes remain. When a change is bigger than the threshold MOT_THR for longer than MOT_DUR (1 ms per count), the chip sets the motion bit in INT_STATUS. Our model counts MOT_THR as 2 mg per count; the register map does not state this scale, so it is a model value.

Every event (data ready, motion, FIFO overflow) can drive the INT pin: active high or low, push-pull or open drain, as a 50 us pulse or latched until your sketch reads INT_STATUS. So Adafruit's motion_detection example works with our model.

The I2C Address: AD0

The AD0 pin sets the address: LOW gives 0x68, HIGH gives 0x69, so two MPU6050s can share one bus. Change AD0 and the address in begin() together.

What's New in MPU6050 Sensor Library for Proteus V1.1

If you used version 1.0, here is what has changed:

  • Two devices in TEPMPU6050.LIB: MPU6050 Simple (MPU6050TEP, the v1.0 device) and MPU6050 Advance (MPU6050ADVTEP) with a pop-up window.
  • A redrawn, live board: the royal-blue GY-521 with an animated instrument window above it (artificial horizon, gyro and temperature bars), PWR / I2C / INT LEDs (a TEP addition) and the live I2C address.
  • Six presets (FLAT, TILT 30, ROLL 45, UPSIDE DOWN, SHAKE, SPIN) and a horizon you click to tilt the sensor; the Simple panel closes with a red X.
  • The DLPF delay of the data sheet (v1.0 had no filter dynamics).
  • Motion detection with MOT_THR, MOT_DUR and the high-pass filter, and the INT pin: polarity, push-pull or open drain, latched or 50 us pulses.
  • Data-ready and FIFO-overflow interrupts.
  • An I2C log: every read and write decoded, and the SCL clock measured on the pin.
  • Four measured test tools on the Advance.
  • A two-UNO demo with the TEP Serial Monitor instead of the Virtual Terminal: a tilt line, a tilt alarm LED and eight commands; every v1.0 output line is kept.
  • Lighter package: about 1.66 MB, without the C++ source code and the AVR core archive.

And your old designs keep working. A design with the v1.0 symbol runs with the new model and shows the old MPU6050 CONTROLS panel; here, the v1.0 demo with the v1.1 DLL:

Figure: A v1.0 design after the update: ACCEL X dragged to 8.91 g, and the v1.0 sketch prints "Accel g: 8.91, 0.00, 1.00".

Re-pick the part from the library to get the v1.1 board and the red X.

MPU6050 Sensor Library for Proteus: Simple vs Advance

Both devices run the same model with the same properties; only the panel differs:

MPU6050 Simple vs Advance
FeatureSimpleAdvance
Full MPU6050 model (0x68 / 0x69, ranges, DLPF delay, FIFO, motion detection, INT pin)✔✔
Blue GY-521 board: live horizon, gyro and temperature bars, PWR / I2C / INT LEDs✔✔
Control panel on the schematic (six presets, seven sliders, what the sketch read)✔✘
Pop-up window you can move, resize and minimise✘✔
Sensor page: a large live horizon, presets, click-sliders with - / +✘✔
I2C check, Timing, Step response and Orientation✘✔
TEP Dark / Light theme, text size, Help page with Copy diagnostics✘✔
Same device name as v1.0 (old designs keep working)✔✘

Choose Simple to keep the controls beside your circuit, and Advance when your sheet is full or you want hard numbers about your sketch. The demo has one of each.

Download MPU6050 Sensor Library for Proteus

Click the button below to download MPU6050-Sensor-Library-for-Proteus-v1.1.zip (about 1.66 MB, without the C++ source code):

MPU6050 Sensor Library for Proteus V1.1
  • README.txt: a detailed guide to the files, the wiring, the model, the test tools and real hardware.
  • Proteus Library Files: TEPMPU6050.LIB (both devices), TEPSERIALMON.LIB and our Arduino UNO library ArduinoV3TEP.LIB / ArduinoV3TEP.IDX.
  • Proteus Model Files: TEPMPU6050.DLL and TEPSERIALMON.DLL.
  • Proteus Simulation: MPU6050-ArduinoUnoV3.pdsprj, MPU6050_Demo.hex (both UNOs run it) and copies of both DLLs.
  • Arduino Code: MPU6050_Demo.ino and three unmodified libraries by Adafruit Industries: the Adafruit MPU6050 library 2.2.9 with its examples (BSD licence, license.txt), Adafruit BusIO 1.17.4 (MIT licence, LICENSE) and Adafruit Unified Sensor 1.1.15 (Apache License 2.0, LICENSE.txt).

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 MPU6050 Sensor Library for Proteus

  1. Close Proteus and extract the whole zip file.
  2. Copy the four files from Proteus Library Files into the LIBRARY folder, usually C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY (on some PCs C:\ProgramData\Labcenter Electronics\Proteus 8 Professional\LIBRARY).
  3. Copy TEPMPU6050.DLL and TEPSERIALMON.DLL into the MODELS folder.
  4. Start Proteus, press P and search for MPU6050. You get the Simple and the Advance device (category Sensors > Motion, as in v1.0).

Updating from v1.0? Replace TEPMPU6050.LIB and TEPMPU6050.DLL, and delete TEPMPU6050.IDX if there is one in LIBRARY. The DLL keeps its v1.0 name, so a v1.0 design keeps its v1.0 symbol and runs with the new model, with the v1.0 panel (no new board, no red X); re-pick the part to get the v1.1 board. Tested in Proteus 8.5; Proteus 7 is not supported.

The GY-521 Board in Proteus

We drew the sensor as a clean TEP board in the royal blue of the GY-521: two gold mounting holes, the MPU-6050 in the centre with the tantalum capacitor below it, the 662K regulator, the X / Y / Z axis glyph and the big GY-521 title. Here is U1, the Simple device, lying flat:

Figure: U1 (Simple) lying flat: 0.00, 0.00 and 1.00 g, and SKETCH READ shows exactly that.

GY-521 or MPU6050?

You see two names on the part, and both are right. MPU-6050 is the chip, InvenSense's motion sensor in the middle of the board, so the chip reads MPU-6050 INVENSENSE. GY-521 is the name of the blue breakout board that carries the chip, its regulator, its small parts and the 8-pin header, so the board title reads GY-521, as on the real module. In Proteus, you still search for "MPU6050".

The Instrument Window

Above the board sits an animated instrument window. The artificial horizon works like the one in an aeroplane: pitch moves it up and down, roll turns it, and a yellow pointer marks the roll on the bezel. Bars for the three gyro axes (GX, GY, GZ) sit on the left, a temperature bar (T) on the right, and PITCH, ROLL, GZ and the temperature are written below. Click the horizon to tilt the sensor.

Pinout

The eight pins keep the v1.0 names, order and places, which are also the order of the real GY-521 header:

GY-521 pins in Proteus (VCC GND SCL SDA XDA XCL AD0 INT)
PinWhat it doesDemo connection
VCCPowerSupply terminal
GNDGroundGND
SCLI2C clockArduino A5
SDAI2C dataArduino A4
XDAAuxiliary I2C data, for an external magnetometer (not simulated)Not connected
XCLAuxiliary I2C clock (not simulated)Not connected
AD0Address: LOW = 0x68, HIGH = 0x69GND (0x68)
INTInterrupt output (it also drives the INT LED)Not connected

LEDs and Indicators

Board animations (the same on both devices)
IndicatorWhat it shows
Artificial horizonPitch and roll of the sensor
GX / GY / GZ barsThe rotation rate on each axis
T barThe die temperature
PWR LED (red)Lit while VCC and GND are connected
I2C LED (blue)Flashes for 150 ms with every I2C transaction to this sensor
INT LED (amber)Lit while the INT pin is active
I2C 0x68 / 0x69The live address, from the AD0 pin
PANEL / OPEN PANEL, SIMPLE / ADVANCEThe panel button and the device badge

The three LEDs are a TEP addition: the real GY-521 has only a small power LED.

Component Properties

MPU6050 properties (double-click the sensor > Edit Properties; the v1.0 properties, the same on both devices)
PropertyMeaningDefault
AX, AY, AZThe acceleration at the start in g, -16 to 16 (gravity included)0, 0, 1 (lying flat)
GX, GY, GZThe rotation at the start in deg/s, -2000 to 20000
TEMPERATUREThe die temperature at the start, -40 to 85 C25

Every Run starts again from these properties. The panel style comes from the device (Simple or Advance), not from a property.

MPU6050 Simple: The Control Panel on the Sheet

Beside the Simple board sits the MPU6050 CONTROLS panel (on the right of the image above):

The MPU6050 Simple control panel
PartWhat it does
Header, red XMPU6050 CONTROLS; the X closes the panel
Six presetsFLAT, TILT 30, ROLL 45, UPSIDE DOWN, SHAKE and SPIN; the active one turns dark blue
Seven slidersThe v1.0 sliders: ACCEL X / Y / Z (-16 to 16 g), GYRO X / Y / Z (-2000 to 2000 deg/s) and TEMPERATURE (-40 to 85 C)
SKETCH READWhat your sketch really read over I2C, decoded by the model
TILT SET / SKETCH SAWThe tilt you set, against the tilt in the sketch's readings
Last lineMOTION DETECTION OFF with the filter and the sample rate (DLPF 21 HZ, 1000 SAMPLES / S), or ON with the threshold, the duration and the number of events

SKETCH READ is the line to watch: it is not what the sliders say, but what your Arduino got from the chip.

Presets and Tilt

One click sets all three accelerometer values for a position:

The four position presets (pitch / roll as the demo sketch computes them)
PresetACCEL X, Y, ZPitch / rollTilt alarm
FLAT0.00, 0.00, 1.00 g0.0 / 0.0Off
TILT 30-0.50, 0.00, 0.87 g29.9 / 0.0Off (not more than 30)
ROLL 450.00, 0.71, 0.71 g0.0 / 45.0On
UPSIDE DOWN0.00, 0.00, -1.00 g0.0 / 180.0On

SHAKE adds a shake on top of the current position (see below); try SPIN yourself and watch which bars and readings move. Here is ROLL 45:

Figure: ROLL 45: Y and Z read 0.71 g, and the sketch saw a roll of 45.0°.

The horizon turns 45 degrees, and the yellow pointer moves along the bezel. Y and Z read 0.71 g each: still 1 g in total, just shared by two axes. The sketch saw 0.0 / 45.0, more than 30 degrees, so UNO 1 lights the tilt alarm LED D1. UPSIDE DOWN turns the world over:

Figure: UPSIDE DOWN: Z reads -1.00 g, and the sketch's roll is 180.0°.

The ground is on top now, and Z reads -1.00 g. The demo's roll = atan2(AY, AZ) = atan2(0, -1) gives 180 degrees, so the tilt alarm stays on.

SHAKE and the Motion Interrupt

Now type MOTION ON on U3 (or click its quick button) and click SHAKE. U1 was lying FLAT when I clicked it:

Figure: SHAKE on top of FLAT: the sliders keep the base values and show the shake under them; the INT LED is lit, 28 events.

SHAKE is an effect on top of the slider values, so the sliders keep their base values (ACCEL X 0.00 g (base)), and an amber marker with SHAKE now under each one shows what the sensor feels at this moment: 0.01, 0.08 and 0.97 g, -17 and -8 deg/s. The sketch read -0.12, 0.10 and 0.96 g and -16 / -4 deg/s, so its tilt says 7.3 / 6.2 instead of 0.0 / 0.0. That is why pitch and roll from the accelerometer are only right while the sensor holds still. The last line reads MOTION DETECTION ON: 20 MG, 20 MS - 28 EVENTS, the demo's threshold of 10 counts x 2 mg for 20 ms. The amber INT LED lights while the INT pin is active, and the blue I2C LED flashes with the sketch's reads.

Closing the Panel

Need room on the sheet? Click the red X: the board button says PANEL: CLOSED with a grey dot, and the sensor keeps running. PANEL brings the panel back. Here, U1 is still at ROLL 45:

Figure: The panel closed: PANEL: CLOSED; the horizon still shows ROLL 45.

MPU6050 Advance: The Pop-Up Sensor Window

The Advance device keeps only the board on the schematic. Here is U2, lying flat:

Figure: U2 (Advance) with OPEN PANEL and the ADVANCE badge; AD0 goes to ground (0x68).

At Run, the "TEP MPU6050 Advance" pop-up opens with the look of our TEP Serial Monitor and no Windows title bar: move it by its header, resize or minimise it, and reopen it with OPEN PANEL. The header shows the state (here U2 · 1000 Hz), the Sensor and Test tabs and the palette (theme), gear (Settings) and ? (Help) icons.

The Sensor Page

Figure: The Sensor page at FLAT: MEASURING · 1000 Hz · ±16 g · ±2000, and SKETCH READ 0.00 0.00 1.00 G.
  • Toolbar chips: I2C 0x68, 2 readings / s (the demo's 500 ms), INT idle and the sample rate, 1000 Hz.
  • Green bar: MEASURING · 1000 Hz · ±16 g · ±2000, the state and the ranges your sketch set.
  • LIVE VIEW: a large horizon with pitch, roll, the size of the acceleration |a| (1.00 g at rest), the gyro and the temperature; click it to tilt the sensor.
  • CONTROLS: the six presets and a click-slider with - / + for each of the seven inputs.
  • WHAT THE ARDUINO READ OVER I2C: SKETCH READ, TILT SET against SKETCH SAW, the motion detector, and the ranges, the DLPF (21 Hz, delay 8.5 ms), the FIFO (0 bytes) and the INT pin.

In the featured image at the top, I clicked TILT 30 on this page. ACCEL X went to -0.50 g and ACCEL Z to 0.87 g, and the horizon reads pitch 29.9°, not 30.0°: cos 30° is 0.866, the preset sets 0.87 g, and atan2(0.50, 0.87) is 29.9°. The model's own TILT SET line says 29.9 too, and so does the sketch. U4 had MOTION ON, so it also printed a few "Motion detected!" lines; while the sensor held still at TILT 30, the readings went on without them. And 29.9 is not more than 30, so the tilt alarm LED D2 stayed off.

The Test Page: Four Measured Sensor Test Tools

The four tools on the Test tab only change the sensor's inputs (and restore them) and watch the I2C reads your Arduino really makes; they never talk to your Arduino. So every number is what the chip and your sketch really did, timed with the simulation clock. Each tool ends with a bold "Good for:" line and a grey line on how it measures. All results below come from U2 with the demo sketch.

1. I2C Check: What Did Your Sketch Write Into the Chip?

Figure: I2C check: WHO_AM_I 68, CONFIG 04 (21 Hz), both ranges 18, 0 NACKs and an SCL clock of 79 kHz.

Good for: "checking that the MPU6050 answers and what your sketch really wrote into it." It works live, without a Run button. Read the register table like a checklist:

  • WHO_AM_I 68: an MPU-6050, at 0x68 with AD0 low.
  • PWR_MGMT_1 01: awake, clocked from the gyro PLL; PWR_MGMT_2 00: all axes on.
  • SMPLRT_DIV 00 and CONFIG 04: 1000 samples a second through the 21 Hz filter, delay 8.5 ms.
  • GYRO_CONFIG 18 and ACCEL_CONFIG 18: ±2000 deg/s (16.4 LSB per deg/s) and ±16 g (2048 LSB per g).
  • MOT_THR, MOT_DUR and INT_ENABLE 00: motion detection was off on U2 at that moment; INT_STATUS 01: the data-ready flag.
  • USER_CTRL, FIFO_EN and FIFO_COUNT 00: the FIFO is off and empty.

Below the table: the address 0x68 (pin low), 401 transactions (12 a second), 1617 bytes with 0 NACKs, and the SCL clock, measured on the pin: 79 kHz (the sketch leaves Wire at its default clock). The last transactions show one demo reading every 0.5 s: the 14 data bytes from ACCEL_XOUT_H in 1467 us (accelerometer, temperature and gyro in one burst), then ACCEL_CONFIG and GYRO_CONFIG in about 228 us each, because the Adafruit library reads both ranges again in every getEvent() to scale the raw values. Right after Run, the same list shows the set-up writes, such as "write CONFIG = 04" (21 Hz) and "write ACCEL_CONFIG = 18" (±16 g).

2. Timing: How Often Is There New Data?

Figure: Timing, 3 s: a sample every 1.00 ms, 6 reads every 499.9 ms, every one new data.

Good for: "seeing how often new data exists and whether your sketch reads it in time." Choose a 1, 3 or 10 s window and click Run test. In 3 s, the sensor made 3000 conversions, one every 1.00 ms (1000.0 a second, min and max 1.00 ms), exactly what the registers expect: 1 kHz / (1 + SMPLRT_DIV 0). The sketch read 6 times, every 499.9 ms. The data it got was 1.0 ms old on average (1.3 ms at most), it never read the same sample twice, and there were no busy NACKs.

The list at the bottom shows every read: at 0.317 s, 0.817 s, 1.316 s and so on, 499.7 to 500.7 ms apart, each one "new data". The line under the timeline adds the filter: the DLPF delays every sample by 8.5 ms (accelerometer) and 8.3 ms (gyroscope). So the demo reads one sample in 500, and a sketch that read more than 1000 times a second would get the same sample twice.

3. Step Response: How Quickly Does a Change Reach Your Sketch?

Figure: Step response, tilt x 3: every step showed in full in the first reading, 266 ms after it.

Good for: "seeing how quickly a change reaches your sketch - conversion, filter and read period together." Choose the tilt (pitch 0 to 45 degrees), the rotation (GZ 0 to 250 deg/s) or the temperature (25 to 40 C), and 1, 3 or 5 steps of 1.5 s each. The tool steps the input itself, restores it afterwards, and plots every reading your sketch made: the dashed line is the set value, the dots are the readings.

Step response, tilt (pitch), 3 steps (U2, the demo's 500 ms reads)
StepChangeFirst reading (10 %)90 % reachedSettled (2 %)Readings
10 to 45 deg266.3 ms266.3 ms266.3 ms3
245 to 0 deg266.5 ms266.5 ms266.5 ms3
30 to 45 deg266.6 ms266.6 ms266.6 ms3

The three columns are the same in every step: the first reading after the step already had the whole change. The 8.5 ms filter delay is tiny next to the demo's 500 ms reads, so the 266 ms is simply how long the sketch waited for its next read. To see the filter itself, type FILTER 5 (19 ms delay) and RATE 200 on U4 and run it again.

4. Orientation: Does Your Pitch and Roll Maths Work Everywhere?

Figure: Orientation: 7 of 7 OK, worst error 0.12°, and the shake fired 29 motion interrupts.

Good for: "checking that your pitch / roll maths and the motion interrupt work in every position." The tool holds the sensor flat, nose up 45, nose down 30, rolled right 45, on its edge and upside down, 2.2 s each, and computes pitch and roll from the accelerometer values your sketch read (atan2), with a small horizon for each. Then it shakes the sensor for 1.5 s and counts the motion interrupts in INT_STATUS.

The result: 7 of 7 set points OK. Five positions read exactly (error 0.00°); nose down 30 read -29.9 (0.12°), like TILT 30 on the Sensor page, far inside the 2.0° limit. The shake fired 29 motion interrupts. Type MOTION ON on U4 first: without it, the shake cell says "motion INT off (type MOTION ON)".

Settings and Help

The gear opens Settings: theme (TEP Dark or Light), text size, open the panel at Run, and the window size, saved for your Windows user.

Figure: Settings, saved under HKCU\Software\TheEngineeringProjects\TEP MPU6050 Advance.

The ? icon opens Help & Support: eight cards with their links (the MPU6050 forum board for bugs and ideas, this article, updates, donate, website, forum), Check for updates, and Copy diagnostics for a bug report: the inputs, what was read, the registers, the last transactions and the test results. A links.ini next to the DLL can change the links.

Figure: Help & Support: every card shows its link; TEP MPU6050 Advance v1.1, build 2026-10-08, TEPMPU6050.DLL.

MPU6050 Tilt Alarm with Arduino in Proteus

Open MPU6050-ArduinoUnoV3.pdsprj from the Proteus Simulation folder, with MPU6050_Demo.hex and both DLLs beside it. Its two Arduino UNOs from our Arduino Library for Proteus V3.0 run the same HEX file:

  • NODE 1 - SIMPLE: UNO 1 (ARD1) with the MPU6050 Simple (U1), the tilt alarm LED D1 on A0 and Serial Monitor U3.
  • NODE 2 - ADVANCE: UNO 2 (ARD2) with the MPU6050 Advance (U2), the tilt alarm LED D2 on A0 and Serial Monitor U4.

Both sensors have AD0 to ground (0x68); each UNO has its own I2C bus, so that is no conflict.

Figure: The whole circuit running, without the pop-up windows: U1 at ROLL 45 (tilt alarm LED D1 on), U2 flat (D2 off).

Wiring

Demo wiring (the same on both UNOs)
FromToWhy
MPU6050 VCC / GNDSupply / groundPower (the PWR LED lights)
MPU6050 SCL / SDAArduino A5 / A4I2C clock and data
MPU6050 AD0GNDAddress 0x68
MPU6050 XDA / XCL / INTNot connectedINT is optional: it drives the INT LED and can go to D2 for attachInterrupt
LED + 220 ΩA0 to GNDThe tilt alarm LED
Serial Monitor RXD / TXD / GNDArduino D1 / D0 / groundShows what the Arduino prints, sends what you type
Serial Monitor RXD2Not connectedI2C has no serial line to watch

A4 and A5 are the UNO's I2C pins (see our Introduction to Arduino UNO). The Wire library turns on the UNO's internal pull-ups, so the simulation needs no external pull-up resistors; a real GY-521 has its own on board.

The Arduino Code

The sketch uses the unmodified Adafruit MPU6050 library (with Adafruit BusIO and Adafruit Unified Sensor), like v1.0:

#include <Wire.h>
#include <Adafruit_MPU6050.h>
Adafruit_MPU6050 sensor;
bool ready=false;

The new v1.1 variables: the LED pin, the print period (RATE), the motion detector and the tilt alarm:

const uint8_t LED_PIN=A0;
unsigned long readEvery=500, lastRead=0, lastPoll=0, ledUntil=0;
bool motionOn=false, tiltLine=true, alarmOn=false;
uint8_t motionThreshold=10;

In setup(), begin(0x68) finds the sensor at the AD0-low address, and the sketch sets the widest ranges and the 21 Hz filter, as in v1.0:

  Serial.begin(9600); Wire.begin(); Wire.setWireTimeout(25000,true);
  pinMode(LED_PIN,OUTPUT); digitalWrite(LED_PIN,LOW);
  ready=sensor.begin(0x68);
  if(!ready) { Serial.println(F("MPU6050 not found. Check power, A4/SDA, A5/SCL and AD0.")); return; }
  sensor.setAccelerometerRange(MPU6050_RANGE_16_G);
  sensor.setGyroRange(MPU6050_RANGE_2000_DEG);
  sensor.setFilterBandwidth(MPU6050_BAND_21_HZ);

The loop reads every RATE ms. getEvent() fills three events; the acceleration comes in m/s², so the sketch divides by 9.80665 to print g:

  if(now-lastRead>=readEvery) {
    lastRead=now;
    sensors_event_t a,g,t; sensor.getEvent(&a,&g,&t);
    Serial.print(F("Accel g: ")); Serial.print(a.acceleration.x/9.80665,2);

The gyro comes in rad/s, so it is multiplied by 57.29578 (180 / π) to print deg/s:

    Serial.print(F("Gyro deg/s: ")); Serial.print(g.gyro.x*57.29578,1);

Then the new tilt line, with the atan2 formulas from above:

    const float ax=a.acceleration.x, ay=a.acceleration.y, az=a.acceleration.z;
    const float pitch=atan2(-ax,sqrt(ay*ay+az*az))*57.29578, roll=atan2(ay,az)*57.29578;

The tilt alarm switches at more than 30 degrees, and its message comes only when it changes:

    const bool tilted=fabs(pitch)>30 || fabs(roll)>30;
    if(tilted!=alarmOn) { alarmOn=tilted; Serial.println(alarmOn ? F("Tilt alarm: ON (more than 30 deg)") : F("Tilt alarm: off")); }

MOTION ON sets up the motion detector with the 0.63 Hz high-pass filter, the threshold (10 by default), 20 ms, and a latched, active-high INT pin:

    sensor.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
    sensor.setMotionDetectionThreshold(motionThreshold);
    sensor.setMotionDetectionDuration(20);
    sensor.setInterruptPinLatch(true);
    sensor.setInterruptPinPolarity(false);
    sensor.setMotionInterrupt(true);

The loop asks the chip every 50 ms if the motion bit is set, and keeps the LED on for 1 s after each event:

  if(motionOn && now-lastPoll>=50) {
    lastPoll=now;
    if(sensor.getMotionInterruptStatus()) { Serial.println(F("Motion detected!")); ledUntil=now+1000; }
  }
  digitalWrite(LED_PIN,(alarmOn || millis()<ledUntil) ? HIGH : LOW);

HELP prints two lines, so it fits the Serial Monitor's Simple interface:

void help() {
  Serial.println(F("Commands: HELP, STATUS, RANGE 2|4|8|16, GYRO 250|500|1000|2000,"));
  Serial.println(F("  FILTER 260|184|94|44|21|10|5, RATE ms, MOTION ON [thr] | OFF, TILT ON | OFF"));
}

The settings live in the chip and in RAM, so a reset brings back the start values. To change the sketch, export a new HEX file and load it into both UNOs; see How to get the HEX file from Arduino. New to Arduino? Start with our Arduino Tutorial for Beginners.

Serial Monitor Commands

Commands of the demo sketch, upper or lower case (monitor quick buttons: STATUS, MOTION ON, RATE 200, HELP)
CommandWhat it does
HELPThe command list (two lines)
STATUSTwo lines: the ranges, the filter and the print period; the motion detector and the tilt alarm
RANGE 2 | 4 | 8 | 16The accelerometer range in ±g
GYRO 250 | 500 | 1000 | 2000The gyroscope range in ±deg/s
FILTER 260 | 184 | 94 | 44 | 21 | 10 | 5The digital low-pass filter in Hz
RATE msThe print period, 100 to 10000 ms (default 500)
MOTION ON [thr] / MOTION OFFThe motion interrupt: high-pass 0.63 Hz, threshold 10 by default, 20 ms, latched
TILT ON / TILT OFFThe tilt line under each reading

How to Run the Demo

  1. Press Run. Both Serial Monitors (9600 baud) and U2's pop-up open; the PWR LEDs light, and the I2C LEDs flash with every reading.
  2. On U1's panel, click TILT 30, ROLL 45 (D1 lights), UPSIDE DOWN and FLAT, or click the horizon.
  3. Click STATUS on U3, then MOTION ON, and click SHAKE on U1's panel.
  4. On U2's Sensor page, try the presets; type MOTION ON on U4, then run the four tools on the Test tab.
  5. Close U2's window and open it again with OPEN PANEL; close U1's panel with its red X and open it with PANEL.

MPU6050 Proteus Simulation Results

The Serial Monitor in Its Simple Interface

Both monitors in this demo run in the Simple interface of our TEP Serial Monitor, as in every monitor screenshot here. Only the log, the send box and one slim toolbar row stay visible (baud rate, follow, pause, search and clear), so the window stays small.

  • Switch to it: right-click the log and choose Simple interface, or press Ctrl+Shift+U.
  • Back to the full view: click the corner button (the expand arrows at the top right), press Esc or Ctrl+Shift+U, or right-click and choose Full interface.
  • Your choice is remembered.

Type commands such as STATUS or MOTION ON in the send box and press Enter; the quick buttons (STATUS, MOTION ON, RATE 200, HELP) come back with the full view. Every line of the v1.1 sketch is 80 characters or less, so it fits this small window. Read all about the monitor in TEP Serial Monitor Advance for Proteus.

Start-Up

After Run, U3 prints the v1.0 line, the new v1.1 line and then a reading every 500 ms: the v1.0 accelerometer and gyro lines plus the new tilt line:

Figure: U3 in the Simple interface: the two start lines, then Accel, Gyro and Tilt every 500 ms.
TEP MPU6050 - drag acceleration, gyro and temperature controls.
TEP MPU6050 Demo v1.1 - type HELP in the Serial Monitor
Accel g: 0.00, 0.00, 1.00
Gyro deg/s: 0.0, 0.0, 0.0 | T: 25.0 C
Tilt: pitch 0.0, roll 0.0 deg
Accel g: 0.00, 0.00, 1.00
Gyro deg/s: 0.0, 0.0, 0.0 | T: 25.0 C
Tilt: pitch 0.0, roll 0.0 deg

Flat at 25 C: 0, 0 and 1 g, no rotation, pitch and roll 0.0. The "Gy" at the bottom of the screenshot is the next reading, still on its way at 9600 baud.

ROLL 45: The Tilt Alarm

Figure: U3 after ROLL 45: the alarm line once, then the readings go on.
Tilt alarm: ON (more than 30 deg)
Accel g: 0.00, 0.71, 0.71
Gyro deg/s: 0.0, 0.0, 0.0 | T: 25.0 C
Tilt: pitch 0.0, roll 45.0 deg

One click on ROLL 45, and the sketch prints "Tilt alarm: ON (more than 30 deg)" once and lights D1; then the readings go on with 0.00, 0.71, 0.71 g and a roll of 45.0. The alarm line comes only when the alarm changes, so it does not fill the log; FLAT prints "Tilt alarm: off".

STATUS

Figure: U3: STATUS answers in two short lines.
Gyro deg/s: 0.0, 0.0, 0.0 | T: 25.0 C
STATUS
Tilt: pitch 0.0, roll 45.0 deg
Status: +-16 g, +-2000 deg/s, filter 21 Hz, every 500 ms
  motion OFF, tilt alarm ON

STATUS gives the ranges, the filter and the print period, then the motion detector and the alarm (here OFF and ON). The reading the sketch was printing finishes first, so its Tilt line comes before the answer.

MOTION ON

Figure: U4: MOTION ON, then STATUS confirms "motion ON, tilt alarm off".
Tilt: pitch 0.0, roll 0.0 deg
MOTION ON
Motion detection ON: threshold 10, 20 ms
Accel g: 0.00, 0.00, 1.00
Gyro deg/s: 0.0, 0.0, 0.0 | T: 25.0 C
Tilt: pitch 0.0, roll 0.0 deg
STATUS
Status: +-16 g, +-2000 deg/s, filter 21 Hz, every 500 ms
  motion ON, tilt alarm off

Threshold 10 means 10 counts of 2 mg, that is 20 mg, for 20 ms, as the Sensor page showed. Lying flat, nothing happens: a steady position is not motion.

SHAKE: Motion Detected!

Figure: U3 during SHAKE at ROLL 45: "Motion detected!" again and again, and one shaken reading.
Motion detected!
Motion detected!
Motion detected!
Motion detected!
Motion detected!
Motion detected!
Accel g: 0.06, 0.73, 0.72
Gyro deg/s: -9.7, -7.4, 0.0 | T: 25.0 C
Tilt: pitch -3.4, roll 45.3 deg
Motion detected!
Accel g: 0.00, 0.71, 0.71
Gyro deg/s: 0.0, 0.0, 0.0 | T: 25.0 C
Tilt: pitch 0.0, roll 45.0 deg

With MOTION ON on U3, I clicked SHAKE at ROLL 45. The sketch asks the chip every 50 ms, so a shake prints a row of "Motion detected!" lines. A reading in the middle of the shake shows the extra movement: 0.06, 0.73, 0.72 g, -9.7 and -7.4 deg/s, and a tilt of -3.4 / 45.3. When the shake ends, the readings are back at 0.00, 0.71, 0.71 g and a roll of 45.0.

Troubleshooting

  • "MPU6050 not found. Check power, A4/SDA, A5/SCL and AD0.": check VCC / GND (the PWR LED must be lit and the board must show I2C 0x68), SDA on A4, SCL on A5, and that AD0 matches the address in begin() (0x68 = AD0 low); then restart the simulation.
  • The values do not change: the blue I2C LED must flash with every read. A slider change shows at the sketch's next read, and through the low-pass filter (FILTER 5 delays it by 19 ms).
  • Z reads 1 g although nothing moves: correct, that is gravity. AX = AY = AZ = 0 is free fall.
  • "Motion detected!" never comes: type MOTION ON first; the motion detector only sees changes, so a steady tilt is not motion. Click SHAKE.
  • TILT 30 does not light the LED: correct; it reads 29.9 degrees, and the alarm needs more than 30.
  • The part is not simulated, no panel or no monitor window: TEPMPU6050.DLL or TEPSERIALMON.DLL is missing from MODELS and the project folder; click OPEN MONITOR on a closed monitor.
  • The Advance pop-up does not appear: click OPEN PANEL on the board, or turn "Open the panel at Run" back on in Settings.
  • No red X, or the board looks like v1.0: the design still holds the v1.0 symbol; replace TEPMPU6050.LIB, delete TEPMPU6050.IDX and re-pick the part.
  • Your own sketch uses SoftwareSerial to receive: Proteus 8.5 cannot receive with SoftwareSerial; use the hardware Serial, as the demo does, or AltSoftSerial.

Things to Know Before Using a Real GY-521

The demo sketch uses only Wire and the Adafruit libraries, so it runs on a real UNO and GY-521, too. Keep in mind:

  • Supply: the GY-521 has a 3.3 V regulator (662K), so feed VCC with 5 V or 3.3 V from the Arduino. The MPU-6050 itself is a 3.3 V part. In the simulation, VCC goes to a supply terminal.
  • Pull-ups: the GY-521 has its own I2C pull-ups (2.2 k or 10 k to 3.3 V on most boards), so A4 / A5 need nothing else, and a 5 V UNO reads the 3.3 V levels correctly.
  • Address: AD0 has a 4.7 k pull-down on the board (0x68); tie AD0 to VCC for 0x69. Two MPU6050s on one bus need different AD0 levels.
  • XDA / XCL are the MPU-6050's auxiliary I2C master, for a magnetometer; they are not simulated.
  • INT is optional; wire it to D2 if your sketch uses attachInterrupt.
  • Noise, offsets and drift: a real sensor has them, so calibrate it, and expect an angle summed from the gyro to drift; the model gives exact values.

Limitations of the Simulation

  • Not modelled: the DMP (motion processing firmware), the auxiliary I2C master, the self-test, the offset registers, the cycle and low-power wake-up modes, zero-motion and free-fall detection, noise, offsets and drift. The MOT_THR scale (2 mg per count) is a model value.
  • The model is our own implementation, written from the MPU-6000 / MPU-6050 product specification and register map; it contains no InvenSense code.
  • Licences: BSD for the Adafruit MPU6050 library 2.2.9, MIT for Adafruit BusIO 1.17.4 and Apache License 2.0 for Adafruit Unified Sensor 1.1.15. The HEX file also contains the Arduino AVR core 1.8.6, which includes LGPL-licensed code; its source code is on GitHub.
  • Tested in Proteus 8.5 on 8 Oct 2026 (the demo, both panels, the four tools, a v1.0 design and every screenshot here) and with 4,928 automatic PC checks, all passed, 27 of them with the real demo sketch and the unmodified Adafruit library on two UNOs; the unchanged v1.0 test passed too. Proteus 7 is not supported.

Need temperature, humidity and pressure next to the motion? See our BME280 Sensor Library for Proteus. Measuring light? Try our BH1750 Light Sensor Library for Proteus. To send your readings to another Arduino by radio, add our HC-12 Library for Proteus.

So, that was all about the MPU6050 Sensor Library for Proteus V1.1. I hope the live horizon, the presets, the motion interrupt and the four test tools make the MPU6050 much easier to understand, so your tilt alarm or motion project works the first time you wire a real GY-521. If you use the MPU6050 Sensor Library for Proteus in a project, please share your feedback 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!