
If you have ever hung a picture frame or built a shelf, you know how crucial a level is. Traditional bubble levels are great, but what if you need to measure an exact 45-degree angle? Or what if you want an audible beep when your surface is perfectly flat so you don’t have to keep looking at it?
In this project, we are going to build a Digital Smart Level and Pitch Monitor. By combining the incredibly precise MPU6050 Accelerometer/Gyro with a crisp 0.96” OLED Display (I2C) and an Active Buzzer Module, we’re creating a tool that belongs in every maker’s workshop.
The MPU-6050 constantly measures the pull of gravity on three different axes (X, Y, and Z). By doing some clever math (which the Arduino handles for us), we can calculate the exact “Pitch” and “Roll” of the sensor.
We’ll display these real-time angles on the OLED screen. As a bonus, we’ll program the Arduino to trigger the active buzzer when both the pitch and roll hit exactly 0.0 degrees—meaning it is perfectly level!
To follow along with this project, you’ll need the following components:
Because both the MPU-6050 and the OLED display use the I2C communication protocol, wiring is incredibly easy. They can actually share the same two pins on the Arduino!
OLED Display & MPU-6050 (I2C Bus):
Active Buzzer:
To make this work, you’ll need to install the Adafruit MPU6050, Adafruit SSD1306, and Adafruit GFX libraries via the Arduino Library Manager.
Here is the complete code to run your Smart Level:
#include <Wire.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.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);
Adafruit_MPU6050 mpu;
const int buzzerPin = 8;
const float levelThreshold = 1.0; // Degrees of tolerance
void setup() {
Serial.begin(115200);
pinMode(buzzerPin, OUTPUT);
digitalWrite(buzzerPin, LOW);
// Initialize OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
display.setTextColor(WHITE);
// Initialize MPU6050
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip");
while (1) {
delay(10);
}
}
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
}
void loop() {
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
// Calculate Pitch & Roll from accelerometer data
float pitch = -(atan2(a.acceleration.x, sqrt(a.acceleration.y*a.acceleration.y + a.acceleration.z*a.acceleration.z))*180.0)/M_PI;
float roll = (atan2(a.acceleration.y, a.acceleration.z)*180.0)/M_PI;
// Update Display
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
display.println("Digital Smart Level");
display.setTextSize(2);
display.setCursor(0, 20);
display.print("P: "); display.print(pitch, 1); display.println((char)247);
display.setCursor(0, 45);
display.print("R: "); display.print(roll, 1); display.println((char)247);
display.display();
// Check if Level (within threshold)
if (abs(pitch) < levelThreshold && abs(roll) < levelThreshold) {
digitalWrite(buzzerPin, HIGH); // Beep!
} else {
digitalWrite(buzzerPin, LOW); // Silence
}
delay(100);
}
Once you upload the code, securely tape or mount your breadboard to a flat, sturdy object (like a small piece of wood or an empty Altoids tin). As you tilt the object, you’ll see the exact degrees update instantly on the OLED. Once you hit exactly 0 degrees (within our 1.0 degree tolerance threshold), the buzzer will sing!
You’ve just built a precision measurement tool using less than $20 worth of parts. Happy making!