Writing a flight controller. Follow my progress @

Similar projects worth following
Quadcopter flight controller built on a breadboard. Utilizing the C++14 compiler and taking advantage of all of the awesome features the standard library offers. I ended up modifying a good amount of the teensy3 core library as I went along, but it served as pretty great starting point to have a lot of features just "work". I decided to use FreeRTOS since it is so widely supported and easy to use, and I decided to build with a makefile because it offers much more flexibility than being tied to some IDE's build system. I had to modify the Teensy3.6 board in order to get access to SWD debugging, but that was also totally worth it :)Feel free to reach out with any comments or questions, and definitely take a look at the github page!

Aiming to improve in embedded firmware, electrical engineering, and software design. 

--- Features --------------------------------------------------------------

  • Makefile + SWD GDB upload and debug
  • FreeRTOS
  • BSP is essentially cores/teensy3
  • Dispatch queue for asynchronous and interval scheduling (100us tick interrupt)
  • Publish / subscribe communication framework
  • MPU9250 @ 1kHz gyro / accel / mag on 10MHz SPI
  • FrSky XM+ mini on UART SBUS
  • 400Hz PWM outputs for actuator control signals
  • 250Hz attitude estimation, 1kHz control. Complimentary filter attitude estimator using euler angles, [WIP] quaternion estimator w/ EKF
  • Data streaming in csv format over serial
  • Interactive plotting and visualizations with python and OpenGL

Things I'd like to do...

  • Telemetry radio to host
  • MAVLink over telemetry radio for QGC communication
  • Full quaternion estimation and control
  • Optical flow for position hold

--- Tools -------------------------------------------------------------------

  • make / cmake
  • GDB
  • JLink mini
  • Siglent SDS1202X-E
  • MCUXpresso
  • Lipow battery charger

--- Components -------------------------------------------------------

  •  Teensy 3.6 microcontroller board
  • MPU9250 3-axis gyro / accel / mag
  • FrSky XM+ Mini radio transmitter
  •  Blade Theory XL kit from amazon. Removed camera, radios, and flight controller board (leave the power distribution board attached).

Graphics Interchange Format - 453.40 kB - 09/22/2019 at 06:30


Graphics Interchange Format - 2.11 MB - 09/22/2019 at 06:28


Adobe Portable Document Format - 6.21 MB - 09/19/2019 at 07:32


MPEG-4 Video - 802.89 kB - 09/19/2019 at 07:31


Graphics Interchange Format - 8.03 MB - 09/19/2019 at 07:30


View all 6 files

  • 1 × Teensy3.6
  • 1 × MPU9250
  • 1 × FrSky XM+ mini
  • 1 × Blade Theory XL kit
  • 1 × 4S LiPo

View all 6 components

  • It can fly, but there's lots of ways to improve

    Jacob Dahl09/24/2019 at 00:30 0 comments

    I spent the best part of 2 days now trying to tune this thing to fly the way I want... it is not easy! The primary problem I am having is with attitude response. The rates response is solid, and by reducing the cutoff frequency of the gyro filter, I have really been able to tighten up the rates controller. Attitude control on the other hand has been a struggle. I want to ONLY use proportional gain, however I am seeing that at large angle errors the response is very sluggish, however I cannot crank up the P gain any higher otherwise I get oscillations at hover. I think this problem is more complicated than simply controller tuning, there is probably a significant effect from airframe vibration coupled with my rudimentary attitude estimator. I think moving to an EKF -- and fusing in mag data -- would clean up the attitude estimation around hover dramatically. I really should implement logging so that I can verify these suspicions... yet another thing to do.

    Overall I am extremely happy with the project, and I have effectively accomplished what I set out to do: make a drone fly. I will surely work on this project off and on for quite some time, but for now I want to turn my attention to solving real world problems. This has been a great learning exercise and an awesome experience, I can't wait for what's next!

  • First flight

    Jacob Dahl09/22/2019 at 22:15 0 comments

    Spent the first few hours of the day getting everything ready for flight testing. I implemented the yaw controller, added the plumbing, and found some ballpark gains. I fiddled with the rate controller gains for Pitch and Roll a little bit more, and then began iterative flight testing for fine tuning the gains. I realized quickly that I needed a level horizon calibration, so I implemented that. The vehicle felt slugging and hard to control, requiring a lot of over compensation with the sticks. I realized I need both stick expo as well as to allow the attitude controller to command a higher angular rate setpoint to increase responsiveness. Increasing the maximum angular rate made my P gain for the attitude controller too high, so I had to dial that back as I cranked up the max allowable rates. It took a little while to find the sweet spot for attitude controller gains, stick expo, and max angular rates, but I finally landed on something that feels solid. 

  • Houston, we have lift off!

    Jacob Dahl09/22/2019 at 05:35 1 comment

    Ha, it's always funny to look back at yesterday's problem after having solved it. You feel so dumb for not seeing it right away! It's a bittersweet feeling, but the feeling of solving a hard problem -- even if it was only hard because you're a simpleton -- feels so good. 

    Last night, after depleting all of my batteries juice and retiring to relaxation, I realized what was wrong. I was trying to tune for both impulse response and steady state. The problem was, I was trying to put the quad on edge. This is absolutely not helpful. I got confused by the language in the PX4 docs about the rate tuning process, where it was suggested to tilt the vehicle on edge to tune the I gain. I realize now that they were implying while flying the vehicle. Duh. The test fixture was effectively a moment arm on the quad as soon as it rotated about the dowel! After reading many articles on the interwebs, I decided to only test for impulse response (poke the drone) and step response (oscillate with fixed speed between shallow angles). I started by finding the correct P gain (2/3 * frequency_begin_oscillations) and then dialed in D with P and I set to zero. After finding "ballpark" values for P and D. I used the step response to factor in I gain, and dialed P back a bit further...

    ...Rate controller tuned!

     I am not sure the impact of this overshoot in the step response, and I am also a little bit concerned about the rise time. I was primarily trying to avoid heavy ringing and in some cases minor high frequency oscillations with previous more aggressive tunes I had set up. 

    Next was the attitude controller, but that's just P gain so was quite easy to find a good initial value. I did one last "hold in hand" test, and then went to flight test it. It flew! It was actually very smooth, although the attitude control was noticeably sluggish. I haven't implemented the yaw controller yet (been busy, stuff and things) so it is quite difficult to fly. The yaw controller should be quick and easy (rates only), so I am planning on tomorrow being a flight testing day!

  • Controller tuning

    Jacob Dahl09/21/2019 at 06:02 0 comments

    Put my batteries thru the ringer today. Scrounged the internet and began to experiment with some heuristics for PID tuning. Finally landed on a method that I am committing to. I think I am near the ballpark value I want to be at for `P`, I need to see how high I can take `D` such that I reduce overshoot / oscillations given a step input. I added in a little bit of `I` at the end, I think I need to reduce it or take it out until I dial in P and D. I should note, I am only tuning the pitch rate controller right now, so that's what these plots are.

    I am prefiltering the gyro data used for the control signal using a low pass filter with a cutoff of 80Hz. The gyro itself has a hardware DLPF at 92Hz. I am sampling the gyro at 1kHz, I might want to think about using a different kind of filter for the prefiltering.

    P =  0.3

    I = 0.06

    D = 3.0

    Step input: 10 degree step with angular rate of 60 dps

    Step input: 45 degree step with angular rate of 80 dps

    I need more `I` gain clearly, however I am not sure how to add it in without inducing oscillations. It looks like I overshoot quite a bit initially, which means the `P` gain could probably come down a little bit.

  • Built a test jig for controller tuning -- chaos ensues

    Jacob Dahl09/20/2019 at 05:14 0 comments

    I need to tune my rates controller, so I decided to build a jig. I ran by home depot and collected some supplies, and then stopped by Mark Sauder's house and he let me borrow some tools to create the jig, thanks Mark! Eager to get these controllers tuned and to use my newly built jig, I modified the code to only enable pitch rate control. Not knowing a good starting point for my gains, I chose P = 0.001 and left everything else at zero. As soon as I armed, the quad immediately started spinning around the dowel, promptly flinging the RC receiver off the breadboard. The kill switch on my controller is the only way to kill the motors. I stood there panicking for about 20 seconds as I watched it go round and round, the dowel visibly weakening with every violent rotation. I finally grabbed my nearby notebook and shoved it into the action. It took a few seconds to subdue the thrashing, but I was finally able to grab the battery and cut power. 

    Needless to say, the dowel on the jig snapped and my notebook is torn to shreds. I lost a diode on the FrSky while reworking it, so I fixed it by just shorting the pads. Thankfully everything still works, so I'm ready to try again tomorrow once I buy a new dowel. 

    Lesson of the day: strap down the damn receiver!!! (and write a better failsafe for drivers that crash..!!!!..@#!!)

    Update: I had motor wires 1/2 and 3/4 reversed. Doh.

    11:03 PM

  • Introduction -- first post

    Jacob Dahl09/19/2019 at 07:14 0 comments


    I almost finished this project and this is the first time I've really written anything more than what is in the README. I decided to take on this project in early August 2019. It has been a huge amount of work but I am extremely satisified with how far it has come given starting from nothing and having never designed an entire embedded system from scratch. I am eager to continue on with other projects, so I decided to hold off on the full quaternion estimation and control scheme, as it would be quite time consuming to fundamentally learn how the algorithms work (this project is about fundamentals). 

    A lot of the inspiration in design has been taken from PX4 and ROS. I favored reducing complexity and increasing ease of use by using the C++ standard library and STL. This does use more flash. This does use dynamic memory allocation (allocates once at the beginning). You do have to be more careful about what you do and how you do it. However it offers enormous flexability to write better code that is easier to understand. I didn't really implement anything more than "bare minimum" other than the DispatchQueue, which I used as a tool to familiarize myself better with FreeRTOS, timers, and scheduling in general.

    Smashed my  head into the wall trying to make the drone fly. Learned a lot, but definitely went at it with guns blazing and failed to notice obvious problems with the implementation. Fixed those problems and ultimately led me to understand what actually needs to be considered. Decided to build a test rig for tuning pitch/roll rate controllers. I will be able to independently control roll/pitch on a fixture with a rotating center beam, which the vehicle mounts to. I will also be able to connect via serial to view the data in real time thanks to my real time plotting python script. I have considered just writing the driver for a telemetry radio so I don't need hardwired PC serial... just one more thing to do. 

View all 6 project logs

Enjoy this project?



CarmenFay wrote 10/02/2022 at 17:19 point

TeensyFlight36 is a small airplane built for flying around the world. Its wingspan is just 36 inches, which means that it can carry up to two passengers at a time. It's powered by a single electric motor and propeller, and it can fly for up to an hour and 20 minutes on a single charge. It has a top speed of 56 mph and a range of 70 miles. I will find out the benefits of listening to music while reading because I have heard that You Read Relaxed when you listen to music.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates