How I Developed the Scout Flight Controller, Part 11: Bonus Code

Tim Hanewich
4 min readOct 2, 2023

--

This article is part of a series documenting the development of a custom quadcopter flight controller from scratch. For a list of the other related articles, please refer to the introductory article found here.

At this point in my series, I will share any bits of code that were useful at some point during development, perhaps may still be incorporated into Scout’s source code today, or otherwise are no longer used.

Firstly, you can find the full repository of the Scout Flight Controller’s source code on GitHub here.

Many of these code snippets can be used in similar projects or in other projects using the same components. I hope these are helpful!

MPU-6050 MicroPython Driver

Probably the most reusable component of this project that can easily be used in any other project is my MPU-6050 driver.

This is a very lightweight module that allows you to very easily read accelerometer and gyroscope data from an MPU-6050.

You can find the source code of my MPU-6050 MicroPython driver here.

I described how to use this class a bit in an earlier chapter about the MPU-6050.

ESC Calibration Script

All four of the electronic speed controllers must be calibrated to ensure the throttle commands being sent to each are even across all four. I wrote a basic script for performing this ESC calibration that you can find on GitHub here.

While this script is specifically designed for the ESC’s I purchased and used during this project, I believe most ESCs follow the same, if not a very similar, calibration process.

Analog Potentiometer to PWM Converter

I wrote a basic script that converts the signal from an analog potentiometer into a digital pulse width modulation that can be used to drive a motor via an ESC. Thus, you can easily control a BLDC through an ESC with a potentiometer during testing.

You can find this script on GitHub here.

NonlinearTransformer

When interpreting the level of thrust to apply given a given level of throttle input, we have to consider that we don’t want the quadcopter to become “twitchy”; we don’t want it to react too strongly to minor throttle/attitude commands it is receiving from the pilot. So, to “ease in” these inputs while also maintaining the same level of performance at the far reaches of these inputs, I developed the NonlinearTransformer class.

This class will transform any percentage level of input (0%, or 0.0 to 100%, or 1.0) to a Nonlinear equivalent. In other words, this class “softens” the input and introduces the input more gently. For example:

We see two graphs above. In the first, there is a linear relationship between input (X) and output (Y). 25% throttle will yield 25% thrust. In the second, on the right, there is a nonlinear relationship between input and output. 25% input will result in 10% throttle. Using this NonlinearTransformer class as a middle layer between the direct control input and the applied levels of thrust can make the drone feel less “twitchy” and smoother to fly.

You can find the NonlinearTransformer class in the toolkit.py module that is still part of Scout's source code.

ControlCommand

Originally, my plan was to send packets of data over UDP to control Scout on a local network. I later pivoted to using the RC receiver and transmitter discussed previously, but some of the remnants of the original implementation still remain.

I wrote the ControlCommand class as a data packet that contains the throttle, roll, pitch, and yaw. Each of those four are floating point numbers and intended to be between either 0.0 and 1.0 or -1.0 and 1.0. This class also has a frame property. This integer is incremented upwards with each packet that is sent; this serves as a validation to ensure the packet the quadcopter received most recently is indeed the most recent and not one that simply arrived late.

This ControlCommand class has easy methods for serializing the packet into a series of bytes, using the encode method, and then deserializing on the client side (quadcopter side), using the decode method.

You can find the ControlCommand class in the toolkit.py module that is still part of Scout's source code.

PIDCommand

Similar to the ControlCommand class, I also originally had an implementation that would allow me to update the quadcopter's PID tuning values on the fly (without having to re-flash the code). I designed the PIDCommand class for packaging a series of PID gain values (proportional gain, integral gain, derivative gain) and the intended axis, and then serializing these into a series of bytes which can be delivered to the quadcopter. The quadcopter would then unpackage these bytes and make the PID gain changes in the software.

You can use the encode and decode methods of the PIDCommand class for this. You can find the PIDCommand class in the toolkit.py module that is still part of Scout's source code.

That’s all… for now!

Thank you to all of you that followed along in this series. I truly hope my writings are of value. I’m sure this series will sit online for quite some time and maybe be used by an aspiring developer who just wants to make something cool, just as I was when I started this project.

Please reach out to me on Twitter/X @TimHanewich with any questions. Thank you!

--

--