First off: This post is a huge mess. I cannot explain well, and I did not order it well. Also, it is really long. If you want me to elaborate on something, improve something, find a typo or grammatical mistake or whatever, please tell me. Also, feel free to skip sections that do not appeal to you (I attempted to compensate for the lack of structure by adding paragraphs and headings).


Drones, or UAVs, as they are called in literature, are the next big thing in robotics. They are versatile, can perform tasks such as transportation reliably, reach places where people or other robots could not, and, most importantly, over the last few years they became cheap and accessible.
And so, building a drone was our choice when me and a friend were allowed to pick a year-long project at school. Smile
This project is by far my most complex undertaking yet, and part of it is already done. This combination results in an obscure post, because I am bad at explaining and telling stories, but I will do my best. I will not explain all techniques in detail, but instead mention and summarize some of them, and provide links to various articles I found helpful in understanding the concepts for those interested.

We wanted to really build it ourselves as much as possible and make it as cheap as possible. So we did not consider buying a flight controller, instead going for an Arduino based approach and decided to design and 3D print the frame ourselves. Our sketches resulted in a drone of about 200 - 250 grams of weight, with a camera and pilot assisting functions such as automated takeoff, landing and hover functions. The cool thing is that the motors can handle a mass of up to 600 grams (barely able to take off then), which means that, with a properly designed payload mount, we could, for example, attach some cargo carrying equipment or a GoPro (the latter of which I find much more interesting!).
The flight time without additional payloads is about 13 minutes, though this is from a calculation and was not verified experimentally yet.
The budget for the whole project is 102 € and a few cents, which is much cheaper than commercial drones of this category! But that is without spare parts and with some of the components already laying around at home (most notably a charger for the batteries, which could cost anywhere from 10 € to 50 € if bought additionally), and a self-designed and 3D printed frame. I estimate that the actual price is 150-200 € considering that, depending on what charger, frame and how many spare parts you would choose.


Early on, the supervising teacher was rather skeptical of the idea, because he did not think we would succeed in building a working drone. It's understandable, because we'd lose a few valuable months of our time before realizing it, and would have to choose a different project in the middle of the year. But the consequence was that the teacher requested a demonstration takeoff/hover within one and a half months, so we'd have enough time to switch projects just in case.
This tight schedule baffled us at first, because that would be difficult indeed. We figured that we would not be able to build our full planned drone to a stage where it would fly by that time, so we had to strip it of most things to create a bare minimum prototype. After the demonstration flight, the prototype would be dismantled and the experience and parts used to build the fully functional drone.

So far, we have completed the prototype hardware-wise and almost finished the programming stage. The demonstration flight was supposed to be on Friday last week, and it kind of happened. We tuned the control algorithm, but apparently it was not good enough. This resulted in stability issues and ultimately a collision. The drone suffered some damage, most notably one of the motors broke. replacement has just arrived and we installed it instead of the broken part.

Hardware / List of parts

We chose and bought a list of parts for the full version of the drone. On request, I may send you (or publicly post) a full Excel spreadsheet with prices, sources, masses, electrical calculations and other info where needed. But here is just a list of parts and explanations:

  • Arduino Pro Mini (5v): This is the smallest available Arduino. We chose an Arduino as controller, because we were both familiar with how to program them and because they were available at such a tiny size. The 5v version is simply more compatible with our electronics.
  • USB to Serial adapter: Because the Arduino was designed to be small, it does not even include an USB interface which is required for programming. Instead, there is an external chip with a USB port on one side and serial IO pins on the other side.
  • Raspberry Pi Zero: Because the full version drone will include a camera, all this data needs to be processed. The Arduino is nowhere near powerful enough to handle it, so we went for a small powerful computer, the Raspberry Pi. It will not only stream the data to an SD card, but also use the camera as a basic optical flow sensor and possibly take some load off the Arduino by processing other things as well, depending on how much processing power will be left. The Arduino remains as a microcontroller running at a high frequency.
  • HC-SR04 Ultrasonic sensors: Just the most generic rangefinder. They can be found at $1 apiece and are good enough for most things. We will use two, one pointing downwards for altitude estimation and one pointing to the front for collision avoidance.
  • GY-91: This is a rather obscure chinese board. It is basically an MPU9250 accelerometer/gyroscope/magnetometer IMU package and a BMP280 pressure sensor for altitude estimation.
  • Raspberry Pi Camera + Adapter cable: This is just the standard Raspberry Pi camera, which is more or less guaranteed to work in our setup. It requires an adapter cable to work with the Pi Zero, though.
  • D24V5F5 Voltage regulator: The battery provides a voltage anywhere from 8.4v to 7.4v depending on charge level. The voltage regulator steps it down to a stable 5v for the onboard electronics, which all run on 5v.
  • NRF24L01+ Radio Module: Obviously, those are for the communication with the drone. One of them will fly, and the other one will be mounted on something for control. This will either be an Arduino with buttons or a Raspberry Pi with touch screen. Probably the former, though.
  • Battery: Those don't seem to have a unique name or ID. We went for a set of two Li-Po batteries from Floureon. The 7.4v / 1000mAh / 20C ones. They were cheap, work, as far as we can tell, perfectly and have the capacity for about 10 minutes of flying.
  • C10 Micro Outrunner Brushless Motors: After some looking, we found motors that would provide about twice or thrice the weight of the drone in thrust. They were comparatively cheap and light. However, they did not turn out to be good, despite the reviews.
  • BLHeli Racestar 20A ESCs: For those not familiar with RC models and terms, ESCs are electronic speed controllers. They are required to actually control the motors with the main power and a signal as inputs. Those were the second cheapest ESCs because of a sale when we bought them, and rather overpowered for our motors. They work really well, but are rather expensive without sale. Another friend recommended not to buy the specific cheapest model we found, because they introduced too much of a delay between the input signal and the output control.
  • 5030 Propellers: Apparently, "5030" is some rather standard propeller form factor. It means 5 inches in diameter and 3 inches of pitch, that is how far it "screws" itself into the air in a full rotation.
  • Propeller adapters: Our propellers have a 3mm diameter hole, while our motor has a 2mm shaft. The adapter fixes this and is also a mount for the propellers. That is, it can be fixed on the motor shaft tightly and a screw-on cap holds the propellers in place.

In addition to those parts, we use about 100g of ABS 3D printing filament for the frame, an SD card for the Raspberry Pi, a charger for the batteries, lots of wire, some electronic components and breadboards for prototyping.

Hardware / Prototype

Of those parts, the prototype only needs the motors, the ESCs, the Arduino, the GY-91, the D24V5F5 and the battery. We decided not to use the radio modules, because we'd need to build some sort of remote controller for that, and that would take even more time. Instead, we pre-program sequences on the Arduino and execute them without the possibility to intervene. This, of course, requires extra careful testing.

The hardware setup is pretty simple: The battery supplies power to everything. The power is basically split into five lines: One for each motor, and one for the electronics. The motor power lines are run along the drone's edges and are tapped at each ESC. The electronics power line foes into the D24V5F5, which regulates it down to 5V, and then into the Arduino. The Arduino then supplies power to the sensor. It is also connected to every ESC via one signal cable, more on that later.

For the components, we designed a frame. It is basically a flat plane on which things will be mounted on both sides. The bottom side has two diagonals for structural support that double as landing legs. The squares on the top are basically marks to assist with part placement. This is just the prototype's frame, so it is rather bland and not quite complete. What we really like is the two diagonal structures, because they have proven to support the whole thing. However, the diagonal arms are still particularly weak against twisting around their axis, which might be an issue during sharp maneuvers. We also lack some sort of propeller guards that would protect the propellers and motors from damage. And finally, the non-prototype will have a much more complex system of holes and mounts for the components, to save on mass and provide proper anchor points.

(Click for full size)

Surprisingly, the 3D print turned out perfect the first time (it was not only my second ABS 3D print, it was my third print overall). I assumed the large flat part would have warping issues, but it did not at all. In fact, I barely managed to remove it from the printer, it stuck to it really well.
And this mess of wires is what it looks like in reality (for scale, diagonal "wing span" is 26.2 cm)

Possible improvements

As for things that went wrong so far...
If I had another shot at this, I would choose a different IMU. The IMU was the wrong place to save money. It's really difficult to work with, and the code required to make things that other IMUs would do themselves takes up at least a third of the Arduino's memory. We can probably reduce this with optimization, which is a thing we have neglected so far, but it's overall just a bad component. There are better sensors which cost more, of course, but are better documented, provide better functionality and are more sensitive.

Next, I would buy different motors. Those are good enough by the datasheet, but in reality, they are just of poor quality. The accident I mentioned above, which resulted in a broken motor, dates back to a fault we uncovered a month or so ago. In transporting the drone between home and school, we used a box with foam sheets in it to avoid damage. Turns out, the foam exerted enough force on the motors to push the motor itself into its mount (see the image for a better explanation of what the mount is):

This must have broken the connection between the motor and the mount, because we had to glue it back in with epoxy. Now, during the crash, the propeller attached to the motor hit a table. The force was not enough to break the thin plastic of the propeller, it only had a small dent. However, the motor was ripped out of its mount again (despite the epoxy), and, as it continued spinning freely, it tangled itself around its cable and the wires broke off. You can see it if you look closely at the image. This is not repairable. Overall, I have to say that this is not the part of a motor that should be causing trouble, and I am dissatisfied with the quality.

Then, there is the mounting of components on the frame. We used Velcro for the batteries, because it allows them to be removable easily. And we used a double sided tape for the rest, because that was the easiest and cheapest option. Well, turns out, Velcro adheres pretty well, but double sided tape loosens after a few weeks of stressing it in different directions. Hot glue did not adhere at all, for the record. Anyway, the prototype is fine with double sided tape, but the full version of the drone will definitely have screws wherever possible, and different means elsewhere.

And finally, there is the magnetometer. The one issue with it is the proximity to the power lines for the motors. The current in those lines my reach as much as 3.6A, which generates a magnetic field strong enough to make the magnetometer readings useless as a tool for determining orientation. This was not considered at all in the prototype, and we will need to place the IMU as far away from the battery and wires as possible.

Software / Prototype

Lastly, there is the software. The first thing that arrived were the ESCs and the motors, so that was the first thing we assembled and got to work. It was fairly easy - the ESCs can be programmed via a special interface through the Arduino. The documentation was sufficient and after some tinkering, we managed to control all four motors independently from the Arduino. We used the Servo library to send the ESCs signals in the form of pulses between 1000 and 2000 microseconds, which linearly corresponds to a throttle value from 0 to 100 %.

By far the biggest software headache was the IMU. This was caused by the sheer mathematical and physical complexity of such a sensor, my inexperience with electronics, poor documentation and finally some inconsistencies, which initially resulted in the failure of most available libraries. The sensor communicates with the Arduino via I2C, which is basically just another way to wire up multiple circuits in one device and make them exchange information. The first major milestone was making this communication work, which failed because I literally forgot to switch the power on at first (this cost me a day... Yes.). When I figured this out and fixed it, most libraries still failed to initialize communication, because they were querying a register in the IMU, and checking it against a fixed value that it should hold. This is supposed to make sure it can communicate to the sensor. Well, our board is probably a counterfeit, because its register happens to hold a wrong value (and it is read only). This cost me another few days to track down and fix in the library. Long story short, before we actually got to the raw data of the IMU, we spent a week of work on research and troubleshooting.
However, once we did that, the real fun began - getting proper attitude estimates from inertial measurement unit data is a notoriously hard problem, beginning with the proper calibration of the sensors. For the prototype demonstration, we went with using only the gyroscope, and, at most, very simplified accelerometer processing. This means that we rely solely on the gyroscope for orientation information, and have limited information on our velocity and position. The gyroscope is the key component, so it needs to be calibrated well.
Calibration consists of two values: A zero offset, which means what the sensor reports when the rotation is actually zero, and a scale factor, which proportionally scales the output when non-zero. We ignore the scale factor because it is nearly impossible to read without lab conditions, and we just calibrate for the zero offset. The straightforward and most common way to find it is to take many readings (say, 1000) at rest and average them. However, we need to rely on our gyroscope more heavily than usual, because for the prototype it is our only means of attitude sensing. We could, of course, just take even more readings (10000, 20000 or more). But there is one problem: Taking 20000 readings takes about half a minute in our case. If there is just one slight vibration in that time, or an air current, or whatever, the data is skewed. But we devised a plant to detect random vibrations and eliminate them from our data! We divide our 20000 samples into 20 packets of 1000 each. Each of them takes about 1.5 seconds to record. We look for "outlier" packets, by calculating each packet's variance. We discard the 10 worst packets and average the 10 best ones. This gets us only 10000 readings from the gyroscope, however, they are filtered of disturbing factors. An improvement would be to discard only the packets with a variance <= a threshold, however, we left that for a later point. The quality of the data is assessed by adding up the remaining 10 variance values, and the program quits with an error if the data is bad.
With this method, the gyroscope can be calibrated to a drift of 0.5 - 1 °/min on the worst axis (!!!). This is more than enough for a short demo flight without any other sensors.
The accelerometer is, for now, ignored and we use simpler means of estimating altitude. We ignore lateral velocity.

We took a curve of motor throttle versus thrust, which, turns out, is far from linear. We use this to estimate acceleration and thus velocity and altitude. It does not get us into a stable hover, but it is good enough for a demonstration.

To keep the orientation stable, there is a three axis system: Pitch, roll and yaw. Yaw is around the up axis, pitch is around the sideways axis (you can pitch "up" and "down"), and roll is around the front-to-back axis. Yaw is not important, and besides, it does not get disturbed as easily. Also, it requires a completely different method to adjust. So we ignore it for now. Pitch and roll can be changed by changing the motor power. That is, if you need, for example, to pitch up, slightly lower the power of the two motors on the back, which makes the back drop down, and the front rise up. We implemented a system to control this via a "bias": There is a main throttle setting, which is what all motors default to. When a command to adjust the pitch or roll is sent, an asymmetry is introduced by adding a value to the throttles of two motors and subtracting a value from the two opposite ones. This value is directly controlled by PID loops, one for each axis. The benefit is that the two axes are virtually equal, so we only need to tune the PID loops once and use the parameters for both of them.

And, I guess that's it. Sorry for the long post, I just had to get my thoughts in order here and it's still a big mess. Feel free to post opinions on anything, as anything can still be changed in the full version drone. I may edit this post as I find ways to improve the structure, but for now, please bear with this mess. Also, please report typos and/or grammatical mistakes.
So, it's been a while. In that time, we fixed the stabilization algorithm. We decided to analyze a graph of PID output and actual roll/pitch position versus time - which is easier said than done. Optimally, we'd have a logger on the drone which would make use of the Arduino's EEPROM and periodically (at least every 50 ms) save the PID outputs and angles for the pitch, roll and yaw axes separately. This would give us three data plots which we could analyze and derive proper PID parameters from.
However, this was not possible. To log such a piece of data properly you need a float, which is four bytes. Writing a byte to EEPROM takes 3.3 ms. We had to log 12 numbers * 4 bytes = 48 bytes * 3.3 ms = 158.4 ms. This is 1/6th of a second during which the sensors do not track the orientation and position, the guidance is paused and nothing happens overall. Just the Arduino writing data to memory. Not even mentioning that the EEPROM would fill up within 1 second this way, at a logging frequency of 20 Hz / 50 ms per reading.
We figured that we could omit the yaw axis for now - we are only tuning pitch and roll anyway. That is 32 bytes - progress. Next was the fact that we do not have to log the PID output - the PID reacts exactly to the given angle, in a predictable way. And we have the angle. So we can reconstruct the PID output by running a loop in our plotting script and "simulating" the PID output - which is as simple as just adding up the proportional, integral and derivative parts. This gets us down to 16 bytes. It's still a lot, but we're getting somewhere! But we also figured that floats allow for 6 - 7 digits of precision which we do not need! Our angles which we logged kept withing +/- 30 or so degrees, and we need no more than 2 - 3 decimal digits. So we just multiplied them with 1000 and cast them to ints, which are 2 bytes each. This means we have 8 bytes of data to write, which takes 26.4 ms and fills the memory after 6.4 seconds. This was still a lot to pay, so we had no choice but to reduce the period to 100 ms per reading. This would consume 26 ms once in a while, but the guidance algorithm can take it ("downtime" of 25% or so), and the memory would last for 12.8 seconds, which is pretty nice! So, we fired up the program, connected the quad to the PC and got this:

(Red plot is actual orientation data obtained from the drone in degrees, blue plot is the simulated PID response. Time resolution is 0.1 s / division, bigger division every 1 s. Graph data terminates at 8.9 s.)
Note that at about 7.4 seconds the drone touched down in the grass, so the controls did not have any effect and that's the weird flat part at the end of the graph.

Well, no. Actually we did not get /this/, because this is just a plot which I deliberately staged. The actual first plot we got was much worse, and we don't have it anymore anyway. But shush!
Long story short, we spent a few days with this sort of thing, tuned pitch, roll and eventually yaw and it's pretty nice now. We also saw that the drone had a significant drift in a fixed direction, so we introduced a new trim parameter, which is basically a fixed offset to the motor power. And in the end we got (drumroll) this! (Sorry, no idea how to embed .gifv files - does that even work? Also sorry for the potato gif, I have no proper conversion software.)
Notice the bonus moon backdrop! Very Happy

So, we now have officially created a working, hovering prototype. It has no accelerometer support yet and only relies on the gyroscope data. We have lots of challenges to solve for the followup drone. But hey, we made a flying thing! I am proud. Very Happy At this point, the prototype's job is done and we will dismantle it soon - perhaps it will fly another time, but only for demonstration purposes.

For now, we are writing our project report, finalizing the timeline for the second drone and creating a layout in Sketchup. It will be another few weeks before we have any new images, but I will hopefully update this post as we make progress on the 3D model and layout.
Big update!

The prototype phase of the project is finished for some time. Meanwhile, we updated the project schedule (it got tighter Sad), made a remote control for the drone, updated our calculations, finished and 3D printed the frame for the new drone, made a PCB for power distribution, assembled and tested the hardware. Good news - it turned out, in my opinion, really nicely and all the electronics work! Let's have a recap:

To skip the scheduling part (not worth featuring here, I think Razz), let me start with the remote control. It was not a terribly big deal, we just took a perfboard, and Arduino, a HDSP2000 display, an nRF24L01 radio and some buttons and soldered this thing. It runs on a 9V block battery and drops this down to 5V with a buck regulator. It also has one signal LED, because why not? The specific interface we implement with this arrangement of buttons is open, but we have rough ideas.
Here are some images (Click for full size):

Next, for the frame: the prototype was rather simplified. It had few components, so we basically did all the maths on a single sheet of A7 paper on a two hour bus ride, and supplemented it with a sketch on another A4 paper later. The real drone has 10 individual components excluding ESCs and motors (because those are symmetrical and do not need to be accounted for anymore). For that purpose, I made an Excel sheet which I am rather proud of, because it implements everything, from formulas to replacing text and conditional formatting. Long story short, we had (and still have) an Excel spreadsheet which allows us to represent the two sides of the drone frame and assists in aligning components on them so that the torque by their gravitational forces remains low as well as avoid collisions. In other words, it is a tool to help find a valid design which is well balanced. And it works!

Sorry for the German text, I am too lazy to translate it fully. For reference, the spreadsheet mentions "Größe" (Size) as well as abbreviations for "V" (Front), "H" (Back), "L" (Left) and "R" (Right). It features our final layout. Also note one red marked square: this is an intentionally ignored warning about an ultrasonic sensor protruding in front of the frame/not being fully inside the frame.

Next, we implemented this layout in Sketchup by making the basic shape, then placing the components all over it according to the numbers found above. Then, we made cutouts, holes, markings, mounts and various adjustments to accommodate the components. Finally, we got this:

This is somewhat hard to really picture, but there will be better images!
A technical detail is that we added structures both on the upper side (mainly an ultrasonic sensor mount) as well as the lower side (mostly landing legs as well as structural support), so we did not enjoy the luxury of a large flat piece and it would be a hassle to 3D print. To avoid this issue, we cut the large plane in two halves and printed them separately, which solved the issue and opened new possibilities: We could leave some cutouts only in the upper half as an aid to align components on them. Those are the crossed out holes you can see (+-type cross, not x-type). The +es are there to provide structural strength while the 3D print is removed. We cut them away later.

Here is some footage of the 3D print happening:

Unfortunately, I have no images of the two individual parts of the frame, or of the glued frame with no components on it, but here is what we have after gluing, finishing, assembling, soldering, more assembling and finally more gluing again:

Note that there is no battery attached in the images. It goes into the big spot in the middle.

The power distribution PCB is the small green square on the upper side (not the camera on the lower side). There is not much to say about it. I just designed that in Eagle with way undersized traces in the hope that the propeller blowing on it will cool it down to sane temperatures and it will not cause problems. It has to carry up to 15 amps, after all. Fingers crossed, because there is no plan B. It also houses 5v and 3.3v voltage regulators and a small "sensor" for the battery voltage, which is a voltage divider that gets the voltage into a valid range for an analog pin on the Arduino.

One last issue we learned the hard way, but managed to solve now: the main 5v onboard voltage regulator, which acts as a BEC and drops down the two cell LiPo battery voltage down to 5v definitely does not like back-feed, i.e. when current from its output flows back into the regulator. This may happen, and often does happen, when there is no battery attached, so the regulator is idling, but the Arduino or Raspberry Pi are being programmed through USB and feeding the drone's 5v rail. An ideal, zero voltage drop diode would be the perfect solution, but unavailable for us in time. Instead, we found out that the Raspberry Pi can run on slightly less than 5v, so we used a Schottky diode there. And as for the Arduino... It is not connected to USB directly, but rather through a programming header which includes a 5V pin. Turns out, if you remove that pin, there is no 5V supply to the drone, and no 5V supply to feed back into the regulator. Problem solved.
Well, no, not entirely. It also cuts the 5V supply to the Arduino - so much for programming it. You need to attach the battery to power the Arduino externally. This works, but it is somewhat of a waste of battery power. Instead, we found a USB supply which gave us almost 5.4V (I wonder how it did not fry any phones yet Surprised). 5.4V is slightly above the dropout voltage of the 5V buck regulator, so it runs fine and supplies power to the drone. We sacrificed a USB cable and soldered female pin headers to it, which we can now plug into the drone and basically power it from a wall socket. Nice!

All the components, especially the sensors, work, which is amazing (not a single mistake made during soldering! Wooo!). The next step is digesting the sensor data in the Raspberry Pi and designing a protocol where the Pi can act as an I2C master officially, but inofficially be controlled by the Arduino and hand it over the sensor data on demand. This is because the Raspi controls our sensors for processing power, and the Arduino controls the rest of the components for better real time management, and thus, it is "in charge". But there is a catch: The Raspi, by design, cannot really be an I2C slave. Well, it can, but it is hard. So there is that to circumvent.

That's it for now! Sorry for the long delay and long post again. Sad
Feel free to ask for details on specific steps, as obviously this is mostly a summary of things.
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum