P-07 // Started

3D Printed Drone

A custom STM32 quadrotor controller: IMU-to-PWM embedded control, plus a separate MATLAB study of PID, LQR, constrained MPC and aided navigation EKF.

Hardware prototype ยท Simulation validated
  • STM32
  • Sensor fusion
  • LQR
  • MPC
  • MATLAB
  • 3D printing
Open repository
3D Printed Drone project

I built a quadrotor and its flight-control software from scratch, from raw IMU registers to motor PWM. A separate MATLAB study explores navigation estimation and constrained control without presenting simulation as flight evidence.

Hardware

Custom 3D-printed plus-configuration frame, EMAX ECO II 1700 KV motors, 7-inch three-blade propellers, 40 A PWM ESCs and a 4S 2200 mAh battery. First remote-controlled flight: October 2025.

Assembly2

Simulation

The current MATLAB repository model has 12 motion states and four squared-rotor-speed inputs. PID, LQR and constrained linear MPC run at 20 Hz; the nonlinear plant, IMU and navigation EKF advance at 200 Hz.

Historical visualisations: the following Simulink/Simscape image, hover/circle clips and plots document earlier work. They are preserved but are not the current comparison or hardware flight recordings.

Earlier simulated hover and circle tracking, with wind-force visualisation.

sim_image

Current MATLAB study

A 2 m-radius circle at 2.5 m altitude, with a 30 s period and smooth start. All controllers share motor bounds and command-rate limits. Sensed cases use the same EKF design and matched noise sequences, never ground-truth controller feedback.

With wind and 40 ms motor lag, recorded 3D tracking RMS is 5.63 cm (LQR), 5.17 cm (MPC) and 11.39 cm (PID). Simulation only: assumed fixed RTK-GNSS/magnetic aiding, not physical flight accuracy or a universal controller ranking.

Current MATLAB simulation: circle tracking by LQR, MPC and PID with noisy sensors, wind and motor lag
Current repository study: nonlinear plant and shared navigation EKF design.
xyz_tracking_cricle
circle_tracking

Electronics

  • Processor: STM32G431KBT6, Cortex-M4 at 170 MHz.
  • Active sensor: MPU6050 accelerometer/gyro over I2C.
  • RC: four PWM channels, interrupt-driven input capture and digital low-pass filtering.
  • Output: four ESC PWM signals.
  • Carrier board: ultrasonic rangefinder, ESP32 and PWM breakout. These peripherals are not evidence of an active altitude/navigation loop in the public firmware.

Embedded control

schematics
PCB

A nominal 1 ms loop reads the IMU, estimates roll/pitch, runs control and updates ESC PWM; polling TIM6 pads the remaining period. The MPU6050 is configured for 200 Hz output, so loop reads are not necessarily fresh 1 kHz measurements. Boot includes stationary gyro averaging and an ESC calibration sequence. Timing is nominal, not a measured deadline guarantee.

The checked-in path uses a complementary attitude filter and roll/pitch PD. Yaw mixing and thrust are command inputs, not closed-loop heading or altitude estimates. The main loop zeros roll/pitch/yaw stick references for level-reference testing. A scalar angle KF is an alternative.

Separate drone pipelines: embedded IMU attitude fusion and PD to ESC PWM; MATLAB navigation EKF to PID, LQR or MPC and nonlinear plant.
Embedded prototype and MATLAB navigation study are separate implementations.

Attitude fusion and PD

χ̂k = (1 − λ)(χ̂k−1 + Tωmapped)

+ λχacc,k,   λ = 0.02

e = χref − χ̂

τχ = kpe + kdLPF(Δe/T)

χ: roll/pitch. Board mapping: roll uses −gy, pitch uses gx; this is not a general 3D attitude solution.

The alternate scalar KF integrates gyro angle: A = H = 1, B = T, with accelerometer correction. Gain/covariance update each sample; there is no explicit gyro-bias state.

State-space models

Rigid-body dynamics and mixing

Thrust/drag scale with ui = ωi2. For position r, navigation velocity v and Euler angles η = [φ, θ, ψ]T:

[T, τx, τy, τz]T = Mu

M =ktktktktlkt0−lkt00lkt0−lktd−dd−d

l: arm length; kt: thrust coefficient; d: rotor drag coefficient. Inverse mixing, nonnegative bounding, square root, then ESC conversion.

ṙ = v

v̇ = (T/m)Rbne3 − ge3 + Fw/m

IΩ̇ = τ − Ω × (IΩ)

Ω = E(η)η̇

R rotates body to navigation axes. E maps ZYX Euler rates to body rates. Fw: simulated wind. I: diagonal body inertia.

E =10−sinθ0cosφsinφ cosθ0−sinφcosφ cosθ

Hover model: LQR and MPC

At level hover: T = mg, uh = mg/(4kt). Linearising gives ẍ = gθ, ÿ = −gφ. With x = [r; η; v; η̇] and δu = u − uh1:

ẋ = Ax + Bδu

A =00I30000I30G000000G =0g0−g00000B =06×4BvBη

A is 12×12; displayed entries are 3×3 blocks.

mBv/kt =000000001111Bη =lkt/Ix0−lkt/Ix00lkt/Iy0−lkt/Iyd/Iz−d/Izd/Iz−d/Iz

Ad = exp(ATs)

Bd = ∫0Tsexp(At)B dt

xk+1 = Adxk + Bdδuk

uk = uh1 − K(x̂k − xref,k)

Exact zero-order hold, Ts = 0.05 s. LQR uses state-error/motor-effort costs. Wind and motor lag are absent from the LQR/MPC design model but present in the disturbed test plant.

MPC: 40-sample prediction (2 s), 20 control moves, first move applied. Motor bounds and 0.2uh command-step limits are constraints. Simulation PID: position PI/velocity feedback requests acceleration; attitude control generates torque with feedforward and anti-windup. Neither runs in the published STM32 path.

Navigation EKF: simulation only

The 15-state additive Euler-angle EKF estimates ζ = [r; v; η; ba; bg]. The accelerometer measures body specific force:

ṙ = v

v̇ = Rbn(fm − ba) − ge3

η̇ = E−1(Ωm − bg)

ḃa = wa,   ḃg = wg

Bias random walks; averaged adjacent IMU samples, Δt = 0.005 s.

Integrate constant acceleration over one sample, then linearise at the estimate. The resulting 15×15 transition uses 3×3 blocks:

F =IΔt I½Δt2Ja−½Δt2R00IΔt Ja−Δt R000I + Δt Jq0−Δt E−1000I00000I

R = Rbn. Ja: attitude derivative of rotated specific force; Jq: attitude derivative of Euler-rate mapping. MATLAB uses central-difference Jacobians. This is a local EKF model, not constant LTI.

Simulated RTK-GNSS at 10 Hz corrects position/velocity; magnetic field readings at 20 Hz correct attitude:

HGNSS =I606×9Hmag =03×6Jm03×6

zmag = RTmn + nmag

Jm: attitude derivative of the magnetic prediction. Sequential corrections use Joseph covariance updates. Assumed RTK accuracy requires a fixed solution; outages, latency and vibration are not validated.

Controllers receive reordered estimated position, Euler angles, velocity and bias-corrected Euler rates. Truth is only used for the plant, sensor synthesis and scoring.

Hardware tests and validation

I progressed from simulation to suspended-axis tuning and remote-controlled flight in October 2025. The preserved electronics images and older controller/estimator plots above are development material, not proof that MEKF, altitude KF or drag-based velocity estimation runs in the current public firmware.

Repository host tests cover C estimation and mixing modules, not the complete sensor driver or flashed firmware. MATLAB tests cover plant linearisation, motor constraints and noisy/disturbed navigation runs. They do not establish a flight-ready autonomous stack. RTK integration and autonomous flight remain future work.

The drone was mainly tuned in simulation and later on tuned by axis by hanging the drone on strings. This led to rather unstable flight, especially using the pid controller. The ESP with wifi connectivity then allowed fine tuning during flight to stabilize the drone.

20241222_141643