Alexandre DuteauResume
← All projects

Embedded
In progress
Personal project · co-built with a friend · in bench bring-up

Micro Quadcopter

A mini quadcopter designed from the ground up: custom flight controller, from-scratch firmware, and every part selected by hand.

Rather than assembling an off-the-shelf flight controller with stock firmware, we're building the whole stack ourselves. The flight controller is an ESP32 with an MPU-6050 IMU on a custom board, talking to a RadioMaster ELRS receiver over CRSF at 420 kbaud and driving a BLHeli_S 4-in-1 ESC on four 1104 brushless motors. Power is a 3S 450mAh LiPo through a 5V buck converter, and there's an analog FPV link to a Quest 2 headset.

The firmware is C/C++ on PlatformIO, structured as five independently testable modules: CRSF parsing, sensor fusion, PID stabilization, quad-X motor mixing, and failsafe. We deliberately chose an IMU library that exposes raw registers rather than onboard DMP fusion, so the complementary filter (98% gyro, 2% accelerometer, with 500-sample bias calibration) is written by hand. Before any RF hardware was bound, we validated the CRSF parser with a loopback test where the ESP32 builds valid frames itself, CRC-8 polynomial 0xD5 and all, writes them out its own TX pin, and parses them back on RX.

Getting here involved a thrust-to-weight analysis that flagged a 2S under-volting risk on the motors, a correction after checking manufacturer specs, and a switch to 3S and a lighter 20A ESC. Pin assignment was cross-checked against the board's actual pinout, excluding strapping, JTAG, and input-only pins, with a firmware-only fallback for a PSRAM conflict on the UART pair. Stretch goals are altitude hold, position hold, and target tracking.

Bench bring-up so far has mostly been a fight with the IMU. The GY-521 breakout turned out to carry a clone chip that reports a WHO_AM_I of 0x72 instead of 0x68, which sent the library's accelerometer calibration to the wrong offset register, where it never converged. The firmware now reads the ID itself, accepts both, and runs a ported calibration routine against the legacy register directly. Along the way we wrote wiring diagnostics that can tell a short to ground from an unpowered module from a healthy bus, and an I2C recovery routine that clocks SCL up to nine times to free a stuck line.