How I Developed the Scout Flight Controller, Part 11: Bonus Code
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!