[ 6,683 views ]
Een Nederlandse vertaling van deze post kun je hier vinden.
With every electronic circuit I make, there comes a moment when the project is “finished”…. almost!
The last step is always to find a suitable projectbox and even then it is difficult to provide a (often plastic) projectbox with cutouts of the right size and in the right place.
Fortunately I have a 3D printer and in theory I can make a projectbox myself, but it always takes a lot of time. For standard processor boards you can find 3D STL files on the internet, but if you have “designed” a printed circuit board yourself, the only way is a “parameter controlled” solution that you can read in Fusion 360 or in openSCAD. Then you can specify the size of the box via parameters and sometimes a little more, but it never really “fits” well or it is so complex that you have to graduate before you can make something useful with it.
I think I’ve found a solution that can provide almost any printed circuit board with a nice projectbox: the YAPP generator!
In this post I explain what the principles of this YAPP generator are and how you can use it to 3D print beautiful projectboxes!
What you need
- openSCAD
A recent version of “openSCAD” can be downloaded here. - the YAPP generator
You can download this as a “.zip” file from github. Extract the “YAPP_Box-main.zip” file into your openSCAD projects folder. You now have a new folder “YAPP_Box-main” containing several sample files. In “YAPP_Box-main” there is also a folder “library” that contains the YAPP generator (so don’t throw it away!). It is wise to leave the folder structure as it is and save new box designs in this “YAPP_Box-main” folder.
Design philosophy
Most box generators that you can find on the internet allow you to specify the size of the box. Sometimes you have to give inside measurements and sometimes outside measurements.
YAPP does this differently and starts from the printed circuit board for which you need a projectbox. The most important measurements are therefore the length, width and thickness of the printed circuit board. Then you specify where the holes are with which the printed circuit board should be secured. The holes can be used to secure the PCB with screws or you can clamp the PCB between the standoffs in the bottom and top of the projectbox. Then you can specify for all surfaces (lid, base, front, back, left and right) of the projectbox where rectangular and/or round cutouts should be placed.
Finally, texts can be entered that will be printed at the lid of the projectbox.
Coördination System
Before going further it is necessary to understand what the orientation of the projectbox is. It should be clear that the projectbox has six “planes”.
The top is called “lid” the bottom is called “base”. The plane closest to the Y-axis is the “back”. “left” is closest to the X-axis. The plane opposite “back” (which is furthest from the Y-axis) is called “front” and the plane opposite “left” is called “right”
The “zero point” ([x=0, y=0, z=0]) is always left-back at the top of the PCB.
For each plane there is an array in which you can specify where the cutouts should be in that plane. These cutouts all have (pcb)[0,0,0] as their starting point. So if at any time it is decided to enlarge the edges around the PCB (padding) or to make the “pcbStandoffs” higher, the cutouts will move neatly with the position of the PCB.
Cutouts
There are two types of cutouts: “rectangles” and “circles”. Rectangles can be created in two ways, either with the corners at coordinates or with coordinates in the center of the rectangle. For “circles” the coordinates are always the center point.
Standoffs
The “pcbStandoffs” defines the distance between the top of the “base plane” and the bottom of the printed circuit board. Opposite the “standoffs” are automatically made “pushdowns” on the “lid” that are exactly so long that the circuit board is neatly clamped between them.
The standoffs can be fitted with “pins” so that the printed circuit board is also fixed on the X and Y axes. How many “pcb standoffs” should come and where they should be is specified in the array “pcbStands”. Each pcbStand is specified in one line and the properties of a pcbStand are defined per line.
This is how you use the pcbStands arrayt:

Each line in the array provides one standoff.
The third (2) element has the following meaning:
yappBoth: place both below a pcbStand and above a pcbStand. yappLidOnly: the pcbStand is only printed above (lidHalf) yappBaseOnly: the pcbStand will only be printed at the base (baseHalf).
The meaning of the fourth (3) element is:
yappHole: the pcbStand is provided with a “hole” (hole) yappPin: the pcbStand is provided with a “pin”
If the third (2) element is “yappBoth” and the fourth (3) element is specified as “yappPin” then the pin will be printed on the baseHalf and a hole on the lidHalf.
It is possible to print both below and above a hole by specifying “yappHole” as the fourth (3) element:
[3, 12, yappBoth, yappHole]
Cutouts in the six faces
Pay attention!
All examples are made with version 1.3 of the YAPPgenerator. From version 1.4 on the rows in the cutouts arrays have an extra parameter “angle”. For existing designs it suffices to add them with the value “0” (zero) directly before yappRectangle or yappCircle.
For each face there is an array in which you can specify per line where cutouts should come, what the origin of such a recess is (for rectangles) and what shape the recess should have (rectangle or circle). Depending on the “plane”, the first element is the position on the X-axis (lid-, base-, left- or rightPlane) or the Y-axis (front- or backPlane) and the second element is the position on the Y-axis (lid-, base-, left- or rightPlane) and the Z-axis (front-, back-, left- or rightPlane). The third element always indicates the width of the rectangle or the diameter of the circle. The fourth element is, again depending on the plane, the width (lid- or basePlane) or the height (front-, back-, left- or rightPlane) of the rectangle.
Cutouts in the Front Plane
Cutouts in the Back Plane
Cutouts in the Lid Plane
Cutouts in the Base Plane
Cutouts in the Left Plane
Cutouts in the Right Plane
Rectangular cutout at an angle
Base Mounts
To be able to mount the project box you can define so called “Base Mounts”.
Connectors to connect Base and Lid together
The connectors are ideal for connecting the two halves with so-called “inserts”.
Snap Joins
With snapJoins the Base and Lid “click” together without the need for screws or other aids.
A life real example
In this example we are going to create a projectbox for an Arduino UNO.
We start in openSCAD by opening the file “YACC_template.scad” and immediately save it again (“[Save as]) with the name “ArduinoUNO”.
Make sure that the new file is saved in the folder “YAPP_Box-main”.
Now edit the comment lines at the top of the file so that it is clear that a projectbox for an Arduino UNO can be generated with this file. The first real line of code inserts the YACC generator after which the YAPPgenerate() module from this library can be used.
include <./library/YAPPgenerator_v13.scad>
Outer dimensions and stand-offs
Now all variables that determine the final projectbox must be measured one by one and entered into the “ArduinoUNO.scad” file.
pcbLength = 68.5; pcbWidth = 53.3; pcbThickness = 1.5; pcbStands = [ [14.0, 2.5, yappBoth, yappPin] // back-left , [15.3, 50.7, yappBaseOnly, yappPin] // back-right , [66.1, 7.6, yappBoth, yappPin] // front-left , [66.1, 35.5, yappBoth, yappPin] // front-right ];
Connectors
The height of both the USB plug and the powerJack is 11mm.
To add some slack, let’s start the USB plug and the powerJack 1mm closer to the X-axis and increase the width of the cutout for the USB plug by 2mm and the cutout for the powerJack by 3mm. We will also increase the length of both cutouts slightly.
cutoutsLid = [ [0, 31.5-1, 12.2+2, 11.0, yappRectOrg] // USB , [0, 3.5-1, 12.0, 13.5, yappRectOrg] // Power Jack ]; cutoutsBack = [ [31.5-1, -1, 12.2+2, 12, yappRectOrg] // USB , [ 3.5-1, 0, 12.0, 11, yappRectOrg] // Power Jack ];
Headers and ATmega
cutoutsLid = [ [0, 31.5-1, 12.2+2, 11.0, yappRectOrg] // USB , [0, 3.5-1, 12.0, 13.5, yappRectOrg] // Power Jack , [29-1, 12.5-1, 8.5+2, 35.0+2, yappRectOrg] // ATmega328 , [17.2-1, 49.5-1, 5.0, 47.4+2, yappRectOrg] // right headers , [26.5-1, 1.0-1, 5.0, 38.0+2, yappRectOrg] // left headers ];
Other cutouts
Finally, the positions and size of the ICSP connectors, reset button and LEDs must be measured.
The total definition of the cutoutsLid array then looks like this:
cutoutsLid = [ [0, 31.5-1, 12.2+2, 11.0, yappRectOrg] // USB , [0, 3.5-1, 12.0, 13.5, yappRectOrg] // Power Jack , [29.0-1, 12.5-1, 8.5+2, 35+2, yappRectOrg] // ATmega328 , [17.2-1, 49.5-1, 5.0, 47.4+2, yappRectOrg] // right headers , [26.5-1, 1.0-1, 5.0, 38.0+2, yappRectOrg] // left headers , [65.5, 28.5, 8.0, 5.5, yappRectCenter] // ICSP1 , [18.0, 45.5, 6.5, 8.0, yappRectCenter] // ICSP2 , [6.0, 49.0, 8.0, 0.0, yappCircle] // reset button //-- if space between pcb and lidPlane > 5.5 we don't need holes for the elco's -- // , [18.0, 8.6, 7.2, 0.0, yappCircle] // elco1 // , [26.0, 8.6, 7.2, 0.0, yappCircle] // elco2 // , [21.5, 8.6, 7.2, 7.0, yappRectCenter] // connect elco's , [28.2, 35.2, 5.0, 3.5, yappRectCenter] // TX/RX leds , [28.2, 42.5, 3.0, 3.5, yappRectCenter] // led13 , [58.5, 37.0, 3.0, 3.5, yappRectCenter] // ON led ];
In order to actually generate the projectbox, this module call must be placed at the bottom of the program:
//--- this is where the magic happens --- YAPPgenerate();
Then click on [F5] or [F6] to see the result of your work.
Second example (Wemos D1)
In this example we will create a projectbox for a Wemos D1 mini (V3.0.0). The starting point is again the YAPP_template.scad file which we read in and immediately write back as “WemosD1Mini.scad“.
First we have to measure all sizes again.
The “outer dimensions” are put at the top of the script.
wallThickness = 1.5; basePlaneThickness = 1.0; lidPlaneThickness = 1.0; baseWallHeight = 4; lidWallHeight = 4; pcbLength = 35.0; pcbWidth = 26.0; pcbThickness = 1.0; // padding between pcb and inside wall paddingFront = 1; paddingBack = 1; paddingRight = 1.5; paddingLeft = 1.5; // ridge where base and lid off box can overlap // Make sure this isn't less than lidWallHeight ridgeHeight = 2; ridgeSlack = 0.1; // How much the PCB needs to be raised from the bottom // to leave room for solderings and whatnot standoffHeight = 2.0; pinDiameter = 1.8; pinHoleSlack = 0.1; // depending on nozzle diameter standoffDiameter = 4;
The positions and size of the cutouts are included in the cutoutsLid, cutoutsBase, cutoutsFront, and cutoutsRight arrays.
//-- pcb standoffs -- origin is pcb-0,0 pcbStands = [ [3.4, 3.0, yappBoth, yappPin] // back-left , [3.4, pcbWidth-3, yappBoth, yappHole] // back-right , [pcbLength-3, 7.5, yappBoth, yappHole] // front-left , [pcbLength-3, pcbWidth-3, yappBoth, yappPin] // front-right ]; //-- front plane -- origin is pcb-0,0 (red) cutoutsFront = [ [14.0, 1.0, 12.0, 10.0, yappRectCenter] // microUSB ]; //-- top plane -- origin is pcb-0,0 cutoutsLid = [ [6.0, -1.0, 6.0, pcbLength-12, yappRectOrg] // left-header , [6.0, pcbWidth-4, 6.0, pcbLength-12, yappRectOrg] // right-header , [18.7, 8.8, 2.0, 0.0, yappCircle] // blue led ]; //-- bottom plane -- origin is pcb-0,0 cutoutsBase = [ [6.0, -1.0, 6.0, pcbLength-12, yappRectOrg] // left-header , [6.0, pcbWidth-4, 6.0, pcbLength-12, yappRectOrg] // right-header ]; //-- left plane -- origin is pcb-0,0 cutoutsLeft = [ [31.0, 0.5, 4.5, 3, yappRectCenter] // reset button ];
Note that there are only two holes in the circuit board. To keep the printed circuit board in place, four pcbStand are made, but two of them have no pins. Because there is a reset switch in the left front corner, the pcbStand must also be placed in a slightly shifted place in this corner.
Last step is to make some “snapJoins” in the left, right and front panes:
//-- snap Joins -- origen = box[x0,y0] // (0) = posx | posy // (1) = width // (2..5) = yappLeft / yappRight / yappFront / yappBack (one or more) // (n) = { yappSymmetric } snapJoins = [ [shellLength-17, 5, yappLeft] , [shellLength-10, 5, yappRight] , [(shellWidth/2)-2.5, 5, yappBack] ];
Finally, the YAPPgenerate() module must be called:
//--- this is where the magic happens --- YAPPgenerate();
Then press [F5] or [F6] to check if the project box looks as you imagined.
Debug options
There are several options for viewing additional information about the generated projectbox so that it can be checked during the design phase whether the script does what it should do.
printLidShell = true; printBaseShell = true; //-- D E B U G -------------------- default showSideBySide = true; // true hideLidShell = false; // false colorLid = "yellow"; // yellow hideBaseShell = false; // false colorBase = "white"; // white showPCB = false; // false showMarkers = false; // false inspectX = 0; // 0=none, -pcbLength .. +pcbLength inspectY = 0; // 0=none, -pcbWidth .. +pcbWidth //-- D E B U G -------------------
The first two variables (printLid and printBase) indicate whether the top half of the projectbox or the bottom half should be printed. This can be useful if your 3D printer is not large enough to print both halves side by side or if you have only made adjustments in one of the two and (so) only want to 3D print that half again.
showSideBySide
hideLidShell / hideBaseShell
This setting provides insight into the “inside” of the projectbox.
showPCB
This option is especially useful in side-by-side presentation or when showLid and/or showBase are “false”.
showMarkers
Markers are displayed on the four corners of the circuit board and on the rear left corner of the box.
inspectX / inspectY
With a value of -pcbLength to +pcbLength, a cross section of the projectbox is shown.
inspectX negative inspectX positive
Other Exampels
In special cases you want to be able to create objects that cannot be created with the standard arrays. For this, there are four so-called “hooks” that make it possible to define these special objects in the project box or outside the project box. These hooks are called:
- lidHookInside()
- baseHookInside()
- lidHookOutside()
- baseHookOutside()
Suppose you have two push buttons on the PCB that you of course want to be able to operate when the PCB is in the project box. Three things have to be arranged for this.
- You have to define two round holes in the Lid;
- On the inside of the lid there should be two round guides for the “switchExtenders”;
- The switchExtenders must be printed. Because they are not connected to the project box, they can be included in a separate scad file or simply printed “next to the project box”.
For an ESP-CAM you want to make it possible to put it “tiltable” on a foot. You can use the “lid- or baseHookOutside” modules for this.
Snap Joins
A “snapJoin” is a bulge in the Base that fits exactly in a hole in the Lid. A snapJoin clicks the Lid onto the Base without screws or anything else.
Often you want the snapJoins to be applied symmetrically on one or two sides. This can be done by specifying “yappSymmetric” in a snapJoin row as the last argument.
Note: snapJoins can only be created if the ridgeHeight is not lower than 3mm!
Outstanding. And outstanding documentation of this complex project. I’m sure it took quite some effort. Thanks for sharing!
Thanks!
Thank you so much for this project!
Well, I just needed a project box myself and could not find anything that I could use or understand…
Thanks for the complement!
Mounting tabs? Is there any way to put tabs/ears on the outside of the box to allow for screw mounting to a surface? Alternatives I’m not thinking about?
Really great project. Thanks for all the effort and the excellent documentation
Hi Andrew,
Thanks for the compliment!
You can use an array “baseMounts” (see YAPPtemplate.scad) to create … well, “baseMounts”!
Februari 8, 2022
I have updated the documentation with the use of so called “Hook” modules and “base Mounts”
Wow, this is fantastic! It would have saved me a couple of hours of modeling on my last project! (I’m a newbie and very slow in F360 🙂 Thanks!!
Thanks!
Yes F360 is the best .. if only we knew how to use it! What a steep learning curve 🙁
Willem: I’m so glad I found your project on GitHub. This is not “yet another” project box generator. IMHO it definitely is the “premier” project box generator, against which all others will be measured. Good job! Your hard work and OpenSCAD expertise is much appreciated.
Wauw!
Thanks for the nice words!
Complimenten voor deze goed doordachte generator en de documentatie!
Ik ben blij deze gevonden te hebben en zal m veel gebruiken.
Thanks!
There is a new version of the YAPPgenerator (version 1.4) on GitHub.
This version ‘breaks’ from the previous versions in terms of the rows in the cutouts arrays. A new parameter ‘angle‘ has been added after ‘height‘ and before ‘yappRectangle‘ (or ‘yappCircle‘). Rotates the recess of a rectangle (yappRectangle) around the origin (either the angle x/y points to or the center of the recess if yappCenter is also specified).
You can keep using your existing pré 1.4 project boxes by adding a 0 (zero) as the “angle” parameter.
I’m confused. Did the user interface just change?
I just gave your “YAPPgenerator_v14.scad” a try and all of my rectangular cutouts disappeared! I am using OpenSCAD version 2021.01.
Before (with YAPPgenerator_v13.scad):
After (with new YAPPgenerator_v14.scad):
BTW: I really find your library very useful. I’ve made three different tiny enclosures for what I’m currently prototyping.
Yes, as you can read in the README.md and in the documentation there now is an extra param “angle”.
Thanks for the clarification. I clearly missed the warning on “github”. Now you need to update all of your examples and figures unless you plan to maintain v1.13 and v1.14 in parallel. Isn’t having “users” a PITA? Clearly they should pay you more for this! 🙂
If only they would 😉
Yes, as you can read in the README.md and in the documentation there now is an extra param “angle”.
Willem, perfect generator, thank you. Works out of the box with my Prusa printer.
Two feature request:
– rectangle lidhook module for printing transparent light guide from the circuit board SMD led to the lid surface.. probably can be done with cylinder but I have more leds in a row
– option to create mesh on any of the walls – good to keep the lid ventilated to remove heat from the components or allow air exchange for e.g. moisture and temperature sensor
Thanks for the complement.
How do you “see” a mash for the leds? You can always use openSCAD without the YAPPgenerator to create something like that .. or amI missing the point?
Why can’t you use the existing lidHook?
There are several examples for creating ventilation cutouts.
OK, I will check about the mesh outside of YAPPgenerator.
Led light guides should be something like this printed with transparent material.
I wonder if a printed light guide will work…
Hello Willem and thank you for this very handy generator.
I do have one single problem with the generator. I would like to make holes for cables into the box and center this holes/circle cutouts exactly where lid and bottom join. This way i can move the PCB out of the box and exchange the box if damaged or i did come up with a better design. Definition:
cutoutsRight = [
[ 20, 10, 8, 8, 0, yappCircle],
[ 40, 10, 8, 8, 0, yappCircle],
[ 60, 10, 8, 8, 0, yappCircle],
[ 80, 10, 16, 16, 0, yappCircle]
];
It doesnt matter which Z position i choose, its never exactly a half circle. Any hint how i can accomplish this?
Hi Arnd,
Nice you like my generator!
Have you actually printed one of these?
Do you use the latest version of the YAPPgenerator?
I do think they are correct but due to the overlap (ridge) in the top and bottom halve they seem shifted.
If you display them “on top of each other” with zero offset it gives you a rather good impression of what to expect.
I have done this myself for a few boxes and they came out right.
Hi There,
very nice generator indeed!
One question:
How do I get the connectors[] to also honor the PCB thickness and subtract it from the bottom standoff?
Use case is: I want to save PCB space and not use a separate pcbStand[].
I would screw through a PCB hole into the insert in the top, effectively securing the PCB and connecting base/lid in one go…
Thanks,
Oliver
I’m not sure what you try to accomplish.
You can make a hole in the bottom at the exact location of the stands in which case you can screw from the bottom to the insert in the top.
Willem,
please see attached picture. I want to screw from the bottom through the PCB into the insert.
This will allow me to hold the PCB in chassis AND connect base/lid in one go – with only 4 mount points. No pcbStand[] needed.
Best,
Oliver
As I said; You define the pcbStands for only Base as “yappHole”. Then you define the same for Lid, again as “yappHole”. Then on the Base you define the cutouts as circle on the same position as the stands (maybe with a larger diameter for the screw head to fit in).
Willem, thanks for your help on this.
Was trying with your proposed way, see attached picture, item 1. A screw from the bottom would only attach the PCB to the top lid, right? The base would fly off. It is not beeing held by the screw head.
But I think I have a hack/workaround. If I create a cylinder at the right spot via BaseHookInside(), the screw head has something to hold to and keeps the whole assembly together.
See item 2 in the picture.
This should work, I hope. Will try it out.
Thats exactly where the “hooks” are for!
Willem,
if you are interested, I added a connectorsPCB[] to the library (see my github repo).
origin is PCB instead of box, and it subtracts the PCB thickness from the base connector.
Just minimal testing, did not do a print using this yet.
Best,
Oliver
Oliver,
Can you give a code example of “how to use these”?
I think it’s a very usefull extension to the YAPPgenerator!
Regards,
Willem
Hi Willem,
This is great! Just printed my first YAPP-box for a Wemos D1 R2 with space for the C1101, looks really nice.
Would it be possible to insert an additional wall? To compartmentalize a PCB from a sensor for example? It would also be great if there can be cutouts in the additional wall for wires.
Thanks,
Ben
Hi Ben,
Nice you like the YAPPgenerator.
You can use the in- and outsideHooks and you can use all the futures of openSCAD to make a box exactly to your likings!