ESP32 Drone Firmware: Motor, Tilt and Balance Code

Upload these three sketches in order with the Arduino IDE (ESP32 board package). First test each motor, then read the tilt sensor, then let the ESP32 balance the drone.

Check before the next step

Safety: Props off for all three tests on your desk.

Sketch: Motor test

// Step 1: spin each motor for 1 second. TAKE THE PROPS OFF.
const int motorPins[4] = {25, 26, 27, 14};  // FL, FR, RL, RR

void setup() {
  for (int i = 0; i < 4; i++) {
    ledcAttach(motorPins[i], 20000, 8);  // 20 kHz PWM, speed 0-255
    ledcWrite(motorPins[i], 0);
  }
}

void loop() {
  for (int i = 0; i < 4; i++) {
    ledcWrite(motorPins[i], 60);   // gentle test speed
    delay(1000);
    ledcWrite(motorPins[i], 0);
    delay(500);
  }
  delay(3000);
}

Sketch: Read tilt

// Step 2: read roll and pitch from the MPU6050.
#include <Wire.h>
const int MPU = 0x68;

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);                 // SDA, SCL
  Wire.beginTransmission(MPU);
  Wire.write(0x6B); Wire.write(0);    // wake sensor up
  Wire.endTransmission();
}

void loop() {
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);                   // accelerometer data starts here
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6);
  int16_t ax = Wire.read() << 8 | Wire.read();
  int16_t ay = Wire.read() << 8 | Wire.read();
  int16_t az = Wire.read() << 8 | Wire.read();

  float roll  = atan2(ay, az) * 180 / PI;
  float pitch = atan2(-ax, sqrt((float)ay * ay + (float)az * az)) * 180 / PI;
  Serial.printf("Roll: %.1f  Pitch: %.1f\n", roll, pitch);
  delay(100);
}

Sketch: Balance

// Step 3: simple P balancer. It speeds up the motors on the low side.
#include <Wire.h>
const int MPU = 0x68;
const int motorPins[4] = {25, 26, 27, 14};  // FL, FR, RL, RR
float Kp = 1.5;    // proportional gain
int base = 110;    // test throttle (props OFF!)

void setMotor(int i, float speed) {
  ledcWrite(motorPins[i], constrain((int)speed, 0, 255));
}

void setup() {
  Wire.begin(21, 22);
  for (int i = 0; i < 4; i++) ledcAttach(motorPins[i], 20000, 8);
}

void loop() {
  // read roll from MPU6050...
  float roll = 0; // sensor value
  float error = 0 - roll; // target is 0° level
  float correction = error * Kp;

  setMotor(0, base + correction); // Left motors
  setMotor(2, base + correction);
  setMotor(1, base - correction); // Right motors
  setMotor(3, base - correction);
  delay(10);
}

See this step in 3D