OpenScad Tutorial 1: Design of Magnolio's Main Body

Fork me on GitHub



As introduced in my previous post, Magnolio: An Open Source 3D-printed quadcopter, this is the first of a series of posts in which I will describe the creation process of the printed parts of Magnolio in OpenScad, a Solid 3D CAD modelling software. I have decided to do it as a tutorial, so it can also help those of you who are learning, or as a reference. Now, I don't consider myself an expert in OpenScad, so this may as well be a way in which you can leave me a comment telling me how to do it better 🙂 We'll start with the main body part:

Design Concept

This part is designed to house the power electronics, as well as holding the carbon fiber tubes that form the arms of the quadcopter:

Assembled body

Assembled body

On the above picture, the red boxes represent the ESCs (Electronic Speed Controllers for the motors) and the blue object in the middle is the connections PCB. This part supports the whole drone together, it is subject to plenty of torsion and the plastic is not strong enough for this by itself. For this reason, I added the carbon fiber bars on top (on grey) and bottom (barely visible on above picture), they are very important as they add structural rigidity.

Carbon Fiber

I got the carbon fiber bars at my local RC Hobby store, but they can be found online here, for example. The design uses 2mm x 19 mm bars. They are usually sold in 1 meter strips.

Carbon fiber bar (or strip)

Carbon fiber bar (or strip)

The arms are carbon fiber tubes, 12mm and 10mm external and internal diameter respectively. They are sold in 400mm length. I got them at Hobbyking. I have not decided the length of the arms, it will depend on the propeller diameter.

Carbon fiber tube for arms

Carbon fiber tube for arms


A good question is: how do we hold tubes, bars and body together? I will drill holes with the cross bars, tubes and body in place, so they can be fixed with screws, which is why am not including the holes in the 3D model.

Coding the 3D model

Now, let's get started with the 3D printed part on OpenScad. If you haven't done so already, download and install OpenScad. I recommend first going through the first steps tutorial, which will only take about 10min. Have the Language Manual at hand and also the OpenScad Cheatsheet.

Step 1: Body Base

We start by declaring variables that hold the main dimensions of the model. Then just draw a simple box with the command cube:

If you press F5, you'll see something like this: Magnolio_body_1   On this code we can immediately see one of the most powerful features of OpenScad: parameterization. You can define key variables that determine an object and then just change their value if you need to. The model will change accordingly. Now, to create the primitive model the approach is to intersect the previous box with another that is rotated and a bit smaller: Magnolio_body_2   The result will be the area that looks solid in the above picture. We'll use the intersection command, like this:

The new lines of code are marked in yellow. Notice the new variable body_ratio, it is used to set the dimensions of the second cube with respect to the first one. The intersection command holds all of the operations to intersect in its statements, the result is the common body between all of the objects within this command's nested operations. The second body for the intersection is another box, rotated 45Âș around the Z axis, 90% (set by the body_ratio variable) of depth and width of the other box and the same height. Notice how the rotate command precedes the cube command, this is the way to rotate objects. If the object to rotate is made out of more than one operation, you need to enclose them in {...} symbols. This code results in: Magnolio_body_3   Which, as you can see, is the primitive shape of the design.

Step 2: Inside cavities

Now we need to add some space for the electronics inside. This is done by using the difference command:

Notice how all of the previous code goes inside the difference operation. This is how the difference command works: the body resulting from the second operation (a cube, in this case) is subtracted from the body resulting from the first operation (intersection of two cubes, in this case). If there was a third operation, it would also be subtracted from the first, and so on. The result is: Magnolio_body_04 Repeat the above with a 90Âș rotation to get a symmetric cavity:

Magnolio_body_05 And now subtract another two cubes to make space for ESCs, in this case, we have to rotate them 45Âș with respect to the other two cavities:

Notice the new variable wall_width, which is used to calculate the value of variable resulting_inside_w. This variable is then used to dimension the cavity for ESCs, together with variable ESC_cavity_width, which's value was entered after physically measuring the ESC. Again, notice how these variables allow us to easily change dimensions according to our needs. If you chose a different ESC, for instance, you could just enter the correct dimension, render the model again and that's it. The echo command is used to display the resulting values of calculated variables on the OpenScad console . The result looks like this: Magnolio_body_06 As you can see, what's left of the primitive body is just the walls and four hexagonal prisms, which will hold the arms, and into which we'll introduce the cavities to do so.

Step 3: Arm tube cavities

We need to add cylindrical cavities for the arms. There is a cylinder command, that we can use for that. To do this, we can subtract two cylinders that go across the hexagonal prisms from the current object, one rotated 90Âș from the other, like this:

Tube cavities subtration illustration

Tube cavities subtration illustration. The subtracted part is marked in transparent red.

The cylinder command, with the center=true option, will draw a vertical cylinder across the Z axis, this means we'll need to rotate it 90Âș around the X axis to make it lay horizontal first, the result of this operation is subtracted from the current body. We repeat this with additional 90Âș rotation around the Z axis to get the other cylinder subtracted:

Note that we are still working inside the difference statement, subtracting from the current body. Be sure to check the cylinder command documentation (and that of all the other commands we've used, actually), as there are many other ways to use it.

The trouble with the difference command is that you can't see what you are subtracting. Therefore, it is useful to place the operations that generate the subtracted bodies outside the difference statement first, as illustrated in the previous picture. Press F5, and you will see how they intersect with the rest of the bodies and be sure that the subtraction you are performing is correct. Make the necessary modifications if something is wrong, and then move the operations back to the difference statement.

The above code results in: Magnolio_body_08

 Step 4: Cross Bars Cavities

Now we'll add cavities for the carbon fiber bars that were added to de design to strengthen the structure. This operation is very similar to the previous one, but we'll use the cube command instead of the cylinder. The cavities should be placed above the hexagonal prisms, one pair will be as deep as the height of the bar, and the other pair double as much, in order to give space to the other bar. We'll see what I mean in a minute:

Representation of the <i>difference</i> operation carried out to make cross bars cavities.

Representation of the subtract operation carried out to make cross bars cavities.

The code for this is as follows:

This is the first time we've used translate command. The subtracted boxes are moved upwards and downwards the necessary amount in order to put them exactly at the top and the bottom of the body. Note that two of these operations are preformed with a double-height bar, which is necessary in order to make room for the other bar. Furthermore, the double-height cavity at the bottom is placed on the opposite side as the one at the top, so we don't weaken the part too much with this material removal. The result looks like this: Magnolio_body_10

Step 5: Platform for Electronics

We need a base for placing the electronics. It should be placed above the cross bars height. As it has the same base shape, we will use the same approach as for the initial base body, with the intersection command:

Indeed, the operation is the same as the base body, but with different height. Of course, now we are adding code outside the difference statement because we are not longer subtracting. The platform is translated downwards to just above the bottom cross bars level. The result is: Magnolio_body_11 Next, we add a hole for passing the battery cables (probably other signal cables too):

Now our body looks like this:   The hole is not centered, where it would coincide with the connections PCB cables hole, but rather shifted to one side. This is because otherwise the hole would be blocked by the cross bars.

Step 6: ESC Separators and PCB Holder

The last step is to add some structures that will help organizing and holding the electronics in place. We start by adding  elevators that will support the PCB and holes for fixing it with screws and nuts, then we add separators for the ESCs. We'll use a for loop for this:

Ok, I know this was a lot of code in just one step, but look carefully: the only thing new about this new code is the for loop. It is basically repeating the same operation but with a different value for variable ang each time. It starts at 0Âș and goes to 270Âș with 90Âș increments. This means the operation is carried out four times. Each time, one support for the PCB with a hole in the middle is placed, plus two separators for the ESCs. The result is the final body for the drone, which looks like this: Magnolio_body_14

Step 7: Module

All of the parts of Magnolio are stores in a single library file. If you look in the repository, you'll find the code for all of the parts in 3D/Magnolio_parts.scad. Therefore, the above code must become a module, so we can call it from the assembly file, the print file or any other we want. The final code is then:

Note that the dimension variables remain there as a global part of the library, not as part of this module in particular. The reason for this is that we'll use those variables for other modules too. If a change is made in a measure, it must be reflected on all parts, so that they'll fit together once they are assembled.

Printing and Assembling

I printed this part with my RepRap. For reference, here are the most important settings I used for printing, mainly Slic3r settings:

MaterialBlack ABS, 3mm filament
Layer height:0.3mm
Solid layers4 (top), 4 (bottom)
Infill25%, honeycomb pattern
Speed50mm/s (perimeters), 80mm/s (infill)
Suport Material - Overhang threshold85Âș
Support Material - Patternrectilinear
Temperature240ÂșC (extruder), 120Âș (bed)
Here are some pictures of the result, which took about 6 hours to finish:

Printed Main Body, just finished

Printed Main Body, just finished

Notice the support material on the arms holes, that was hard to get cleaned! Here is a look of the bottom, just starting to remove the support material:

Main Body, bottom view. Removing support material.

Printed Main Body, bottom view. Removing support material.

And this is how it is looking now that it is semi-assembled:

Semi-Assembled body with electronics

Semi-Assembled body with electronics

Like it?

I hope this tutorial has been helpful. I tried to include a lot of detail and directions so if would help you, at least as a reference, for your own designs. Whether you liked this or not, please drop me a comment, I'd love to learn from your experience, so I can improve this work and what's to come. I invite you to take a look at Magnolio on Github. If you want to become a contributor, just let me know. There are four more parts to cover, so I also invite you to stay tuned for more tutorials on Magnolio and the forthcoming posts in which I will share the details of the assembly process and, hopefully soon, the first flight!

Leave a Reply

Your email address will not be published. Required fields are marked *