
If you have ever hung a picture frame, you know how crucial a level is. But bubble levels are analog, boring, and they donât beep at you. In this project, we are going to build a Digital Smart Level. Weâll use an accelerometer to measure angles, draw a bubble on an OLED screen, and buzz loudly when itâs perfectly flat. Itâs entirely over-engineered, just the way we like it.
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!