Arduino Arduino Modules Communication Display & LEDs Movement & Distance

MPU6050 Arduino Spirit Level: DIY Digital Level With OLED Display

DIY Daily 5 min read

Introduction

In construction, carpentry, photography, and robotics, ensuring a surface is perfectly level is critical.

Traditional bubble spirit levels have been used for centuries, but the MPU6050 enables greater precision and automation.

In this comprehensive tutorial, you will learn how to build your own DIY Arduino Digital Spirit Level. By combining an Arduino microcontroller, an MPU6050 accelerometer/gyroscope sensor, an OLED display, and visual LED indicators, this smart measuring device calculates real-time Pitch and Roll angles, displaying them numerically while warning you of alignment deviations.

Components Required

To assemble this project, gather the following hardware components:

  1. Arduino Board (Arduino Nano or Uno)
  2. MPU6050 6-Axis Accelerometer and Gyroscope Module
  3. 0.96-inch I2C OLED Display (128×64 pixels)
  4. Active Buzzer (for audio feedback when level)
  5. LEDs (Red, Green, Blue) with 220Ω current-limiting resistors
  6. Breadboard and Jumper Wires
  7. USB Cable for power and programming

Circuit Wiring Guide

Connect the components to your Arduino as follows:

  • MPU6050 Module:
    • VCC ==> 5V
    • GND ==> GND
    • SCL ==> A5 (SCL on Uno) / Pin 22 (on Mega)
    • SDA==> A4 (SDA on Uno) / Pin 20 (on Mega)
  • OLED Display (I2C):
    • VCC ==> 3.3V or 5V (check module spec)
    • GND ==> GND
    • SCL ==> A5
    • SDA ==> A4
  • Indicators & Buzzer:
    • Green LED ==> Digital Pin 4 (Indicates Level)
    • Red/Yellow LEDs $\rightward Digital Pins 5 & 6 (Indicate Tilt)
    • Buzzer ==> Digital Pin 7

Arduino Source Code

Below is the complete, production-ready Arduino code to run the digital level measuring device. Make sure you have installed the Adafruit GFX, Adafruit SSD1306, and Wire libraries via the Arduino Library Manager.

Arduino Code:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// MPU6050 I2C address
const int MPU = 0x68; 
float AccX, AccY, AccZ;
float pitch, roll;

// Pin definitions
const int greenLED = 4;
const int redLED = 5;
const int buzzer = 7;

void setup() {
  Serial.begin(115200);
  
  // Initialize I2C and MPU6050
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B); // PWR_MGMT_1 register
  Wire.write(0);    // Set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  // Initialize OLED display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  
  pinMode(greenLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(buzzer, OUTPUT);
  
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 10);
  display.print("MPU-6050 Digital Level");
  display.display();
  delay(2000);
}

void loop() {
  // Read accelerometer data
  Wire.beginTransmission(MPU);
  Wire.write(0x3B); // Starting register for accelerometer readings
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true);
  
  AccX = (Wire.read() << 8 | Wire.read()) / 16384.0;
  AccY = (Wire.read() << 8 | Wire.read()) / 16384.0;
  AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0;

  // Calculate Pitch and Roll angles in degrees
  pitch = atan(AccX / sqrt(AccY * AccY + AccZ * AccZ)) * 180 / PI;
  roll = atan(AccY / sqrt(AccX * AccX + AccZ * AccZ)) * 180 / PI;

  // Update OLED Display
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(30, 0);
  display.print("MPU-6050");
  
  display.setCursor(10, 20);
  display.print("P: ");
  display.print(pitch, 2);
  display.print(" deg");

  display.setCursor(10, 40);
  display.print("R: ");
  display.print(roll, 2);
  display.print(" deg");
  
  display.display();

  // Check if surface is level (within a +/- 1 degree tolerance)
  if (abs(pitch) <= 1.0 && abs(roll) <= 1.0) {
    digitalWrite(greenLED, HIGH);
    digitalWrite(redLED, LOW);
  } else {
    digitalWrite(greenLED, LOW);
    digitalWrite(redLED, HIGH);
  }

  delay(100);
}
#arduino #Arduino Sensor #MPU6050 #OLED Display #sensor

DIY Daily

Electronics tinkerer and tutorial writer at DIY Daily.

Leave a Comment

Your email address will not be published. Required fields are marked *