Introduction: Quadcopter and DIY Flight Controller Basics

About: I've been working with robotics, programming and have been making things for 6 years now. My biggest achievement would be a drone that I made and programmed. I also entered the Hackaday 2017 prize with a cheap…

Hey guys!

This won't be an instructable "per se", but I'll write/talk about how I made my quadcopter and flight controller. I'll talk about the FC more, since I build it from ground in about a year. Mind you, it was not made with an Arduino, however, it's still in C, and the process is more or less the same.

The point of this is probably to tell you (if you are planning on making one yourself) what I wish I knew when I started making it and had no grouped information available. I hope you'll enjoy it!

You can also check out the video above!

Step 1: Hardware

Now these parts were bought pretty much on random, and probably they could be more energy and money efficient, but they work and it's not stupid if it works.

The main part is ofcourse the brain. It's Texas Instruments Tiva C microcontroller (TM4C123GH6PM). It runs on 80MHz, has many GPIOs and it's a bit more professional as Arduino. It also has pre-made libraries, but as said, they are more complex and allow more flexibility.

  • Props: 10x4.5
  • Motors: Multistar 2213 950kV
  • Battery: Multistar 3S 5200mAh
  • ESC: Afro ESC or any ESC that has 1000Hz refresh rate
  • Frame: 550X from Hobbyking
  • TX/RX: Turnigy TGY-i6 and iA6 6 channel receiver
  • IMU: MPU6050
  • Sonar: HC-SR04

It weights about 1200g and total cost should be around 250EUR. (only quadcopter and remote. Chargers, soldering iron, about a million propellers, 3 MPUs, 1 uC are calculated seperatly, few motors).

PROPS: Not much to say about that, if you are using 550 frame, 10x4.5 or 1045 is enough.

MOTORS: As I know higher kV is needed for smaller quads with smaller props. Also kV means how many rpm motor has for each volt. So if you are using 3S battery, and 950kV that means motor has 11970 rpms at full battery.

BATTERY: I'm using 5200mAh battery which gives me about 40min of normal flying. Bigger is not always better, because bigger the battery, more weight!

ESC: Just make sure that its current rating isn't lower than motors. I use 30 A, but I could get away with 20 A.

TX/RX: I'm using turnigy remote with 6 channels. Be aware, 4 channels are used by quad for movement! So you have 2 left, which I used for PID tuning. At times, I was sorry I didn't bought a remote with 9 channels, but they cost more, so that wasn't an option for me.

IMU: The MPU6050 is probably the cheapest option, since it has gyro and acc. It has some demons in it, but for the most time it doesn't make your quad crash, so it should work. :D

SONAR: That's a bit more problematic, since this sonar was not designed for quadcopter use ( high vibrations ) and you could have many problems. I recommend buying something more expensive for altitude hold.

Step 2: Software

Here is the link to the code: GitHub repository with code

I also used pre-made libraries, but for the most part I made my own.

Sometime ago I realized that it's best practice to make your own, because if something goes wrong, you know what's happening inside the code, and you don't spend weeks reading the documentation. For the most part.

I'll write about things that I confused me the most. Ofcourse somethings only make sense when you do them yourself, for example PID regulation, but I'll try to explain how I understand it. Perhaps it'll help you.

1. PID regulation

Let's start at beginning. I hope you have some knowledge about how this thing works, because I won't comment the basics. Also, I don't really understand the mathematics behind it, so don't take everything here as holy truth.

I used cascaded PID controller (look at the picture above "Per Axis PID Structure").

Few names explenation:


As you can see in the picture, rate PID has two inputs. One is output from stabilize PID (which is infact desired angular velocity) and second is actual angular velocity. This loop is the slowest one, and it runs with the same frequency as MPU "new data" frequency, which is 1 ms. When doing tuning, this controller must be fine tuned before attempting to tune stabilize PID!


This runs faster, outside the MPU loop, from about 1ms to 25us, depending on whether MPU sends out a new value. One imput is actual angle of quadcopter, the other is desired angle from the pilot. Always make sure that desired angle is in range from let's say -40:40 degrees. That means that if you read remote controller values in micro seconds (1000-2000), you should map them in some internal range(-1000 , 1000... that's how I use them) and then to actual angle you want your quad to have (-40, 40). Higher these values, more "acro" flight you'll have. This is also the case with rate PID, where values must be in proper range of angle velocity.

Effect of stab/rate modes:

In rate mode (ACRO), the desired setpoint is angular velocity of quadcopter. So when you let the stick go, quadcopter will stay in the same position you left it (because then the setpoint is 0). This makes it hard for a beginner to fly it, especially without FPV set.

I find stabilize mode more useful, because here, as you can guess, the desired setpoint is angle, which means that the second you let go of the stick, quadcopter will return to 0 angle. That's why I said that higher value range you use, more agressive the quad gets.

Some notes about guessing values for PID:

I'll explain only P term, since it's the simplest to understand. So what kind of values should you try to plug into controller? Well it depends from what kind of range of values you use as setpoint. I used as said before -40:40 degrees (stabilize mode). And my P value is around 4.5 . So if you think about it, it kinda makes sense. If I would have range of setpoint from -100:100, then my P value should be around 10. I and D terms are more complex and I can't say for sure, but you can get your quad to "fly" only with P term, which is enough to continue tuning other values.

IMPORTANT: when I say that you should divide setpoint with 10, I don't mean this as holy truth. You should experiment with lower values. I only said this because it took me a while to even find good values, and now that I have some feeling about this, I can say what works for me. The best way to do this is read values from potentiometer in your remote controller and use them for tuning. Perhaps start with range from 1:5 and make it larger until you see oscillations.

2. Pulse Width Modulation for Electronic Speed Controller (PWM for ESC)

If I were using Arduino, I wouldn't have any problems here. However in my microcontroller, I had some problems getting correct period for my PWM regarding clock ticks.

So, for a PWM, you'd want your writing period to be as fast as you can. Normal ESCs have from 50Hz to about 400Hz. At 500 Hz you would already have a problem because the period would be the same as the longest PWM value. To explain: Normal ESCs have values in range from 1000us to 2000us. So the period should be above 2000us, but if you calculate 1/500Hz you'll get period of 2ms, or 2000us. So that wouldn't work. I'm using 400Hz frequency and it works just fine.

However, since this is not an Arduino you can't just write analogWrite and go fly it. You have to calculate how many clock ticks do you need to make 2.5ms long periods. All you have to do is divide 2.5ms with clock tick lenght (with 80Mhz clock that's 1.25e-8) and divide again with divider you are using for PWM(2, 4, 8, 16, 32). If you get value bigger then 16bit, use higher divider, because in Tiva C the count register only holds 16bit value.

Internal Measuring Unit MPU6050 (IMU MPU6050)

So the thing is that I had some help filtering values to get the angle. My friend helped me make a complementary filter (I'm in first year of collage and don't have the knowledge yet). Hence, I won't be able to explain how it works. I'm pretty sure that there is a lot of info about that on the internet. You can also check out Kalman filter.

The biggest problem that I had with MPU is that it freezes from time to time and I have to reset it by unplugging the battery from quadcopter. I think that this has to do with I2C protocol, but I have no idea how to fix it.

Step 3: Conclusion

I could write whole book on this topic. It's huge and somewhat complicated, so believe me I tried to explain it the best I could. If there is something that I didn't write about, or if you have something to ask, please do.

For the end, I would just like to say that there is no better feeling then seeing that after so many time your quad flies with the code that you wrote. Also it's the best way to get better in programming and robotics.