Enter Your Electronics & Design Project for a chance to win a $100 Shopping Cart!

Back to The Project14 homepage

Project14 Home
Monthly Themes
Monthly Theme Poll


Enclosure modelled in OpenSCAD

It's all very well deciding that the PCB itself will be the front panel for my lock, but it will still need an enclosure. I decided that I'd tackle the simplest lock first - and that was my garage door. The reason for this is that all I have to do is simulate a button press, At worst a relay across the existing push-button would do. Of course, that still leaves the issue of how to mount it outside the garage. Once again, this is probably the simplest use case. I can go with a 3D printer box and route the cable straight through the single-skin brickwork of my garage.


Being a coder at heart, my tool of choice for 3D modelling is OpenSCAD. It's very different from the more artistic modelling tools, but particularly suits a parametric design. I've tuned my workflow over the years and this is what I find works for me:

  • Make sure anything I think I might change is a variable. Depth of the enclosure, PCB thickness, clearances - all of these are easy to change after a bit of trial and error.
  • Use Visual Studio Code as an editor and set OpenSCAD to auto-preview whenever it is saved.
  • Include things like the PCB itself as a component. It will never be printed, but it helps visualize what;s going on.
  • Model the pieces (e.g. the main upper bit and the lower) in-place. Render them together and comment out all but one when doing a final export


<Here's the code for my enclosure. Notice that the PCB module is prefixed with %. This makes it partially transparent. Notice also that the lower is shifted with one (optional) line so I can visualise the whole thing.


pcbThick = 1.65;
pcbX = 60;
pcbY = 100;
pcbZ = 1;

fit = .2;

wallThick = 3;
wallInner = wallThick-wallSlot;

cutY = wallThick+1;

boxX = pcbX + 2* wallInner;
boxY = pcbY + 2* wallInner;
boxZ = 25;

fixZ = boxZ-12;
fixY = 7;

module main() {
    difference() {
        cube([boxX, boxY, boxZ]);

        translate([wallThick, wallThick+fixY, wallThick])
            cube([boxX-2*wallThick, boxY-2*wallThick-fixY, boxZ]);

        translate([wallThick, wallThick, fixZ])
            cube([boxX-2*wallThick, boxY-2*wallThick, boxZ]);


        translate([15,-0.1,10]) m3screw();
        translate([boxX-15,-0.1,10]) m3screw();

module upper() {
    difference() {
        translate ([-1,-1,-1]) cube([boxX+2, cutY+1, boxZ+2]);

module fixture() {

module m3screw() {
    rotate([-90,0,0]) {

module cable() {

    translate([wallThick, (boxY-cableY)/2, -1])
            cube([boxX-2*wallThick,cableY, boxZ]);

module mounting() {
    translate([boxX/2,boxY/2+35,-1]) cylinder(r=2,h=boxZ);
    translate([boxX/2,boxY/2-35,-1]) cylinder(r=2,h=boxZ);

module lower() {
    translate([0,0,-boxZ-1]) { // Move so you can see both
        difference() {
            translate ([-1,cutY,-1]) cube([boxX+2, boxY, boxZ+2]);


module PCB() {
    translate([wallInner+fit, wallInner+fit,boxZ-pcbZ-pcbThick])

module slot() {
       minkowski() {
            translate([0,0,-fit/2]) cylinder(r=fit, h=fit);



It took a few iterations. I didn't have enough clearance for the connections to the bottom of the PCB. The PCB was a bit too snug of a fit first time round, and I decided to have the back fairly open rather than just a hole for the cable. I prototyped in a yellow filament as I tend to use up too much of the black. I was almost tempted to leave it in yellow to make it easier to find in the dark, but I'm glad I went with the black in the end.


2 versions of the enclosure Enclosure mounted on wallI didn't make a firm decision as to how I'd connect to the board when designing it. I created some SMT pads on a 0.05" spacing. Initially I soldered on a single row of through-hole header pins that I'd bent at an angle to make them surface mount. I worked pretty well, but I suspected that a attaching a female header a few times might left the pads. Also it stuck out a bit too much and fouled the enclosure I'd printed. I decided to make it lower profile by soldering wires directly. I used a bit of hot glue for strain relief - especially when sliding into the enclosure from below. I can detach the PCB from the rest of the circuit with a Molex microfit connector that pushed through the hole in the garage wall.


All in all, I'm pretty happy how it turned out. I was tempted to use a resin printer to get a nicer finish, but I've found from experience that it can be hard to get nice flat shapes printed without warping, and I think the end result is good enough - especially as it's hidden round the side of the garage out of view. This was the easiest place to drill through the wall.


Next post - firmware >>