No, I'm not talking about dermatology here.  I'm not that kind of doctor.*  Last week in a blog about modularization of 3D printing I promised to return with more detail about that project.  This is one of those installments.  We're going to talk about one of my favorite aspects of OpenSCAD, the ability to use variables in 3D modeling. 

This is a particularly interesting topic to me because variables probably seem second nature to those familiar with programming in other contexts, but they're not a fundamental concept to many 3D modelers, particularly those who use sculpting tools rather than scripting.  It's like English versus Russian.  Both tools serve the purpose of communication but a fundamental element of English, the article, doesn't even exist in Russian.  That's why Boris and Natasha are always looking for moose and squirrel rather than THE moose and A squirrel.

In this example I'm going to create the box bottom used for my dice/pawn box.  The catch is, I need different sizes of this box -- my Film Tycoons pawns are much taller than standard dice, so a box for the former must be taller than the latter.  Also, I may want to change the width of the box to accommodate more than six dice or pawns, right?  If I were doing this in a standard drag and drop visual editor I'd end up making multiple copies with slightly different sizes.  Very inefficient.   

Incidentally, if you develop an impromptu love of OpenSCAD and you're in the Dallas/Fort Worth area, I'm teaching an introductory course March 8th at the Maker Spot.**

Let's walk through some code!  This is an example, not a tutorial, so I'm going dive into it rather than building up from scratch.  If you're new to scripting I wouldn't expect you to learn the language from this.  Rather, if you're interested in 3D modeling I hope this'll inspire you to consider learning OpenSCAD to pursue it. 


Like many programming languages I'm going to start out defining a bunch of variables.  Ignore the $fn = 50 variable.***  The next three define the width, depth, and height of the box I'm building. 

Next, take a gander at the module boxbottom() declaration.  Like many other programming languages, this declaration and the curly braces create a set of code which can be invoked repeatedly.  In a drag and drop modeling program like Tinkercad you could click on a cube in a sidebar menu, drag it to the work environment, then click and drag handles to re-size it.  In OpenSCAD I can define a shape with a whole mess of code inside the { and }, then create instances of whatever was defined by simply typing boxbottom()

You might have noticed that the module declaration contains an optional variable, ih.  If the module is called without specifying a value the default of 1 will be used.  We'll get to that usage later.

Line 23 is my basic shape.  It's a cube with dimensions defined by three (four) variables: bbow, bbod, and bw+ih.  At their current values this provides me a cube 70mm long, 50mm deep, and 9mm high.  (bw is set to 4, and when I called the module in line 16 I set ih to 5.)   So far I've created a block of plastic.  Not very good for putting things in.

But wait!  Line 23 is actually enclosed in a function, difference().  The first line of difference() defines an object -- all subsequent lines are removed from that object.  So, I start with a cube in line 23, and in line 24 I take away a slightly smaller cube.  Do the math; the dimensions of the second cube are 62 x 42 x 5. 

Important side note: I want the second cube taken away from the center of the first cube.  See that translate() function in line 24?  It moves the forthcoming cube.  My two cubes both align at the origin of [0, 0, 0].  I'm using the variable bw to specify the thickness of my box wall, 4mm.  Translate() moves the second cube to the right by that much, then back by the same amount, then up. 

Of course, the focus here is the scalability.  What if I print this box and determine that 4mm isn't thick enough for the box walls?  Simple -- I change the variable bw.  Lines 23 and 24 adjust the outer cube and inner cubes accordingly.  Want the box to be bigger?  Change bbow to 100 and bbod to 75; all dimensions are adjusted accordingly.

The second part of the boxbottom() module handles the upper part of the box bottom.  As you can see from the picture above the cavity of the box bottom isn't consistent -- the wall actually gets thinner at the top, which accommodates a pressure-fit overlap from the box lid.  I won't walk through the code for that, but will point out the translate() function in line 27.  It's outside the difference() function on the same line, so it applies to everything built in that difference() grouping.  Note the use of bw and ih there -- they raise the second part of the box bottom to the appropriate position.

Just a few more notes on the importance of scalability here.  First, the box bottom is only one piece of the overall "system."  Other modules create the box lid, the shaped inserts, and a name plate -- each of these pieces must scale, so they all rely on the variables defined at the top.  Second, I don't have to render just a single box.  OpenSCAD also allows me to use for-next loops and arrays, a combination which opens up far more possibilities.  More on that in a future blog; arrays are much more fun to demonstrate with Scrabble tiles or Fibonacci spirals, right?  Totally with you on that.

* I first adopted the "DrUsual" handle when playing a first person WWII shooter game.  People invariably asked what kind of doctor I am.  I typically claim to be an Emergency Battlefield Proctologist. 

** Good seats are still available.

*** Okay, I'll tell you.  $fn is a special variable which determines the "roundness" of anything, well, round.  Set it to 6 and every cylinder becomes hexagonal.  Set it to 50 and cylinders are "pretty darn round."  Set it to 100 and they're "really darn round."  The higher this variable is set, though, the longer it takes for a model to render.


Modularization, the Musical

Editorial note: I didn't actually write a musical about modularization.  I just liked the title, and have a theory that Melissa Schmitz only reads my blog if there's alliteration involved.  Sorry for misleading you.

I combined a few projects today to make a gift for someone, as well as some potential prizes for people when we launch our Film Tycoons Kickstarter campaign.  I've been 3D printing personalized dice for a long time and shared earlier the custom pawns I made for the game -- yesterday I built a box specifically for these types of toys. 

But not just any box!  It's a modularized box!  Or rather, the OpenSCAD code to generate the box is modularized.  The point: efficiency of flexibility.  The OpenSCAD script results in one command for each of the box parts: the bottom, the lid, the part-specific insert, and the name plate. You can produce many configurations of the box with hardly any time required, no cloning, re-modeling, etc.

Eric Hallberg, if you're reading this, feel free to borrow the technique for the automobile industry.  Seriously, no charge.  Happy to share.  :)

The lid changes size simply by changing a variable.  The dice fit in the box with the default lid size, so rendering the lid is as easy as typing boxlid().   The Film Tycoons pawns are taller, though, so boxlid(14); makes a taller lid to accommodate.  Likewise, the nameplate is a separate piece which fits somewhat snugly (and even more so with a little epoxy) to the lid; I could have printed the name directly in the lid, but the separate plate allows for a lot more flexibility.

The round or square inserts -- similar approach.  Specify the size of the holes in the insert and the code centers them appropriately. Most important here is that by printing the insert separately the box bottom can be printed ahead of time.  (I didn't take the extra step of combining the round-hole and square hole inserts in a single code block, but I'll likely do that before blogging about the actual code.)

Odd "box" trivia: the Simon & Garfunkel song  The Boxer  is NOT about a dog after all!

Odd "box" trivia: the Simon & Garfunkel song The Boxer is NOT about a dog after all!

Oh, and the length and width of the box?  Also variable-driven.  If I needed ten dice for that Super Secret Professional Double Yahtzee League, it's just a matter of tweaking two numbers and you suddenly have a ten-die box. 

The only part of the project that can't be tweaked and re-printed in seconds* is the Chinese writing.  That's a bigger challenge than putting text on the nameplate; the characters have to be brought into another program as a graphic, converted to a format OpenSCAD can understand and extrude as a 3D object, then incorporated into the model.  Another topic for a later blog.

And Missy, I still feel slightly guilty about the alliteration/musical thing, but I'll try to make it up to you.  Maybe with some 3D printing haiku or something.  You're welcome in advance.

* That's not exactly true.  Nothing 3D prints in "seconds."  At least, not in so few seconds that it wouldn't be more appropriate to measure in minutes or hours.  The more accurate way to say this would be, "...tweaked and started re-printing in seconds."

Dialing In My Frustrating Frustum

Yesterday I decided it would be fun to create a 3D model of a pyramidal frustum.  I have no idea how this popped into my head, but I've decided to blame it on my friend Mike P., from way back in junior high and high school.  Mike had a great knowledge of the esoteric and was quite a good artist.  It's quite possible that while we were playing Car Wars one day he made an offhand comment like, "If I designed a house it would be a pyramidal frustum."  That'd be just like Mike.

So yesterday I decided to model my own pyramidal frustum, and because no project can be left simple, I decided to embed Fibonacci spirals in the faces.  (Plus, anything with a Fibonacci spiral is automatically +5 in Mysterious, right?)  You can see the OpenSCAD code for the modeling if you like, but here I'm going to talk about dialing in the FlashForge Dreamer settings to make a nice print.

The four prints in the photo are ordered left to right from first printed to final print.  The first print's pretty bad.  The copper layers are really uneven and the edges are stringy. The blue spirals look terrible -- the second extruder leaked blue filament everywhere, yet somehow managed to not fill well in the print itself.  Go figure.  I'm using Simplify3D to slice and in that first print, the Hatchbox bronze PLA was set at 180 while the Metalink blue was set to 200.

(My Dreamer has upgraded nozzles which tend to make Hatchbox PLA print at lower temps than the original nozzles.  However, I just got this Metalink filament recently and used it to print all the sea tiles for a Settlers of Catan set quite nicely at 200C.)

For the second attempt I decided to turn on retraction and coast at end.  I was trying to avoid using a priming pillar because pillars really add to the length of a print.  I find that the priming pillar needs to be 10 or 12 mm square, minimum, to NOT break away from the print bed.  When your pyramid is 30mm square at the base, that priming pillar adds significantly to the overall print time.  So, retraction on to 2mm, coast at end of Simplify3D's default .2mm.  Result: a still very crappy looking frustum.

Third attempt: increased the retraction to 5mm and the coast at end to 2mm.  (Yeah, that's a big jump in the coast value.)  I also lowered the temp on my Metalink filament to 190, since it was still leaking little drops of blue all over the place.  The threading seems to have gotten even worse in this one.

Fourth try: all right, I'm turning on the ooze shield.  I use this feature a lot when I print dice, since it helps prevent cross-contamination of the filaments.  I'd been trying to avoid this since it adds to the print time; not quite as badly as the prime pillar, but noticeably.  In this case, the print time went from 36 minutes to almost exactly an hour.  Yikes. 

On the other hand, the ooze shield made that fourth frustum come out far nicer than any of the previous attempts.  I did leave my retraction and coast set the same as the third attempt, but the ooze shield clearly made the biggest difference.  I'll have to experiment further with tweaking the retraction, extra restart distance, and other related settings.  For now though, when someone has a critical need for a pyramidal frustum, I'll have to stick with the ooze shield.