IMU and Accelerometer Modules for Makers: MPU6050, BNO055, ADXL345, and Reading Motion Data
Sooner or later almost every maker project needs to know which way is down, whether it's moving, or how fast it's spinning — a robot that has to self-balance, a drone that needs attitude data, a fitness tracker counting steps, or a camera gimbal fighting hand shake. The part that answers those questions is an inertial measurement unit (IMU): a chip that packs an accelerometer, usually a gyroscope, and sometimes a magnetometer into one small package. This site's input shaper coverage already uses an ADXL345 to measure printer resonance, but that's a narrow, single-axis-at-a-time use case. This guide covers IMUs as a general sensing category — what accelerometers and gyroscopes actually measure, how to wire and read the common breakout boards, and how to turn raw, noisy readings into a stable orientation estimate you can actually use.
What an Accelerometer Actually Measures
A MEMS accelerometer does not measure velocity or position — it measures proper acceleration, the force per unit mass acting on a tiny suspended proof mass inside the chip, expressed in units of g (9.81 m/s²). Sitting perfectly still on a table, an accelerometer reads roughly 1g on whichever axis points straight up, because gravity is constantly accelerating the proof mass against the sensor's spring suspension. That's the key insight beginners miss: a stationary accelerometer never reads zero on all three axes. This is also exactly what makes accelerometers useful for tilt sensing — measure the gravity vector's components on X, Y, and Z, and basic trigonometry gives you pitch and roll.
What accelerometers are bad at is measuring orientation change over time by integration. Integrating acceleration twice to get position drifts almost immediately because of sensor noise and bias — this is why phones don't use accelerometers alone for indoor positioning, and why every serious IMU project pairs the accelerometer with a gyroscope.
What a Gyroscope Adds
A MEMS gyroscope measures angular velocity — degrees or radians per second of rotation around each axis — using the Coriolis effect on a vibrating internal structure. Unlike the accelerometer, a gyroscope has no idea which way is "down"; it only reports how fast the sensor is currently rotating. Integrate that rate over time and you get a very good short-term estimate of orientation change, but every gyroscope has a small bias error that integrates into steadily growing drift — a cheap gyro can drift several degrees per minute if you rely on it alone.
This is the classic complementary problem: accelerometers are accurate over the long term (gravity doesn't drift) but noisy and useless during fast motion or vibration; gyroscopes are smooth and accurate over the short term but drift over minutes. Combining the two — sensor fusion — is what makes a usable orientation sensor.
Common IMU Modules and When to Use Each
ModuleSensorsInterfaceNotes MPU60503-axis accel + 3-axis gyroI2CThe classic cheap 6-DOF IMU. No magnetometer, so no absolute heading. Digital Motion Processor (DMP) can do on-chip fusion but the library support is dated. Good enough for tilt, balance bots, and input shaping-style vibration capture. MPU9250 / ICM-20948Accel + gyro + magnetometer (9-DOF)I2C / SPIAdds a compass axis for absolute yaw/heading, not just relative rotation. The ICM-20948 is the modern successor and what most new "9-DOF" breakouts actually ship. BNO055Accel + gyro + magnetometer, with on-chip sensor fusionI2C / UARTBosch's "smart" IMU — it runs its own Kalman-style fusion internally and hands you a ready-made quaternion or Euler angle over I2C. Far less code on the MCU side, at a higher unit cost. BNO085 / BNO086Accel + gyro + magnetometer, improved fusionI2C / SPI / UARTSuccessor to the BNO055 with better calibration behavior and game rotation vector output that ignores magnetometer noise — popular in VR controllers and drones. ADXL3453-axis accelerometer onlyI2C / SPINo gyro, but high sample rates and low noise — this is what Klipper input shaping and vibration/impact-detection projects use. Not a general orientation sensor. LSM6DSOX / LSM6DS3Accel + gyro, plus a small onboard ML coreI2C / SPIST's higher-end 6-DOF option with an embedded finite state machine for gesture/tap detection without waking the main MCU — useful for battery-powered wearables.Wiring an I2C IMU to ESP32 or Arduino
Nearly all of these breakouts default to I2C, which means four wires: VCC (3.3V — most breakout boards are not 5V tolerant even though some have onboard regulators, check the specific board), GND, SDA, and SCL. On an ESP32 the default I2C pins are typically GPIO 21 (SDA) and GPIO 22 (SCL), but any two GPIOs work with Wire.begin(sda, scl). On an Arduino Uno, I2C is fixed to A4 (SDA) and A5 (SCL). Add 4.7kΩ pull-up resistors to 3.3V on SDA and SCL if your breakout board doesn't already include them — most do, but stacking multiple I2C devices with their own pull-ups can over-pull the bus and cause bus lockups.
Check the I2C address before wiring anything else — the MPU6050 defaults to 0x68 but many breakouts bring out an AD0 pin that switches it to 0x69, letting you run two on the same bus. Run an I2C scanner sketch first; a silent bus is almost always a wiring or address problem, not a dead chip.
From Raw Readings to a Usable Orientation: Sensor Fusion
If you're using a "dumb" 6-DOF sensor like the MPU6050, you have to do the fusion yourself. There are three approaches in increasing order of complexity and quality:
- Complementary filter — the simplest option. Blend the gyro-integrated angle with the accelerometer-derived tilt angle using a weighted average, typically 98% gyro + 2% accelerometer per update, recalculated every loop. It's a handful of lines of code, runs comfortably on an ATmega328, and is good enough for a self-balancing robot or camera stabilizer.
- Kalman filter — a proper statistical estimator that models sensor noise and bias explicitly and produces a mathematically optimal blend. More CPU and more tuning (you need believable noise variance values for your specific sensor) but noticeably more stable under vibration than a complementary filter.
- Madgwick / Mahony filter — quaternion-based fusion algorithms designed specifically for IMUs and widely used in flight controllers (Betaflight uses a variant of this). They avoid gimbal lock, handle 9-DOF magnetometer fusion cleanly, and run efficiently enough for a 32-bit MCU at hundreds of Hz. This is the right choice if you're building anything that needs to survive full 360° rotation.
If you'd rather not implement any of this, the BNO055 and BNO085 do all three levels of fusion on-chip and simply hand you a stable quaternion or Euler angle over I2C — worth the extra few dollars for anything beyond a simple tilt switch.
Calibration: The Step Everyone Skips and Regrets
Every accelerometer and gyroscope has manufacturing offset error — a gyro reading 2°/s while sitting perfectly still, or an accelerometer reading 0.98g instead of 1.00g on its resting axis. Uncalibrated, this shows up as steady drift even with good fusion code.
- Gyro bias calibration — with the sensor perfectly still, average a few hundred readings on power-up and subtract that average as a zero offset for the session. Gyro bias also drifts with temperature, so a one-time factory calibration isn't enough for precision work.
- Accelerometer offset and scale calibration — place the sensor flat on each of its six faces in turn and record the reading; this produces the offset and per-axis scale factor needed to correct for manufacturing tolerance. Libraries like the MPU6050's official calibration sketch automate this.
- Magnetometer calibration — if you're using a 9-DOF sensor for absolute heading, the magnetometer needs a "figure-8" calibration routine, physically waving the sensor through all orientations near its final mounting location so the firmware can map out and cancel hard-iron and soft-iron distortion from nearby motors, steel, and battery packs. Skipping this is the single most common reason a compass heading is wildly wrong on a finished robot or drone.
Practical Uses in Maker Projects
- Self-balancing robots and inverted pendulums — pitch angle from a complementary or Kalman filter feeds directly into a PID loop controlling wheel motors.
- Camera and antenna gimbals — orientation feedback lets a servo or brushless gimbal motor counter-rotate to cancel hand shake or vehicle motion.
- Step counters and activity trackers — accelerometer magnitude peaks, filtered and thresholded, are the basis of every pedometer algorithm.
- Impact and tamper detection — many IMUs (including the LSM6DSOX) support onboard interrupt thresholds that wake a sleeping MCU only when acceleration exceeds a set value, ideal for battery-powered shipping-impact loggers or security sensors.
- Drone and FPV flight controllers — Betaflight and similar firmware read a 6-DOF IMU at 1-8kHz as the core input to the flight stabilization loop, exactly the kind of high-rate fusion a Madgwick filter is built for.
Common Problems
SymptomLikely Cause Orientation slowly drifts even when stationaryMissing or poor gyro bias calibration; too much weight given to the gyro term in the fusion filter Heading jumps or reads backwards near motors/speakersUncalibrated magnetometer, or magnetic interference from nearby current-carrying wires — route sensor leads away from motor phase wires and BEC/regulator inductors I2C bus hangs or NACKs intermittentlyMissing pull-ups, too-long wires without shielding, or a second I2C device sharing the same default address Readings are noisy/jittery even with good filteringVibration from the mounting surface itself — rigidly bolting an IMU to a printer frame or drone arm couples mechanical resonance directly into the readings; soft-mount with foam or silicone grommets for anything sensitiveAn IMU is one of the few sensors where the hardware is almost never the hard part — a $2 breakout board and four wires get you raw data in minutes. The real work is in the fusion math and calibration routine that turns that raw data into something a control loop can trust. Start with a complementary filter on a 6-DOF sensor to get something working, and only reach for a full Kalman or Madgwick implementation once you've confirmed the simple version isn't accurate enough for what you're building.
Related Guides
- I2C vs SPI vs UART: How to Choose and Use Serial Communication Protocols
- I2C Wiring and Protocol Guide for Arduino, ESP32, and Raspberry Pi
- Shift Registers and I/O Expanders for Arduino and ESP32: 74HC595, MCP23017, and PCF8574 Explained
- Battery Fuel Gauge ICs for Lithium Projects: MAX17048, BQ27441, and Coulomb Counting Explained
- Real-Time Clock Modules for Arduino and ESP32: DS3231 vs DS1307, Battery Backup, and NTP Sync
- Capacitive Touch Sensing for Makers: TTP223, MPR121, and ESP32 Native Touch Pins
- How to Program Addressable LED Strips: WS2812B Patterns, Effects, and Power Design
- How to Use Sensors with Arduino and ESP32: Temperature, Distance, Load, Current, and Hall Effect