Guide to The DIY Micro Drone: Building a Brushed Motor Quadcopter with ESP32 and a 3D-Printed Frame

The DIY Micro Drone: Building a Brushed‑Motor Quadcopter with ESP32 & a 3D‑Printed Frame

A step‑by‑step, code‑ready guide for hobbyists who want a lightweight, affordable quadcopter that flies straight out of the box.

Introduction

Building a micro drone from scratch feels like a rite of passage for makers. This tutorial focuses on a brushed‑motor quadcopter because brushed units are cheap, easy to control, and perfect for beginners. The brain of the aircraft is an ESP32 development board, which gives you Wi‑Fi, Bluetooth, and plenty of I/O pins for future upgrades. All structural parts are 3D‑printed, meaning you can tweak the design without ordering new metal brackets.

By the end of this guide you will have a fully assembled, calibrated, and flight‑tested micro drone that can be controlled via a simple web interface.

Required Components

Item Specification Typical Source
ESP32‑DevKitC Dual‑core, 240 MHz, 520 KB SRAM Banggood, AliExpress
Brushed Motors (×4) 130 kv, 30 mm Ø, 12 V max HobbyKing
Electronic Speed Controllers (×4) 5‑V–12‑V, 10 A brushed Aliexpress
Lithium‑Polymer Battery 7.4 V, 350 mAh, 30 C eBay
3‑Axis Gyro/Accelerometer (MPU‑6050) I2C, ±2000 °/s SparkFun
3D‑Printed Frame PLA, 30 mm × 30 mm × 10 mm Print yourself (STL provided)

1. Designing & Printing the Frame

A sturdy yet lightweight frame is the foundation of stable flight. Download the STL file and print with the settings below:

  • Layer height: 0.2 mm
  • Infill: 30 % (grid)
  • Print speed: 55 mm/s
  • No support structures required

After printing, sand the motor mounts lightly to ensure a snug fit. Tip: add a thin layer of epoxy to the screw holes for extra durability.

2. Wiring the Electronics

The wiring layout is simple: each ESC connects to a motor and to the ESP32 power rail. Below is a visual diagram and a concise pin‑mapping table.

Wiring Diagram Image
ESC Motor ESP32 Pin
ESC‑1 Front‑Left GPIO 18 (PWM)
ESC‑2 Front‑Right GPIO 19 (PWM)
ESC‑3 Rear‑Left GPIO 21 (PWM)
ESC‑4 Rear‑Right GPIO 22 (PWM)

3. Flashing the ESP32 Firmware

The following Arduino sketch implements a minimal flight controller: it reads the MPU‑6050, runs a PID loop, and outputs PWM signals to the four ESCs. Copy the code into the Arduino IDE, select ESP32 Dev Module, and upload.

#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;
const int motorPins[4] = {18, 19, 21, 22};

// PID constants (tune for your frame)
float Kp = 1.2, Ki = 0.04, Kd = 0.02;
float targetAngle = 0.0;
float integral = 0, previousError = 0;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  mpu.initialize();
  if (!mpu.testConnection()) {
    Serial.println("MPU6050 connection failed!");
    while (1);
  }
  for (int i = 0; i < 4; i++) {
    ledcSetup(i, 50, 16);          // 50 Hz, 16‑bit resolution
    ledcAttachPin(motorPins[i], i);
    ledcWrite(i, 0);               // ESCs stay idle
  }
  delay(2000); // allow ESCs to arm
}

void loop() {
  int16_t ax, ay, az, gx, gy, gz;
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  // Convert gyroscope reading to deg/s (sensitivity = 131 LSB/(°/s) for MPU‑6050)
  float pitchRate = gy / 131.0;

  // Simple complementary filter for pitch angle
  static float pitch = 0;
  pitch = 0.98 * (pitch + pitchRate * 0.01) + 0.02 * (atan2(ax, sqrt(ay*ay + az*az)) * 180 / PI);

  // PID control
  float error = targetAngle - pitch;
  integral += error * 0.01;
  float derivative = (error - previousError) / 0.01;
  float output = Kp * error + Ki * integral + Kd * derivative;
  previousError = error;

  // Map output to motor speed (1000–2000 µs pulse width)
  int pwm = constrain(map(output, -30, 30, 1000, 2000), 1000, 2000);
  for (int i = 0; i < 4; i++) {
    ledcWrite(i, pwm);
  }

  delay(10);
}

Quick calibration: Adjust Kp, Ki, and Kd while the drone is tethered until it hovers level for at least 3 seconds. Store the final values in EEPROM (code omitted for brevity) for future re‑use.

4. Adding a Simple Web‑Based Controller

The ESP32 can host a tiny web server. The snippet below adds a joystick‑style control page accessible from any smartphone on the same Wi‑Fi network.

#include <WiFi.h>
#include <WebServer.h>

const char* ssid = "MicroDrone_AP";
const char* password = "flyhigh123";

WebServer server(80);

// Global control variables
float throttle = 0;
float pitchCmd = 0;

void handleRoot() {
  String html = R"rawliteral(



Micro Drone Controller

)rawliteral"; server.send(200, "text/html", html); } void handleCmd() { if (server.hasArg("throttle")) throttle = server.arg("throttle").toFloat(); if (server.hasArg("pitch")) pitchCmd = server.arg("pitch").toFloat(); // Apply throttle & pitch to ESCs (simplified) int base = map(throttle, 0, 1000, 1000, 2000); int adj = map(pitchCmd, -1, 1, -200, 200); ledcWrite(0, base - adj); ledcWrite(1, base + adj); ledcWrite(2, base - adj); ledcWrite(3, base + adj); server.send(200, "text/plain", "OK"); } void setup() { Serial.begin(115200); WiFi.softAP(ssid, password); server.on("/", handleRoot); server.on("/cmd", handleCmd); server.begin(); // (Motor PWM init same as previous section) } void loop() { server.handleClient(); }

Connect your phone to the network MicroDrone_AP, visit http://192.168.4.1, and start piloting.

5. First Flight & Safety Checklist

  1. Battery check: Verify voltage is within 7.2‑8.4 V.
  2. Propeller orientation: All props must spin clockwise (CW) or counter‑clockwise (CCW) as labelled.
  3. Clear area: At least a 2 m × 2 m open space, no people or pets.
  4. Arming procedure: Power on, wait 3 seconds, then push the throttle stick to maximum for 1 second to arm.
  5. Hover test: Gradually lower throttle until the quad hovers ~30 cm. If it drifts, fine‑tune the PID constants.
“Never fly indoors until you have a stable hover. Small micro drones can bounce off walls and damage components.”

Ready to Start?

Become Part of the ICT Club Community

Many learners are already building the technology skills that improve their daily work performance. Your journey starts today.