top of page

(Yet Another) Network Controlled DIY Quadcopter: First Draft

  • Writer: Eldan Ben Haim
    Eldan Ben Haim
  • Sep 26, 2021
  • 15 min read

Updated: Sep 27, 2021

Some people are born to expand the borders of the realm of possible. Whether they imagine a brave new world and then set course towards making it real, or merely concoct new ways for our own familiar world to evolve, these people are often getting bored with traveling on paved roads. Sure, they’ll stand on the shoulders of giants, but as means to an end. What they’re really after is harnessing their creativity, skills and competence towards making a real change in the world. They may succeed (Benz and Daimler, Edison, Einstein, Columbus), or they may fail (the artillery man from War of the Worlds?) — but they’re definitely going to live on trying.


Others find their thrill in the sheer execution of things. Craftsmen — carpenters, builders, watchmakers to name a few — don’t necessarily revolutionize their discipline (and a good thing they don’t!) and still they take significant pride and joy in their craft. They often possess the same passion for the craft as the “explorers” are passionate about their own crusades. And it is this passion that turns into the characteristic qualities of their products.


As for me — a Good Day is a day where I executed on something that was challenging. At least when working on my hobbies, I don’t seek to invent a field in Mathematics (whew); suffice that I succeeded to solve a difficult puzzle. Not every piece of software I write introduces a new algorithm or data structure or even abstraction to the world; and yet I’m perfectly fine with writing (what I deem as) properly engineered software. I don’t need to invent the car; I’d be fully content with just building a decent one.


Or, in our present case — a Quadcopter.


By now, Quadcopters are well studied. So when I set out to build Quadimodo, I wasn’t looking to invent a new type of flying vehicle. In fact, I wasn’t even going to build the best, or fastest or otherwise innovate on Quadcopters. I just wanted to build one – to put my skills into a difficult, but not previously-unsolved problem. It didn’t really have to fly. I mean, at least not for a long range. I started with the goal of building something that will be able to stabilize itself, and only as I was progressing with this project, I upped the ante, ending up with a drone that was able to fly decently in-doors.


As I started exploring what's available online about Quadcopters, I found a vibrant scene of drone builders. Many designs are available and discussed online; some of these are more complex than others. I found this to be very comprehensive and accessible, and similar to what I wanted to try. Also this YouTube series was helpful. While I happily devoured any knowledge I could find online, I decided to create my own design. I will start with a very simple design, experience where and why it fails, and evolve from there. Like any other 40-year-old teenager, I basically wanted to make my own mistakes and learn from them. I’m doing this, by the way, so you won’t have to ;)


Propulsion

Since I didn’t care about the quad’s size, it was going to be driven mostly by the size of my 3D printer’s printing surface. Or even smaller. As I wasn’t concerned about speed, maximum altitude and stamina either (I just want the thing to fly, decently, for a short while), it was clear that the propulsion system chosen will also be driven by simplicity.


The motors powering a small Quadcopter's rotors are normally of one of two types:


  • Brushed coreless motors. These are very similar to “regular” DC motors: they’re brushed because they have “brushes” that conduct electricity to the motor’s electromagnet (they’re part of what’s called the Commutator in a motor). These brushes are installed in the motor such that as the rotor spins (along with the electromagnet mounted on it), the polarity of electricity conducted to the motor’s electromagnet is reversed each half-turn of the rotor. This keeps the magnetic field generated by the electromagnet acting together with the stator (basically the fixed magnets) to spin the rotor in a consistent direction: after the rotor completes half-a-turn, the electromagnet poles are positioned such that the forces between them and the stator magnets are now opposite to the motor’s spinning direction. To make the motor spin continuously the poles need to be reversed, which is done by reversing the direction of the current flow through the electromagnet. In addition to being "brushed", these motors are also "coreless", which means that the electromagnet is built without a core — the electrical wire is wound in a way that creates a mostly self-supporting structure. Without a core mounted to the rotor, its mass and inertia are reduced which improves the motor’s efficiency.


  • Brushless motors. With brushless motors, we lose the commutator brushes. Instead of the electromagnet being mounted on the rotor, it is actually static — and mounted on the motor’s casing. The magnets are now mounted on the rotor. While the core working principle of the motor remains the same, in the absence of commutator brushes to switch the polarity of the electromagnetic field some other means need to be employed to decide when to reverse the current in the electromagnet. This is the role of an Electronic Speed Controller (or ESC) — a circuit designed to sense the position of the rotor and apply corresponding electric current to the stationary electromagnet to generate the desired magnetic field. The main benefit of using brushless motors is their efficiency. Since there are no brushes there are less power losses to friction; also the electromagnetic field can be controlled with more sophistication.


With no minimal size constrains, and since I wanted to have a simple design with as few “black boxes” as possible, and since I didn’t really want to expand the scope of this project to building my own ESCs, I opted for a small coreless, brushed motors Quadcopter. I own a couple of these toy Quadcopters; they’re all cheap and fly quite nicely so it definitely should be possible to build one!


I’ve ordered a few sets of coreless motors from AliExpress without really paying too much attention to their specs (size, RPM). I figured I’ll try a few of these sets and see what works. I’ve also ordered several sets of propellers — taking into account that throughout my experiments several of these may break. This assumption turned out to be one of the very few initial assumptions I made in this project that remained valid throughout :)


Frame

I also needed a frame to mount the motors as well as the rest of the electronics. I'm always happy with those (rare) occasions that I have use for my 3D printer!


There’s plenty of tools out there to allow you to design a 3D model for printing. Among those, if you have rudimentary coding skills and you need to design a technical piece, you really want to look at OpenSCAD or JSCAD. Both of these tools allow you to write code that generates the model you’re trying to build. Code representation for these models has several benefits, with the main ones for me being the ability to create reusable design components, and the ability to parameterize the design. My work process normally involves browsing JSCAD on Safari on my iPad from the safety of my bed late night, creating the model ignoring any real world dimensions, and then at some later stage taking measurements in my workshop, updating parameters, printing a prototype, and repeating until I'm happy with the results. In fact, I like JSCAD so much I’m contemplating to package it up with nice UI as an iPad application. Might also add direct printing from that to Octopus. If anyone else besides me thinks this can be a useful thing be sure to drop me a note below!


Anyway, back to reality, I’ve started with the initial design shown below. There are 4 “sleeves” that hold the 4 motors. At the bottom of these sleeves you can see holes through which the motor’s wires go in to the control system. A hole at the bottom of the middle of the quad is where these wires go through. As I describe later in this post, this design has quite a few issues that were fixed in later editions. Of course the drone’s dimensions are customizable through model parameters.


ree


Basic Control Circuitry

A Quadcopter is basically controlled by individually changing the speed of each of its four motors. "Without limiting generality", if we label the 4 motors of a Quadcopter as Front-Left, Front-Right, Back-Left and Back-Right, then:


  • To make the drone go higher — we increase the speed of all four motors. To make it go lower — we decrease their speed.

  • To move the drone “left” or “right” we rotate it slightly around the axis that goes from front-to-back (us professionals call this “roll”. There. You’re not a layman anymore). This is accomplished by changing the difference of speeds between the pair of *-Left motors and *-Right motors.

  • Similarly, to move the drone ”forward” or ”backward” we rotate it slightly around the axis that goes from left-to-right (the folks that use the word “roll” call this “pitch”). To do that, we change the difference of speeds between the pair of *-Front and *-Back motors.

  • Finally, to rotate the drone around the axis that goes from its top to its bottom (that also has a name: “yaw”), we first observe that if the 4 motors are spinning to the same direction — the vehicle will continuously spin around itself to the opposite direction (that’s Newton’s 3rd law for you, I guess). To avoid that, we rotate each pair of “diagonal” motors (so Front-Left and Back-Right is one pair, Front-Right and Back-Left is another pair) in an opposite direction. Now it becomes pretty obvious how we can yaw — by changing the speeds of these diagonal pairs.



ree

Clearly a fundamental thing we’re going to need is a way to power the 4 motors in a variable way, controlling the power (and hence speed) of each of them individually. One simple way to control the speed of a DC motor is using PWM signals. With PWM, instead of having the motor receive power constantly we quickly switch its power on and off in cycles. The period of time the motor is switched on vs the period of time it’s switched off don’t have to be equal. So, if every switching cycle is, say, 100 milliseconds, we can decide to turn the motor on for 10 milliseconds and then off for 90 milliseconds (and repeat this again in the following cycles). This means that the power is provided to the motor for 10% of the time, or a 10% duty cycle. If we turn the motor on for 90 milliseconds and turn it off for 10 milliseconds — that’s 90% duty cycle. And if it’s constantly on — that’s 100% duty cycle.


Now, I’m not sure whether the duty cycle is linear to the motor’s speed, or its moment or any other physical measure. But clearly increasing the duty cycle increases the motor’s speed and decreasing one will decrease the other.


How do we generate this PWM signal, then? We could build an analogue circuit to do that, but since I’m a digital guy (so I actually couldn't) and we’re going to need to have a microcontroller on board anyway (we’ll see why shortly), what we’re going to do is just generate PWM signals using code on the microcontroller. Problem is, microcontrollers tend to output signals through digital outputs that are not designed to power motors (or any other significant load, for that matter). So we’re going to have to use these signals to control some sort of switching transistor that would allow current to flow based on the PWM signal.


I started, despite popular wisdom, with a ULN2803A chip (which is what I had handy in my workshop). This is a single IC chip that contains 8 darlington pairs (never mind what these are for now) — each can function as a switch for a 500mA current. I connected the 4 motors to a power source through 4 of these darlington pairs, and their 4 gates would be connected to corresponding digital outputs of a microcontroller.


Speaking of which, I needed to choose a microcontroller. Here too, the choice was driven by the mundane — I decided to use a WeMos D1 Mini board, sporting an ESP-8266 microcontroller, simply because I had a branch and I was quite familiar with this board. Little did I know that during this project I’m going to fry quite a few of these boards and order a few new batches… The ESP-8266 supprts 32-bit processing, runs at 80MHz or 160MHz and, of course, has on-board WiFi. It’s a really great board in terms of cost-performance (you get these at ~$2 per board in AliExpress!), and I use it often for my projects. For Quadimodo, it seemed like a good choice in terms of compute power, and I was planning to use WiFi to control the drone — seeing as this was meant to only fly in-doors, in my workshop.


Now, what if we want the drone to ”stay put”, and hover balanced? We just need to make sure that all 4 motors are rotating in the same speed…


… which, anyone who tried to do any real world physics system would recognize immediately as a blatant lie. First, the word “just” here is deceiving; making sure 4 motors are spinning in the same speed is more complex than it sounds (depending on the accuracy you’re after it may get very complex indeed). Second, even if we were able to spin the motors in the same speed that’s probably not what we actually need: for example, weight is not evenly spread across the drone. There may also be some wind in the room. All of this means that we’re not really looking to spin the motors in the same speed to begin with (I guess that’s actually good news ;) )


In fact, if we want the drone to move in a controlled manner we’re a bit in the dark too. As mentioned above, the relation between PWM duty cycle and thrust is not as simple as idealists would hope for. And the same annoying imperfections of the real world that apply to keeping the drone in place also apply here.


The way this problem is typically solved for drones is by having an IMU — inertial measurement unit — to measure the actual orientation of the drone, and then have the microcontroller apply corrective changes to motor speeds to reach the desired orientation. The microcontroller doesn’t need to compute the exact model governing how changing the PWM duty cycle will affect the drone’s orientation; rather it has a “vague intuition” that it needs to e.g., increase the power of the right pair of motors if the drone’s roll angle is leaning too much to the right. And so it will increase these motors’ speed, and will then re-evaluate the drone’s orientation, adjusting the corrective changes it made. This kind of feedback control loop is sometimes called a servo system. Now, you want this control loop to ”learn”, over time, how to compensate for the environment and the drone’s imperfections. And, you want the system to reduce overshoot, and still respond swiftly to environmental changes and control requests. I’ll cover how this control loop actually works (using a PID control loop) in a future post. The main point for now is that we also need an IMU as part of our initial circuitry version. I went for the MPU-6050. As you probably have guessed by now, this was pretty much what I had in my workshop. But it also turned out to be quite popular among drone builders.


The MPU-6050 is a 6-degrees-of-freedom measurement unit. It has 3 accelerometers, measuring acceleration on the X, Y and Z axis. And in addition, it has 3 gyroscopes — measuring angular speed around the X, Y and Z axis. This is a MEMS device — Micro Electro Mechanical System; accelerometers and gyroscopes are, after all, essentially mechanical devices. The chip also has an on-board processor and interface unit; it’s capable of doing some signal processing on the raw readings before providing them to the microcontroller. The WeMos D1 Mini board interfaces to the MPU-6050 using an I2C bus, consisting of 2 wires (one for clock and one for data).


The reason we need 6 degrees of freedom and not only 3 (e.g 3 accelerometers) is because accelerometers and gyroscopes each have their own shortcomings. Accelerometers tend to be noisy (even more so in the presence of 4 vibrating motors…) but they have no drift: they present the current acceleration operating on the IMU — and if we average them over time they would give a consistent readout of drone orientation (tho this averaging means we have some latency in the reading) assuming that the drone remains in place. Meaning, if the drone actually accelerates in some direction this will be picked up by the accelerators as well -- so they won't give a good measurement of drone orientation. Gyroscopes on the other hand tend to be less noisy, so we can take their readouts without too much filtering – and in almost “real time”. However since gyroscopes measure angular velocity, we need to integrate this reading to obtain an estimation of orientation. This integration, combined with computation and measurement imperfections, leads to drift in the computed orientation over time. Hence we use “sensor fusion” to combine an averaged, long-term reading from accelerometers (to compensate for drift over time) with a “here-and-now” estimate of the current orientation based on integrating angular velocities.


So, to summarize — we now have an initial version of a drone frame, with 4 mounted motors, a ULN2803A chip for switching motors, a WeMos D1 Mini as the “brains” and an MPU-6050 IMU for measurement of the drone orientation. The initial build of the drone, excluding propellers, can be seen in the photograph below.



ree
Tiny little drone

Basic Control Software

Now that we have the hardware in place, it’s time to create the basic control software. I started with a PWM generation routine. This is implemented by programming the ESP-8266’s timer to fire an interrupt that will evaluate the selected speed for each of the 4 motors, and turn digital output pins on/off based on timing. The timer is programmed to fire every 10 microseconds. Each motor has its desired PWM duty cycle stored as a number between 0 and 1000. A counter is incremented with each timer interrupt, and reset every 1000 interrupts (1000 interrupts times 10 microseconds mean that the counters are reset every 10 millisecond, or 100 times per second). With each counter reset, all digital output pins corresponding to motors whose required power is > 0 are turned on. With each counter update, any digital output pin corresponding to a motor whose desired power is less than the current counter value is turned off. This means that overall we have 4 independent PWM controls, with a 100Hz update rate and 1000 different speed steps.


Next up is working with the IMU. The drone polls the IMU as often as it can. When the drone boots it starts a “calibration” routine — taking multiple measurements from all IMU sensors and averaging them to establish a “zero point” for each of them. Obviously the drone assumes it’s lying statically on the ground during this process. After this calibration cycle completes, all drone readings are offset relative to the computed zero point. The drone then attempts to compute its orientation based on the raw readings from the IMU sensors and fusion of the different sensors. For current pitch and roll, denoted cpitch and croll below respectively and expressed in degrees:


  • We can use the gyroscopes to update pitch and roll. Assuming dt denotes the time since last update in seconds, and GyroX, GyroY denote angular speed around the X and Y axis expressed in degrees/second, we can say that cpitch=cpitch+dt*GyroX and croll=croll+dt*GyroY.


  • Now X and Y accelerometers are used to estimate current pitch and roll angles. If the drone is “parallel to the ground“ (well, actually if the IMU’s plane’s normal is in the same direction of the force of gravity that’s applied on it), then the earth’s gravity will apply force on the Z accelerometer that will read, roughly, 1g (the gravitational acceleration). As pitch and roll angles grow, Y and X accelerometers will see some acceleration — respectively. If we denote the X, Y, and Z accelerator reading as AccX, AccY and AccZ, and the accelerometer-computed angles as AccRoll and AccPitch, we can say that AccX/sqrt(AccZ^2+AccX^2)=tan(AccRoll) and AccY/sqrt(AccZ^2+AccX^2)=tan(AccPitch). Or, AccRoll=atan(AccX/sqrt(AccZ^2+AccY^2)) and AccPitch=atan(AccY/sqrt(AccZ^2+AccX^2)). Note: In my drone I just looked at atan(AccX/AccZ) and atan(AccY/AccZ). For small enough pitch and roll angles this is probably a good enough approximation (anyway it seems to be working). What we lose by this simplification is that when the drone has both a non-zero pitch and a non-zero roll angle, the angle calculation becomes inaccurate.


  • We can now fuse the two readings. We want the gyro-based reading to have a significant weight in our final estimate, and the accelerometer reading to have a relatively low weight. For pitch we will use: cpitch=beta*cpitch+(1-beta)*AccPitch where we choose beta close to 1. Looking at this equation, it is evident that if the drone is stationary w.r.t pitch — over time cpitch will converge closer to an average accelerometer reading (and thus lose the drift from the gyro estimation); however if the drone‘s pitch changes, the gyroscope reading is used to quickly update it. A similar computation is done for roll as well.


  • Finally for yaw — we only use the Z axis gyroscopes; the accelerometers are obviously not very helpful to compute the yaw angle. Indeed we may see some drift in Quadcopter yaw angle over time. A way to overcome this is to include a Magentometer that can provide a reliable reading of drone bearing. For Quadimodo I felt this was a little too over-the-top :)


Now that we have a PWM and IMU setup ready, what do we actually do with them? I added a simple UDP based control protocol to Quadimodo's code. The drone would send UDP packets with the latest readings from the IMU and the fused orientation evaluation, and would listen for UDP packets that can be sent to update the different motor speeds.


Finally a quick and dirty (mostly dirty!) python script that used gtk to display a rudimentary UI was hacked. The script talks to the drone using the UDP-based protocol; it displayed the current readings and estimated orientation angles, and allows setting the drone motor speeds and updating them.



ree
Yes! He took a "screenshot" using his mobile phone's camera! Ha ha!


And with that, the first draft of Quadimodo is concluded. It doesn’t do much, yet, but the infrastructure is in place. We have a pretty accurate reading of the drone’s orientation, as well as good accurate control of motor speeds. As a prototype it does an ok job.


Unfortunately, this version didn’t seem to have enough power delivered to the motors to actually allow it to lift or even make a significant attempt at balancing the drone. Perhaps the motors are too weak? Or maybe the 500mA limitation imposed by the ULN2803A was too little? A frame structure change? Obviously there’s still some work that needs to be done on the hardware side… More on this, in the next post about Quadimodo.






1 Comment


Avner Gideoni
Avner Gideoni
Sep 28, 2021

Wow. This is impressive. So you know how to write on top of everything else, don't ya.

Like
follow me
  • LinkedIn
  • Twitter

Thanks for submitting!

© 2021 by Eldan Ben-Haim. All rights reserved.

bottom of page