Show HN: Tacocopter – My Custom Flight Controller Programmed in Rust
by njfdev | 2025-12-05 23:40:32+00:00
Hey HN!

I’m Nicholas Fasching, a young hobbyist developer of almost a decade now! I am not satisfied sitting around and doing nothing, so going into 2025, in January of this year, I began planning my next big project.

I wanted something difficult that I could put a lot of time into, where I could use my programming skills to make something happen in the real world. Thus, I settled on making a drone, lovingly called Tacocopter. But this wasn’t just any drone. I was going to fully program the flight controller from scratch, and to make it even harder, all in Rust!

After some research, I started my journey by only ordering the parts for the brains of the drone: a Raspberry Pi Pico 2 microcontroller with various sensors (IMU, barometer, an ELRS receiver, and a GPS module). I put together all these parts on a breadboard, then I began to program the foundation I would need for when I would order the actual drone parts in the future.

I had 4 main interesting challenges during this phase:

1) How to actually program a Pico in Rust? - Rust isn’t commonly used here, as you’d traditionally use something like MicroPython or C++ in the Arduino IDE. But, I ended up discovering and using a lower-level Rust framework called Embassy, which took more effort but also taught me a lot about embedded programming. 2) Debugging and controlling the flight controller? - Rust embedded development has few solutions for debugging, and after much research and experimentation, I ended up developing a custom desktop app in Rust that would control and communicate with the flight controller over USB with a custom data protocol. 3) How to use the GPS module? - I ordered an HGLRC M100-5883 GPS, but it had a connector I couldn’t connect anywhere, so I ended up carefully disassembling the wires from the connector and “Frankensteining” them with some other jumper wires I had. I also had the issue that there were absolutely no pre-existing libraries for this GPS already written in Rust. So, I had to read lots of documentation and write my own driver in Rust, which taught me a lot about hardware communication interfaces and how GPS positioning actually works! 4) How to get radio controller signals? - I ordered an ELRS-compatible transceiver along with an ELRS controller. Similar to the GPS, there was no existing Rust code for the ELRS protocol, and so I had to program it on my own. Unfortunately, the documentation was much less clear, and I ended up having to make some educated guesses and read code examples from existing libraries. It was a struggle, but it was super gratifying to see my controller inputs appear in real time!

I also got all the other necessary prerequisites, such as using the IMU to estimate the drone’s orientation with a Kalman filter and getting altitude measurements from both the ultrasonic sensor and barometer.

I was finally ready to order the drone parts, and after much deliberation, I decided to go with the HolyBro S500 kit. I wanted a bigger drone so I could have enough room for my somewhat large flight controller (because it was on a standard-sized breadboard). By this time, it was June, and when my order came, I began my 2-month-long grind over the summer to make it fly.

By this time, I had heard about Hack Club’s Summer of Making program, and having taken part in previous Hack Club programs before, I excitedly took part. One of the biggest positives I got out of it was that it forced me to regularly document my work (which is a skill I wish I had developed earlier in my life).

Anyway, my new challenge was how to control the brushless motors. I ended up deciding on controlling them through a digital protocol called D-Shot, which provided the benefits of faster control and more reliability compared to other methods. I initially tried programming the protocol myself (which was a miserable failure), but came across an existing implementation for Embassy! Unfortunately, it had some bugs, but using a logic analyzer and my time, I was able to fix them. Thus, I had working motor control!!

I then spent about the next 2 weeks trying to get it flying in my room (while trying not to annoy everyone in the house with its tremendous noise!). During this process, I had lots of PID tuning and code tweaks.

But, at one point, I had one big failure that made me rethink some shortcuts I previously made. In these earlier tuning phases, my wiring was messy, and some of the wires stood up so tall that if there was a sudden jolt, they could go into the spinning blades. I had a bug in my code that could make it freak out if it accidentally spun too much, and during a test flight, one of the landing legs bumped the ground, causing it to spin and trigger that bug…

The drone aggressively spun around, and I heard the ELRS transceiver get ripped off and flung across the room. Luckily, I had previously programmed a safety measure to disarm the drone if the ELRS signal was lost, which it did (this may have been worse if I hadn’t). After inspection, both the antennae on the transceiver were ripped off, with one of the pads torn off in the process. Since the transceiver had a backup antenna pad, I was able to, and still, use this same transceiver. But this event definitely spooked me and taught me not to take shortcuts when dealing with something potentially dangerous. Therefore, I completely redid the wiring to be much safer before continuing to fly.

Following this, I was able to get it flying…finally! I spent some time trying to get it to automatically hold its vertical position (but I have postponed this feature because I decided there were more important things to work on). I also had to make a custom driver and modify a connector for the PM02D power module, which allows me to supply the correct voltage to my board and estimate battery charge so the drone doesn’t die while I’m flying it.

But my biggest issue was stability and reliability, which was my most frustrating problem, taking almost 2 months to figure out. I had 3 major crashes, each breaking propellers (causing me to have to order new ones). These were mostly caused by buffer overflow errors mid-flight due to my UART implementation for the ELRS transceiver and GPS.

In terms of stability, it was very shaky (which caused the motors to dangerously heat up). I assumed for the longest time that this was a PID tuning issue, and I spent an insane amount of time developing an onboard logging system to help me better tune (I could make an entire extra write-up about all the issues I had with that).

Alongside this, I tried optimizing my code to make it faster, including techniques such as multithreading my code across the Pico’s two cores, overclocking its base speed of 150MHz to 300MHz (which took surprisingly a lot of effort), and greatly increasing the ultrasonic sensor performance by writing a custom PIO (Programmable I/O) assembly program for it (I learned a lot about PIO and it is quite interesting if you ever work with Raspberry Pi Picos!).

These optimizations allowed me to increase the control loop speed from 250 Hz to 500 Hz, and that made my drone fly beautifully! The issue before was that it just didn’t update fast enough! Now, the motors no longer get extremely hot, and the drone is flyable. I found that it is actually just fun to fly, and that is currently my biggest use for it.

I then made a showcase video and uploaded it to YouTube (https://www.youtube.com/watch?v=A8tR219AC94), as well as submitted my project to the Hack Club Summer of Making program: https://summer.hackclub.com/projects/1496

This was the most fantastic project I have ever worked on! I learn so much, including embedded programming in Rust, writing custom drivers with little to no documentation, and learning that taking shortcuts can be dangerous.

I have some special compute and vision hardware, and I plan to add some autonomous flight and environmental mapping in the future.

I hope you enjoyed my journey, and I’d love to hear your thoughts and feedback!