Moved iotsa board retainer a bit

Moved iotsa board retainer a bit

//
// This is the iotsa board itself, including the important connectors and
// holes. You can define here if you have shortened the board, which will
// not only change the board itself, but also the box we are going to create around it.
//
numberOfRowsRemoved = 0;
extraMMRemoved = 0; // 0 if nothing removed, 2.2 if any rows removed.
numberOfMMRemoved = extraMMRemoved + (numberOfRowsRemoved*2.54);
iotsaBoardXSize = 63.5 - numberOfMMRemoved;   // one dimension of the unmodified board
iotsaBoardYSize = 43.5;   // the other dimension of the board

boardThickness = 1.8; // The thickness of the PCB board
regulatorAngle = 35; // 0, or higher if you've bent the regulator over backwards.

esp12AntennaStickout = 5; // How many mm the esp12 antenna sticks out of the iotsa board

module iotsaBoard() {
    module esp12() {
        union() {
            cube([24, 16, 2]); // the esp-12 board
            translate([8, 1.5, 2]) cube([15, 13, 2.5]); // the metal cap
        }
    }
    module regulator() {
        rotate([-regulatorAngle, 0, 0])
        translate([0, 0, 5])
        union() {
            translate([0, 4.5, 0]) cube([10.2, 1.3, 15]);
            translate([0, 0, 0]) cube([10.2, 4.5, 8.5]);
        }
    }
    module powerjack() {
        difference() {
            cube([9, 15, 11]);
            translate([4.5, -1, 7]) rotate([-90, 0, 0]) cylinder(14, d=6);
        }
    }
    translate([0, 0, -1.8])
    union() {
        // The board
        difference() {
            cube([iotsaBoardXSize,iotsaBoardYSize,1.8]);
            translate([2, 2, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([2, 41, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([36.5, 2, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([36.5, 41, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([60.5, 2, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([60.5, 41, -0.1]) cylinder(2, d=2, center=false, $fn=12);
        }
        // The components
        translate([-esp12AntennaStickout, 13.5, 1.8]) esp12();
        translate([20, 15, 1.8]) regulator();
        translate([22, -3, 1.8]) powerjack();
    }
}

//
// Box parameters. We are going to compute the size from the parameters.
//
iotsaComponentHeight = 14;  // Make sure this is high enough
iotsaSolderingHeight = 3;   // How far the soldering extends below the board.
boxThickness = 1.5;
boxBottomThickness = boxThickness;
boxFrontThickness = boxThickness;   // This is where the power connector is
boxLeftThickness = boxThickness;
boxRightThickness = boxThickness;
boxBackThickness = boxThickness;
boxTopThickness = boxThickness;

leeWay = 0.3;   // gap we want between board and box (on all sides, individually) and around connector

// Computed parameters
innerXSize = iotsaBoardXSize + esp12AntennaStickout + 2*leeWay;
innerYSize = iotsaBoardYSize + 2*leeWay;
innerZSize = boardThickness + iotsaComponentHeight + iotsaSolderingHeight + 2*leeWay;

outerXSize = innerXSize + boxLeftThickness + boxRightThickness;
outerYSize = innerYSize + boxFrontThickness + boxBackThickness;
outerZSize = innerZSize + boxBottomThickness + boxTopThickness;

strutThickness = 2;
retainerWidth = 3;
retainerLength = 6;

module box() {

    module basicBox() {
         difference() {
            cube([outerXSize, outerYSize, outerZSize]);
            translate([boxLeftThickness, boxFrontThickness, boxBottomThickness])
                cube([innerXSize, innerYSize, innerZSize+boxTopThickness+1]);
        }
    }

    module completeBox() {
     translate([-esp12AntennaStickout-boxLeftThickness-leeWay, -boxFrontThickness-leeWay, -(boardThickness+iotsaSolderingHeight+boxBottomThickness+leeWay)])
        union() {
            // The box itself, with the cutouts for the lid
            difference() {
                basicBox();
                // Front cutout
                translate([boxLeftThickness, -0.5*boxFrontThickness, outerZSize-boxTopThickness])
                    cube([innerXSize, 2*boxFrontThickness, 2*boxTopThickness]);
                // back cutout
                * translate([boxLeftThickness, innerYSize+boxFrontThickness-0.5*leeWay, outerZSize-boxTopThickness-boxBottomThickness])
                    cube([innerXSize, 0.5*boxBackThickness+leeWay, 0.5*boxTopThickness]);

                // front left retainer hole
                translate([boxLeftThickness,-0.5*boxFrontThickness, outerZSize-boxTopThickness-retainerLength])
                    cube([retainerWidth, 2*boxFrontThickness, retainerWidth]);
                // front right retainer hole
                translate([outerXSize-boxRightThickness-retainerWidth, -0.5*boxFrontThickness, outerZSize-boxTopThickness-retainerLength])
                    cube([retainerWidth, 2*boxFrontThickness, retainerWidth]);

                // back left retainer hole
                translate([boxLeftThickness,innerYSize+boxFrontThickness-0.5*boxBackThickness, outerZSize-boxTopThickness-retainerLength])
                    cube([retainerWidth, 2*boxBackThickness, retainerWidth]);
                // back right retainer hole
                translate([outerXSize-boxRightThickness-retainerWidth, innerYSize+boxFrontThickness-0.5*boxBackThickness, outerZSize-boxTopThickness-retainerLength])
                    cube([retainerWidth, 2*boxBackThickness, retainerWidth]);
            }
            // The front support for the iotsa board
            cube([outerXSize, boxFrontThickness+strutThickness, boxBottomThickness+iotsaSolderingHeight]);
            // The back support for the outsa board
            translate([0, innerYSize+boxFrontThickness-strutThickness, 0])
                cube([outerXSize, boxBackThickness+strutThickness, boxBottomThickness+iotsaSolderingHeight]);
        }
   }

    module frontHoles() {
        // Holes in the front. X and Z relative to iotsa frontleft corner, Y should be 2*frontThickness.
        translate([22-leeWay, 0, 0-leeWay]) cube([9+2*leeWay, 2*boxFrontThickness, 11+2*leeWay]);
    }
    module rightHoles() {
        // Holes on the right. Y and Z are relative to iotsa frontright cornet, X should be 2* rightThickness
        * translate([0, 16, 0]) cube([2*boxRightThickness, 9+2*leeWay, 11+2*leeWay]);
    }
    module bottomHoles() {
        // Holes in the bottom. X and Y are relative to inner box frontleft corner, Z should be 2*bottomThickness
        // 4 screw holes
        translate([3, 3+strutThickness, 0]) cylinder(2*boxBottomThickness, d=3, $fn=12);
        translate([innerXSize-3, 3+strutThickness, 0]) cylinder(2*boxBottomThickness, d=3, $fn=12);
        translate([3, innerYSize-(3+strutThickness), 0]) cylinder(2*boxBottomThickness, d=3, $fn=12);
        translate([innerXSize-3, innerYSize-(3+strutThickness), 0]) cylinder(2*boxBottomThickness, d=3, $fn=12);

        // center hole for wires
        translate([innerXSize/2, innerYSize/2, 0]) cylinder(2*boxBottomThickness, d=6, $fn=12);
    }

    union() {
        difference() {
            // The box itself
            completeBox();
            // The holes in the enclosure
            translate([0, -1.5*boxFrontThickness-leeWay, 0]) frontHoles();

            translate([iotsaBoardXSize+leeWay-0.5*boxRightThickness, 0, 0]) rightHoles();

            translate([-esp12AntennaStickout, -leeWay, -(boardThickness+iotsaSolderingHeight+1.5*boxBottomThickness+leeWay)]) bottomHoles();

        }
        % iotsaBoard();
    }
}

module lid() {
      translate([-esp12AntennaStickout-leeWay, -boxFrontThickness-leeWay, iotsaComponentHeight + leeWay])
        union() {
            // The lid itself
            cube([innerXSize, innerYSize+boxFrontThickness, boxTopThickness]);
            // The left front retainer rod
            translate([0, boxFrontThickness, -retainerLength]) cube([retainerWidth, retainerWidth, retainerLength+boxTopThickness]);
            translate([0.5*retainerWidth, 0.75*retainerWidth, -retainerLength+0.5*retainerWidth]) sphere(d=retainerWidth, $fn=12);

            // The right front retainer rod
            translate([innerXSize-retainerWidth, boxFrontThickness, -retainerLength]) cube([retainerWidth, retainerWidth, retainerLength+boxTopThickness]);
            translate([innerXSize-0.5*retainerWidth, 0.75*retainerWidth, -retainerLength+0.5*retainerWidth]) sphere(d=retainerWidth, $fn=12);

            // The left back retainer rod
            translate([0, innerYSize+boxFrontThickness-retainerWidth, -retainerLength]) cube([retainerWidth, retainerWidth, retainerLength+boxTopThickness]);
            translate([0.5*retainerWidth, innerYSize+boxFrontThickness-0.25*retainerWidth, -retainerLength+0.5*retainerWidth]) sphere(d=retainerWidth, $fn=12);

            // The right back retainer rod
            translate([innerXSize-retainerWidth, innerYSize+boxFrontThickness+-retainerWidth, -retainerLength]) cube([retainerWidth, retainerWidth, retainerLength+boxTopThickness]);
            translate([innerXSize-0.5*retainerWidth, innerYSize+boxFrontThickness-0.25*retainerWidth, -retainerLength+0.5*retainerWidth]) sphere(d=retainerWidth, $fn=12);

            // The board locking rod
            translate([41-retainerWidth, innerYSize+boxFrontThickness-retainerWidth, -iotsaComponentHeight]) cube([retainerWidth, retainerWidth, iotsaComponentHeight+boxTopThickness]);
        }
}

box();
% lid();

translate([outerXSize-(esp12AntennaStickout+boxLeftThickness+leeWay), 1.2*outerYSize, outerZSize-(boardThickness+iotsaSolderingHeight+boxBottomThickness+leeWay)]) rotate([0, 180, 0]) translate([(esp12AntennaStickout+boxLeftThickness+leeWay), 0, (boardThickness+iotsaSolderingHeight+boxBottomThickness+leeWay)]) {
    % box();
    lid();
}

//
// This is the iotsa board itself, including the important connectors and
// holes. You can define here if you have shortened the board, which will
// not only change the board itself, but also the box we are going to create around it.
//
numberOfRowsRemoved = 0;
extraMMRemoved = 0; // 0 if nothing removed, 2.2 if any rows removed.
numberOfMMRemoved = extraMMRemoved + (numberOfRowsRemoved*2.54);
iotsaBoardXSize = 63.5 - numberOfMMRemoved;   // one dimension of the unmodified board
iotsaBoardYSize = 43.5;   // the other dimension of the board

boardThickness = 1.8; // The thickness of the PCB board
regulatorAngle = 35; // 0, or higher if you've bent the regulator over backwards.

esp12AntennaStickout = 5; // How many mm the esp12 antenna sticks out of the iotsa board

module iotsaBoard() {
    module esp12() {
        union() {
            cube([24, 16, 2]); // the esp-12 board
            translate([8, 1.5, 2]) cube([15, 13, 2.5]); // the metal cap
        }
    }
    module regulator() {
        rotate([-regulatorAngle, 0, 0])
        translate([0, 0, 5])
        union() {
            translate([0, 4.5, 0]) cube([10.2, 1.3, 15]);
            translate([0, 0, 0]) cube([10.2, 4.5, 8.5]);
        }
    }
    module powerjack() {
        difference() {
            cube([9, 15, 11]);
            translate([4.5, -1, 7]) rotate([-90, 0, 0]) cylinder(14, d=6);
        }
    }
    translate([0, 0, -1.8])
    union() {
        // The board
        difference() {
            cube([iotsaBoardXSize,iotsaBoardYSize,1.8]);
            translate([2, 2, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([2, 41, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([36.5, 2, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([36.5, 41, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([60.5, 2, -0.1]) cylinder(2, d=2, center=false, $fn=12);
            translate([60.5, 41, -0.1]) cylinder(2, d=2, center=false, $fn=12);
        }
        // The components
        translate([-esp12AntennaStickout, 13.5, 1.8]) esp12();
        translate([20, 15, 1.8]) regulator();
        translate([22, -3, 1.8]) powerjack();
    }
}

//
// Box parameters. We are going to compute the size from the parameters.
//
iotsaComponentHeight = 14;  // Make sure this is high enough
iotsaSolderingHeight = 3;   // How far the soldering extends below the board.
boxThickness = 1.5;
boxBottomThickness = boxThickness;
boxFrontThickness = boxThickness;   // This is where the power connector is
boxLeftThickness = boxThickness;
boxRightThickness = boxThickness;
boxBackThickness = boxThickness;
boxTopThickness = boxThickness;

leeWay = 0.3;   // gap we want between board and box (on all sides, individually) and around connector

// Computed parameters
innerXSize = iotsaBoardXSize + esp12AntennaStickout + 2*leeWay;
innerYSize = iotsaBoardYSize + 2*leeWay;
innerZSize = boardThickness + iotsaComponentHeight + iotsaSolderingHeight + 2*leeWay;

outerXSize = innerXSize + boxLeftThickness + boxRightThickness;
outerYSize = innerYSize + boxFrontThickness + boxBackThickness;
outerZSize = innerZSize + boxBottomThickness + boxTopThickness;

strutThickness = 2;
retainerWidth = 3;
retainerLength = 6;

module box() {

    module basicBox() {
         difference() {
            cube([outerXSize, outerYSize, outerZSize]);
            translate([boxLeftThickness, boxFrontThickness, boxBottomThickness])
                cube([innerXSize, innerYSize, innerZSize+boxTopThickness+1]);
        }
    }

    module completeBox() {
     translate([-esp12AntennaStickout-boxLeftThickness-leeWay, -boxFrontThickness-leeWay, -(boardThickness+iotsaSolderingHeight+boxBottomThickness+leeWay)])
        union() {
            // The box itself, with the cutouts for the lid
            difference() {
                basicBox();
                // Front cutout
                translate([boxLeftThickness, -0.5*boxFrontThickness, outerZSize-boxTopThickness])
                    cube([innerXSize, 2*boxFrontThickness, 2*boxTopThickness]);
                // back cutout
                * translate([boxLeftThickness, innerYSize+boxFrontThickness-0.5*leeWay, outerZSize-boxTopThickness-boxBottomThickness])
                    cube([innerXSize, 0.5*boxBackThickness+leeWay, 0.5*boxTopThickness]);

                // front left retainer hole
                translate([boxLeftThickness,-0.5*boxFrontThickness, outerZSize-boxTopThickness-retainerLength])
                    cube([retainerWidth, 2*boxFrontThickness, retainerWidth]);
                // front right retainer hole
                translate([outerXSize-boxRightThickness-retainerWidth, -0.5*boxFrontThickness, outerZSize-boxTopThickness-retainerLength])
                    cube([retainerWidth, 2*boxFrontThickness, retainerWidth]);

                // back left retainer hole
                translate([boxLeftThickness,innerYSize+boxFrontThickness-0.5*boxBackThickness, outerZSize-boxTopThickness-retainerLength])
                    cube([retainerWidth, 2*boxBackThickness, retainerWidth]);
                // back right retainer hole
                translate([outerXSize-boxRightThickness-retainerWidth, innerYSize+boxFrontThickness-0.5*boxBackThickness, outerZSize-boxTopThickness-retainerLength])
                    cube([retainerWidth, 2*boxBackThickness, retainerWidth]);
            }
            // The front support for the iotsa board
            cube([outerXSize, boxFrontThickness+strutThickness, boxBottomThickness+iotsaSolderingHeight]);
            // The back support for the outsa board
            translate([0, innerYSize+boxFrontThickness-strutThickness, 0])
                cube([outerXSize, boxBackThickness+strutThickness, boxBottomThickness+iotsaSolderingHeight]);
        }
   }

    module frontHoles() {
        // Holes in the front. X and Z relative to iotsa frontleft corner, Y should be 2*frontThickness.
        translate([22-leeWay, 0, 0-leeWay]) cube([9+2*leeWay, 2*boxFrontThickness, 11+2*leeWay]);
    }
    module rightHoles() {
        // Holes on the right. Y and Z are relative to iotsa frontright cornet, X should be 2* rightThickness
        * translate([0, 16, 0]) cube([2*boxRightThickness, 9+2*leeWay, 11+2*leeWay]);
    }
    module bottomHoles() {
        // Holes in the bottom. X and Y are relative to inner box frontleft corner, Z should be 2*bottomThickness
        // 4 screw holes
        translate([3, 3+strutThickness, 0]) cylinder(2*boxBottomThickness, d=3, $fn=12);
        translate([innerXSize-3, 3+strutThickness, 0]) cylinder(2*boxBottomThickness, d=3, $fn=12);
        translate([3, innerYSize-(3+strutThickness), 0]) cylinder(2*boxBottomThickness, d=3, $fn=12);
        translate([innerXSize-3, innerYSize-(3+strutThickness), 0]) cylinder(2*boxBottomThickness, d=3, $fn=12);

        // center hole for wires
        translate([innerXSize/2, innerYSize/2, 0]) cylinder(2*boxBottomThickness, d=6, $fn=12);
    }

    union() {
        difference() {
            // The box itself
            completeBox();
            // The holes in the enclosure
            translate([0, -1.5*boxFrontThickness-leeWay, 0]) frontHoles();

            translate([iotsaBoardXSize+leeWay-0.5*boxRightThickness, 0, 0]) rightHoles();

            translate([-esp12AntennaStickout, -leeWay, -(boardThickness+iotsaSolderingHeight+1.5*boxBottomThickness+leeWay)]) bottomHoles();

        }
        % iotsaBoard();
    }
}

module lid() {
      translate([-esp12AntennaStickout-leeWay, -boxFrontThickness-leeWay, iotsaComponentHeight + leeWay])
        union() {
            // The lid itself
            cube([innerXSize, innerYSize+boxFrontThickness, boxTopThickness]);
            // The left front retainer rod
            translate([0, boxFrontThickness, -retainerLength]) cube([retainerWidth, retainerWidth, retainerLength+boxTopThickness]);
            translate([0.5*retainerWidth, 0.75*retainerWidth, -retainerLength+0.5*retainerWidth]) sphere(d=retainerWidth, $fn=12);

            // The right front retainer rod
            translate([innerXSize-retainerWidth, boxFrontThickness, -retainerLength]) cube([retainerWidth, retainerWidth, retainerLength+boxTopThickness]);
            translate([innerXSize-0.5*retainerWidth, 0.75*retainerWidth, -retainerLength+0.5*retainerWidth]) sphere(d=retainerWidth, $fn=12);

            // The left back retainer rod
            translate([0, innerYSize+boxFrontThickness-retainerWidth, -retainerLength]) cube([retainerWidth, retainerWidth, retainerLength+boxTopThickness]);
            translate([0.5*retainerWidth, innerYSize+boxFrontThickness-0.25*retainerWidth, -retainerLength+0.5*retainerWidth]) sphere(d=retainerWidth, $fn=12);

            // The right back retainer rod
            translate([innerXSize-retainerWidth, innerYSize+boxFrontThickness+-retainerWidth, -retainerLength]) cube([retainerWidth, retainerWidth, retainerLength+boxTopThickness]);
            translate([innerXSize-0.5*retainerWidth, innerYSize+boxFrontThickness-0.25*retainerWidth, -retainerLength+0.5*retainerWidth]) sphere(d=retainerWidth, $fn=12);

            // The board locking rod
            translate([31-retainerWidth, innerYSize+boxFrontThickness-retainerWidth, -iotsaComponentHeight]) cube([retainerWidth, retainerWidth, iotsaComponentHeight+boxTopThickness]);
        }
}

box();
% lid();

translate([outerXSize-(esp12AntennaStickout+boxLeftThickness+leeWay), 1.2*outerYSize, outerZSize-(boardThickness+iotsaSolderingHeight+boxBottomThickness+leeWay)]) rotate([0, 180, 0]) translate([(esp12AntennaStickout+boxLeftThickness+leeWay), 0, (boardThickness+iotsaSolderingHeight+boxBottomThickness+leeWay)]) {
    % box();
    lid();
}


fixed screw mount part

fixed screw mount part

difference()
{
  union()
  {
    // main cylinder
    difference()
    {
      cylinder(r=24.5/2, h=2.5);
      cylinder(r=16/2, h=1.5);
    }

    // 3 side blockers
    for(angle = [0, 120, 240])
      rotate([0, 0, angle])
        translate([-1/2, -1/2, 0] + [16/2-1/2, 0, 0])
          cube([1.5, 1, 2]);

    // main screw mount - bottom part
    intersection()
    {
      int_cube_size=7.2;
      rotate([0, 0, 0])
        translate([-int_cube_size/2, -int_cube_size/2, 0])
          cube([int_cube_size, int_cube_size, 2]);
      rotate([0, 0, 45])
        translate([-int_cube_size/2, -int_cube_size/2, 0])
          cube([int_cube_size, int_cube_size, 2]);
    }

    // main screw mount - top part
    {
      int_cube_size=9.5;
      translate([-int_cube_size/2, -int_cube_size/2, 0] + [0, 0, 2.5])
        cube([int_cube_size, int_cube_size, 7]);
    }
  }
  // screw hole
  screw_box_size=7+0.5;
  translate([-screw_box_size/2, -screw_box_size/2, 2.5+1])
    cube([screw_box_size, screw_box_size, 7-1]);
  cylinder(r=4/2, h=12, $fs=1);
}

difference()
{
  union()
  {
    // main cylinder
    difference()
    {
      cylinder(r=24.5/2, h=2.5);
      cylinder(r=16/2, h=1.5);
    }

    // 3 side blockers
    for(angle = [0, 120, 240])
      rotate([0, 0, angle])
        translate([-1/2, -1/2, 0] + [16/2-1/2, 0, 0])
          cube([1, 1, 2]);

    // main screw mount - bottom part
    intersection()
    {
      int_cube_size=7.2;
      rotate([0, 0, 0])
        translate([-int_cube_size/2, -int_cube_size/2, 0])
          cube([int_cube_size, int_cube_size, 2]);
      rotate([0, 0, 45])
        translate([-int_cube_size/2, -int_cube_size/2, 0])
          cube([int_cube_size, int_cube_size, 2]);
    }

    // main screw mount - top part
    {
      int_cube_size=9.5;
      translate([-int_cube_size/2, -int_cube_size/2, 0] + [0, 0, 2.5])
        cube([int_cube_size, int_cube_size, 7]);
    }
  }
  // screw hole
  translate([0, 0, 2.5+1])
    cylinder(r=(7+1.5)/2, h=7-1, $fs=1);
  cylinder(r=4/2, h=12, $fs=1);
}


Fixed issue with fan_mount.scad

Fixed issue with fan_mount.scad

hot_rad = 30/2/cos(30);
hotend_x=25;
fan_x = 15+5;

hotend_y=-5;

thickness = 10;
wall=2;
slop=.2;

fan_hole = (40-wall-wall)/2;
mount_drop = 10;
fan_z = fan_hole+wall;

//fan_mount();
bowden_fan();

%cylinder(r=hot_rad, h=20, center=true);
%translate([-23,0,0]) cylinder(r=hot_rad, h=20, center=true);

m3_cap_rad = 4;
m3_rad = 2;
m3_nut_rad = 6.01/2+.1;

facets = 6;

module fan_mount(){
    difference(){
        union(){
            //core
            cylinder(r1=hot_rad+thickness+wall, r2=hot_rad+thickness*2+wall, h=thickness+wall, $fn=facets);

            hull(){
                intersection(){
                    difference(){
                        cylinder(r1=hot_rad+thickness+wall, r2=hot_rad+thickness*2+wall, h=thickness+wall, $fn=facets);
                        translate([0,0,-.5]) cylinder(r1=hot_rad+wall, r2=hot_rad+wall+wall, h=thickness+wall+1, $fn=facets);
                    }
                    translate([50+hot_rad-6.7,50,50]) cube([100,100,100], center=true);
                }
                translate([hotend_x+fan_x-5,hotend_y,fan_z]) rotate([0,90,0]) cylinder(r=fan_hole+wall, h=5);
            }

            hull(){
                intersection(){
                    difference(){
                        cylinder(r1=hot_rad+thickness+wall, r2=hot_rad+thickness*2+wall, h=thickness+wall, $fn=facets);
                        translate([0,0,-.5]) cylinder(r1=hot_rad+wall, r2=hot_rad+wall+wall, h=thickness+wall+1, $fn=facets);
                    }
                    translate([50+hot_rad-6.7,-50,50]) cube([100,100,100], center=true);
                }
                translate([hotend_x+fan_x-5,hotend_y,fan_z]) rotate([0,90,0]) cylinder(r=fan_hole+wall, h=5);
            }

            //fan mount
            translate([hotend_x+fan_x,hotend_y,fan_z]) rotate([0,90,0]){
                hull() for(i=[0:90:359]) rotate([0,0,i]) {
                    #translate([20-wall,20-wall,-wall]) cylinder(r=wall,h=wall*2, $fn=16);
                }
            }

            //mounting lugs above fan
            translate([hotend_x+fan_x,hotend_y,fan_z]) rotate([0,90,0]){
                for(i=[-16, 16]) difference(){
                    hull(){
                        translate([-16-mount_drop,i,-fan_x+3]) cylinder(r=m3_rad+wall, h=wall*2, $fn=16);
                        translate([0,i,-fan_x+3]) cylinder(r=m3_cap_rad*2, h=wall);
                    }
                    translate([-16-mount_drop,i,-fan_x+3-.1]) cylinder(r=m3_rad, h=wall*2+1, $fn=16);
                }
            }
        }

        //center cutout
        translate([0,0,-.5]) cylinder(r1=hot_rad+wall, r2=hot_rad+wall+wall, h=thickness+wall+1, $fn=facets);

        //front cutout
        translate([-(hot_rad+thickness*2+wall),0,0]) cylinder(r=hot_rad+thickness*2+wall, h=thickness+wall*10, center=true, $fn=facets);

        //fan holes
        translate([hotend_x+fan_x,hotend_y,fan_z]) rotate([0,90,0]){
            for(i=[-16, 16]) for(j=[-16, 16]) {
                #translate([j,i,-.1]) cylinder(r=m3_rad, h=wall+.2, $fn=16);
                translate([j,i,-wall*2-.1]) cylinder(r2=m3_nut_rad, r1=m3_nut_rad+.25, h=wall*2+.2, $fn=6);
            }
        }

        //air path
        translate([0,0,-.1]) difference(){
            union(){
                translate([-wall,0,0]) cylinder(r1=hot_rad+thickness, r2=hot_rad+thickness*2-wall, h=thickness, $fn=facets);

                hull(){
                    intersection(){
                        difference(){
                            translate([-wall,0,0]) cylinder(r1=hot_rad+thickness, r2=hot_rad+thickness*2-wall, h=thickness, $fn=facets);
                            translate([0,0,-.5]) cylinder(r1=hot_rad+wall*2, r2=hot_rad+wall*3, h=thickness+wall+1, $fn=facets);
                        }
                        translate([50+hot_rad-6.7,50,50]) cube([100,100,100], center=true);
                    }
                    translate([hotend_x+fan_x-5,hotend_y,fan_z]) rotate([0,90,0]) cylinder(r=fan_hole, h=.3);
                }

                hull(){
                    intersection(){
                        difference(){
                            translate([-wall,0,0]) cylinder(r1=hot_rad+thickness, r2=hot_rad+thickness*2-wall, h=thickness, $fn=facets);
                            translate([0,0,-.5]) cylinder(r1=hot_rad+wall+wall, r2=hot_rad+wall+wall+wall, h=thickness+wall+1, $fn=facets);
                        }
                        translate([50+hot_rad-6.7,-50,50]) cube([100,100,100], center=true);
                    }
                    translate([hotend_x+fan_x-5,hotend_y,fan_z]) rotate([0,90,0]) cylinder(r=fan_hole, h=.3);
                }

                translate([hotend_x+fan_x-5,hotend_y,fan_z]) rotate([0,90,0]) cylinder(r=fan_hole, h=wall+1+5);
            }
            cylinder(r1=hot_rad+wall+wall, r2=hot_rad+wall+wall+wall, h=thickness+wall, $fn=facets);
            translate([-(hot_rad+thickness*2),0,0]) cylinder(r=hot_rad+thickness*2+wall, h=thickness+wall*10, center=true, $fn=facets);
            translate([0,-5+hotend_y/2,0])cube([100,10,wall]);
        }
    }
}

duct_angle=-5;
duct_jut = -5;

module bowden_fan(){
    duct_w = 15+slop;
    duct_h = 20+slop;
    duct_offset=38;

    mount_height = 46;

    offset = -20;
    difference(){
        union(){
            //core
            hull(){
                cylinder(r1=hot_rad+thickness+wall, r2=hot_rad+thickness*2+wall, h=thickness+wall, $fn=facets);
                translate([offset,0,0]) cylinder(r1=hot_rad+thickness+wall, r2=hot_rad+thickness*2+wall, h=thickness+wall, $fn=facets);
            }

            //connection to duct
            hull(){
                intersection(){
                    cylinder(r1=hot_rad+thickness+wall, r2=hot_rad+thickness*2+wall, h=thickness+wall, $fn=facets);
                    translate([hot_rad+wall*2,0,0]) cube([1,200,200], center=true);
                }
                translate([duct_offset,duct_jut,duct_h/2+wall]) rotate([0,0,duct_angle]) cube([1,duct_w+wall*2, duct_h+wall*2], center=true);
            }

            //the duct connector
            translate([duct_offset,duct_jut,0]) rotate([0,0,duct_angle]) duct();

            //mounting lugs
           for(i=[10,-20,-40]) difference(){
                translate([i,hot_rad+wall*2,0]) hull(){
                    translate([5,0,thickness]) rotate([90,0,0]) cylinder(r=m3_cap_rad+wall*2, h=wall, center=true);
                    translate([0,0,mount_height]) rotate([90,0,0]) cylinder(r=m3_cap_rad+wall, h=wall, center=true);
                }

                //mounting holes up top
                translate([i,hot_rad+wall*2,mount_height]) rotate([90,0,0]) cylinder(r=m3_rad+slop, h=20, center=true);
            }
        }

        //connection to duct airflow
        hull(){
            intersection(){
                translate([0,0,wall]) cylinder(r1=hot_rad+thickness, r2=hot_rad+thickness*2, h=thickness-wall, $fn=facets);
                translate([hot_rad+wall*3,0,0]) cube([1,200,200], center=true);
            }
            translate([duct_offset,duct_jut,duct_h/2+wall]) rotate([0,0,duct_angle]) cube([1.2,duct_w, duct_h], center=true);
        }

        //center cutout
        translate([0,0,-.5]) hull(){
            cylinder(r1=hot_rad+wall, r2=hot_rad+wall*3, h=thickness+wall+1, $fn=facets);
            translate([2*offset,0,0]) cylinder(r1=hot_rad+wall, r2=hot_rad+wall*3, h=thickness+wall+1, $fn=facets);
        }

        //air path
        difference(){
            //core
            translate([0,0,-.1]) hull(){
                cylinder(r1=hot_rad+thickness, r2=hot_rad+thickness*2-wall, h=thickness, $fn=facets);
                translate([offset+wall,0,0]) cylinder(r1=hot_rad+thickness, r2=hot_rad+thickness*2-wall, h=thickness, $fn=facets);
            }

            //keep the center walls in place
            translate([0,0,-.5]) hull(){
                cylinder(r1=hot_rad+wall*2, r2=hot_rad+wall*4, h=thickness+wall+1, $fn=facets);
                translate([2*offset,0,0]) cylinder(r1=hot_rad+wall*2, r2=hot_rad+wall*4, h=thickness+wall+1, $fn=facets);
            }

            //bottom on the near side
            translate([10,0,-.5]) cylinder(r1=hot_rad+wall*2, r2=hot_rad+wall*2.5, h=wall+.5, $fn=facets);
        }
    }
}

module duct(){
    duct_w = 15+slop;
    duct_h = 20+slop;
    rad = 20;

    translate([0,0,rad+wall+duct_h/2]) rotate([-90,0,0]) union(){
        intersection(){
            rotate_extrude(angle = 90, convexity = 2){
                translate([rad,0,0])
                difference(){
                    square([duct_h+wall*2, duct_w+wall*2], center=true);
                    square([duct_h, duct_w], center=true);
                }
            }
            translate([0,0,-100]) cube([200,200,200]);
        }

        translate([rad,0,0]) rotate([90,0,0]) translate([0,0,8]) difference(){
            hull(){
                translate([0,0,-8]) cube([duct_h+wall*2,duct_w+wall*2,.1], center=true);
                #translate([duct_h/2+wall/2,0,8]) cube([wall,duct_w+wall*2,.1], center=true);
            }

            //hollow center
            cube([duct_h,duct_w,16.3], center=true);

            //slot for the clip
            translate([wall+1,0,(12-16)/2]) cube([duct_h+wall*2,2,12], center=true);
        }

    }

}

error: pathspec 'bg8/extruder/better_clearance_fan_mount.scad' did not match any file(s) known to git


Changed all the screw holes to accept 2.2 mm diameter screws.

//See:
// http://edutechwiki.unige.ch/en/OpenScad_beginners_tutorial
// https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/

// Global variables.
overcut = 0.1;  // Overcut for solid difference(), to assure complete holes.
overlap = 0.1;  // Intersection for solid union() to avoid the manifold problem.

include <misc_parts.scad>;
include <boards.scad>;
include <rounded_cube.scad>;

// Box internal size.
x_size  = 115.0;
y_size  = 144.0;
z_size  =  29.0;
thick   =   2.2;
chamfer =  13.0;

// Mounting screw holes.
screw_hole1_y = 24;
screw_hole2_y = y_size - 26;
screw_diam    = 3.6;

// Position and size of push button hole.
button_x = x_size;
button_y = 64;
button_z = 16.0;
button_d = 6.2;

// Position and size of power socket hole.
psocket_x = x_size / 2;
psocket_z = 7;
psocket_d = 8.2;

// Position and size for temperature sensor grommet.
tsensor_x  = -thick - 1;
tsensor_y  = 78;
tsensor_z  = 13;
tsensor_h  = thick + 9;
tsensor_d1 = 9.0;
tsensor_d2 = 5.25;

// Positon and size for boiler cable grommet (cable is 5.5 x 3.5 mm).
bcable_x  = 19;
bcable_y  = -thick - 1;
bcable_z  = 9.5;
bcable_h  = thick + 9;
bcable_t  = 1.7; // Grommet thickness
bcable_d1 = 5.4; // Rectangular hole X
bcable_d2 = 3.4; // Rectangular hole Y
bcable_r  = 1.5; // Chamfer radius

//-------------------------------------------------------------------------
// Housing for a rubber foot.
//-------------------------------------------------------------------------
module rubber_foot(d1, d2, h) {
    $fn = 48;
    difference() {
        cylinder(r=(d1 / 2), h=h);
        translate([0, 0, -overcut]) cylinder(r=(d2 / 2), h=(h + overcut * 2));
    }
}

//-------------------------------------------------------------------------
// Housings for rubber feet (grows towards negative z axis).
//-------------------------------------------------------------------------
module box_feet(x, y, margin) {
    d1 = 11.0;
    d2 =  8.2;
    h  =  0.8;
    translate([margin,     margin,     -h]) rubber_foot(d1, d2, h + overlap);
    translate([x - margin, margin,     -h]) rubber_foot(d1, d2, h + overlap);
    translate([x - margin, y - margin, -h]) rubber_foot(d1, d2, h + overlap);
    translate([margin,     y - margin, -h]) rubber_foot(d1, d2, h + overlap);
}

//-------------------------------------------------------------------------
// Flange for screw hole.
//-------------------------------------------------------------------------
module screw_flange(r, t) {
    $fn = 60;
    screw_diameter = 2.2;
    r1 = r * 1.1;
    difference() {
        intersection() {
            cylinder(r=r1, h=t);
            union() {
                translate([r, r, 0]) cylinder(r=r, h=t);
                translate([r, 0, 0]) cube([r, r, t]);
                translate([0, r, 0]) cube([r, r, t]);}}
        translate([r1 / 2, r1 / 2, -overcut]) cylinder(r=(screw_diameter * 0.75 / 2), h=(t + overcut * 2), $fn=24);
    }
}

//-------------------------------------------------------------------------
// Add a flange to the rounded_box() module.
//-------------------------------------------------------------------------
module rounded_box_flange(x, y, z, r) {
    w = 1.5;
    difference() {
        rounded_cube(x_size, y_size, z, r);
        translate([w, w, -overcut])
            rounded_cube(x_size - w * 2, y_size - w * 2, z + overcut * 2, r);
    }
    translate([0, 0, 0]) rotate(a=0 ,  v=[0, 0, 1]) screw_flange(r, z);
    translate([x, 0, 0]) rotate(a=90,  v=[0, 0, 1]) screw_flange(r, z);
    translate([x, y, 0]) rotate(a=180, v=[0, 0, 1]) screw_flange(r, z);
    translate([0, y, 0]) rotate(a=270, v=[0, 0, 1]) screw_flange(r, z);
}

//-------------------------------------------------------------------------
// Round cable grommet.
//-------------------------------------------------------------------------
module cable_grommet(h, d1, d2) {
    $fn = 32;
    cut_width = 3;
    difference() {
        union() {
            cylinder(r=(d1 / 2), h=h);
            translate([0, 0, h - 2.4]) cylinder(r=((d1 + 1.0) / 2), h=2.4);
        }
        translate([0, 0, -overcut]) cylinder(r=(d2 / 2), h=(h + 2 * overcut));
        translate([(d2 / 4), -(d1 / 2), h - (cut_width + 2.5)])
            cube([(d1 / 2), d1, cut_width]);
    }
}

//-------------------------------------------------------------------------
// Rectangular (with chamfer) cable grommet.
// h = height, x, y = hole inner size, r = chamfer radius, t = thickness
//-------------------------------------------------------------------------
module cable_grommet_rect(h, x, y, r, t) {
    cut_width = 3;
    difference() {
        union() {
            translate([-x / 2, -y / 2, 0]) rounded_cube_border(x, y, h, r, t);
            translate([-x / 2, -y / 2, h - 2.4]) rounded_cube_border(x, y, 2.4, r, t + 0.5);
        }
        translate([-(x / 2) - t - overcut, 0, h - (cut_width + 2.5)])
            cube([x + (t + overcut) * 2, y / 2 + t + overcut, cut_width]);
    }
}

//-------------------------------------------------------------------------
// Drill a screw hole with cuts for horizontal and vertical wall mount.
// Screw body diameter is d, head diameter will be d * 2.
//-------------------------------------------------------------------------
module screw_hole(d, depth) {
    $fn = 32;
    hole_depth = depth + overcut * 2;
    hole_bottom = -(depth + overcut);
    cut_length = d * 2;
    union() {
        translate([0, 0, hole_bottom])          cylinder(r=d, h=hole_depth);
        translate([-(d / 2), 0, hole_bottom])   cube([d, cut_length, hole_depth]);
        translate([0, -(d / 2), hole_bottom])   cube([cut_length, d, hole_depth]);
        translate([0, cut_length, hole_bottom]) cylinder(r=(d / 2), h=hole_depth);
        translate([cut_length, 0, hole_bottom]) cylinder(r=(d / 2), h=hole_depth);
    }
}

//-------------------------------------------------------------------------
// Build a cap to place over a screw hole.
// Screw body diameter = d
// Screw head diameter = d * 2
// Screw head height   = d * 0.6
//-------------------------------------------------------------------------
module screw_hole_cap(d, thick) {
    $fn = 36;
    r2 = 1.4142;
    pin_radius = thick * 1.3;
    pin_heigh = (d * 0.6) + (overlap * 2);
    pin_base = -overlap;
    offset = (((pin_radius * r2) - pin_radius) / r2) + ((pin_radius * 2) / r2) + (d / r2);
    size1 = (offset + overlap) * 2;
    size2 = size1 + d * 2;
    translate([-(size1 / 2), -(size1 / 2), 0]) {
        union() {
            translate([0, 0, d * 0.6]) rounded_cube(size1, size2, thick, pin_radius);
            translate([0, 0, d * 0.6]) rounded_cube(size2, size1, thick, pin_radius);
            translate([pin_radius, pin_radius, pin_base])                 cylinder(r=pin_radius, h=pin_heigh);
            translate([size2 - pin_radius, pin_radius, pin_base])         cylinder(r=pin_radius, h=pin_heigh);
            translate([size2 - pin_radius, size1 - pin_radius, pin_base]) cylinder(r=pin_radius, h=pin_heigh);
            translate([size1 - pin_radius, size2 - pin_radius, pin_base]) cylinder(r=pin_radius, h=pin_heigh);
            translate([pin_radius, size2 - pin_radius, pin_base])         cylinder(r=pin_radius, h=pin_heigh);
        }
    }
}

//-------------------------------------------------------------------------
// Make a box with the requested internal size and rounded corners.
// The origin is the lower-left internal corner.
//-------------------------------------------------------------------------
module rounded_box(x_size, y_size, z_size, chamfer, thick) {
    cover_thick = 2;
    union() {
        translate([-overlap, -overlap, -thick])
            rounded_cube(x_size + overlap * 2, y_size + overlap * 2, thick, chamfer + overlap);
        translate([0, 0, -thick])
            rounded_cube_border(x_size, y_size, z_size + thick, chamfer, thick);
        translate([-overlap, -overlap, z_size - cover_thick - thick])
            rounded_box_flange(x_size + overlap * 2, y_size + overlap * 2, thick, chamfer + overlap);
        translate([0, 0, -thick])
            box_feet(x_size, y_size, 10);
        // Draw the box cover, for dimension testing.
        //translate([0, 0, z_size - cover_thick])
        //    %rounded_cube(x_size, y_size, cover_thick, chamfer);
    }
}

//-------------------------------------------------------------------------
// Make a box with rounded corners, drill all the required holes.
//-------------------------------------------------------------------------
module rounded_box_holes(x_size, y_size, z_size, chamfer, thick) {

    holes_diam = 3.5;

    // Boiler cable grommet.
    translate([bcable_x, bcable_y, bcable_z])
        rotate(a=180, v=[0, 1, 0])
            rotate(a=270, v=[1, 0, 0])
                cable_grommet_rect(bcable_h, bcable_d1, bcable_d2, bcable_r, bcable_t);

    // Temperature sensor cable grommet.
    translate([tsensor_x, tsensor_y, tsensor_z])
        rotate(a=90, v=[1, 0, 0])
            rotate(a=90, v=[0, 1, 0])
                cable_grommet(tsensor_h, tsensor_d1, tsensor_d2);

    difference() {
        rounded_box(x_size, y_size, z_size, chamfer, thick);

        // Bottom venting holes.
        translate([x_size / 2, 0, z_size / 2])
            rotate(a=90, v=[1, 0, 0]) vent_holes(12, 3, holes_diam, thick);

        // Top venting holes.
        translate([x_size / 2, y_size + thick, z_size / 2])
            rotate(a=90, v=[1, 0, 0]) vent_holes(11, 3, holes_diam, thick);

        // Backplane venting holes.
        translate([83, 88, -thick]) vent_holes(8, 6, holes_diam, thick);
        translate([25, 38, -thick]) vent_holes(5, 4, holes_diam, thick);

        // Mounting screw holes.
        translate([x_size / 2, screw_hole1_y, 0]) rotate(a=90, v=[0, 0, 1]) screw_hole(screw_diam, thick);
        translate([x_size / 2, screw_hole2_y, 0]) rotate(a=90, v=[0, 0, 1]) screw_hole(screw_diam, thick);

        // Temperature sensor hole.
        translate([-(thick + overcut), tsensor_y, tsensor_z])
            rotate(a=90, v=[0, 1, 0]) cylinder(r=(tsensor_d2 / 2), h=(thick + overcut * 2), $fn=24);

        // Bush-button hole.
        translate([button_x - overcut, button_y, button_z])
            rotate(a=90, v=[0, 1, 0]) cylinder(r=(button_d / 2), h=(thick + overcut * 2), $fn=24);

        // Power socket hole.
        translate([psocket_x, overcut, psocket_z])
            rotate(a=90, v=[1, 0, 0]) cylinder(r=(psocket_d / 2), h=(thick + overcut * 2), $fn=24);

        // Boiler cable hole.
        translate([bcable_x, bcable_y - overcut, bcable_z])
            rotate(a=270, v=[1, 0, 0]) rounded_cube_centered(bcable_d1, bcable_d2, bcable_h + overcut * 2, bcable_r);

    }

    // Reinforce for power socket hole.
    difference() {
        translate([psocket_x, 0, psocket_z]) rotate(a=90, v=[1, 0, 0]) cylinder(r=(psocket_d / 2) + 2.5, h=thick);
        translate([psocket_x, overcut, psocket_z])
            rotate(a=90, v=[1, 0, 0]) cylinder(r=(psocket_d / 2), h=(thick + overcut * 2), $fn=24);
    }

    // Reinforce for boiler cable hole.
    difference() {
        translate([bcable_x, 0, bcable_z])
            rotate(a=90, v=[1, 0, 0]) rounded_cube_centered(bcable_d1 + 5.5, bcable_d2 + 5.5, thick, 3);
        translate([bcable_x, overcut, bcable_z])
            rotate(a=90, v=[1, 0, 0]) rounded_cube_centered(bcable_d1, bcable_d2, (thick + overcut * 2), bcable_r);
    }

    // Mounting screws holes.
    translate([x_size / 2, screw_hole1_y, 0]) rotate(a=90, v=[0, 0, 1]) #screw_hole_cap(screw_diam, 1.7);
    translate([x_size / 2, screw_hole2_y, 0]) rotate(a=90, v=[0, 0, 1]) #screw_hole_cap(screw_diam, 1.7);
}

//-------------------------------------------------------------------------
// Drill a grid of rows x columns vent holes. Each hole has the
// specified diameter and depth, the grid is centered into the origin.
//-------------------------------------------------------------------------
module vent_holes(x, y, diameter, depth) {
    $fn = 6; // 18 = rounded holes, 6 = hexagonal
    step = diameter * 2;
    radius = diameter / 1.8;  // Divide by 2.0 if rounded holes, 1.8 if hexagonal.
    offset_x = (step * (x - 1)) / 2;
    offset_y = (step * (y - 1)) / 2;
    for (i = [1:x]) {
        for (j = [1:y]) {
            translate([(i - 1) * step - offset_x, (j -1) * step - offset_y, -overcut])
              cylinder(r=radius, h=(depth + overcut * 2));
        }
    }
    for (i = [1:x-1]) {
        for (j = [1:y-1]) {
            translate([(i - 1) * step - offset_x + step / 2, (j -1) * step - offset_y + step / 2, -overcut])
                cylinder(r=radius, h=(depth + overcut * 2));
        }
    }
}

//-------------------------------------------------------------------------
// Screw stub: d1 is the outer diameter, d2 is the screw diameter.
// The stub height must be grather than the depth of the hole.
//-------------------------------------------------------------------------
module stub(d1, height, d2, hole_depth) {
    $fn = 36;
    // The hole for a self-tapping screw is narrower than the screw.
    hole_diameter = d2 * 0.75;
    difference() {
        translate([0, 0, -overlap]) {
            union() {
                cylinder(r=(d1 / 2), h=(height + overlap));
                cylinder(r1=(d1 * 0.7), r2=(d1 / 2), h=(4 + overlap));
            }
        }
        translate([0, 0, height - hole_depth])
            cylinder(r=(hole_diameter / 2), h=(hole_depth + overcut));
    }
}

//-------------------------------------------------------------------------
// Screw stubs for relay board (SainSmart like manufacturer).
//-------------------------------------------------------------------------
module stubs_2relays_sainsmart(height) {
    diameter = 7;
    screw_diameter = 2.2;
    hole_depth = 6;
    // Offset of first (lower left) hole from edge.
    translate([2.75, 2.75, 0]) {
        translate([ 0,      0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([33.5,    0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([0,    45.5, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([33.5, 45.5, 0]) stub(diameter, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Screw stubs for relay board (Keyes manufacturer).
//-------------------------------------------------------------------------
module stubs_2relays_keyes(height) {
    diameter = 7;
    screw_diameter = 2.2;
    hole_depth = 6;
    // Offset of first (lower left) hole from edge.
    translate([3.5, 9, 0]) {
        translate([ 0,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([38,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([0,  40, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([38, 40, 0]) stub(diameter, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Screw stubs for PCD8544 LCD (Nokia 5110/3310), blue PCB model.
//-------------------------------------------------------------------------
module stubs_pcd8544_blue(height) {
    diameter = 6.5;
    screw_diameter = 2.2;
    hole_depth = 6;
    // Offset of first (lower left) hole from edge.
    translate([4.25, 2.25, 0]) {
        translate([ 0,    0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([34.5,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([0,    41, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([34.5, 41, 0]) stub(diameter, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Screw stubs for PCD8544 LCD (Nokia 5110/3310), red PCB model.
//-------------------------------------------------------------------------
module stubs_pcd8544_red(height) {
    diameter = 6.0;
    screw_diameter = 2.2;
    hole_depth = 6;
    // Offset of first (lower left) hole from edge.
    translate([1.75, 2.0, 0]) {
        translate([ 0,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([40,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([ 0, 39, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([40, 39, 0]) stub(diameter, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Screw stubs for Raspberry Pi Model B v.2.
//-------------------------------------------------------------------------
module stubs_raspberrypi_model_b_v2(height) {
    screw_diameter = 2.2;
    hole_depth = 6;
    translate([38, 25.5, 0]) {
        translate([    0,    0, 0]) stub(6.5, height, screw_diameter, hole_depth);
        translate([-25.5, 54.5, 0]) stub(6.5, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Main procedure.
//-------------------------------------------------------------------------
translate([-(x_size / 2), -(y_size/2), 0]) {
    rounded_box_holes(x_size, y_size, z_size, chamfer, thick);
    translate([ 5, 12,  0.0]) stubs_2relays_sainsmart(5.0);
    translate([ 8, 90,  0.0]) stubs_pcd8544_red(20.5); // Non diminuire Y sennò tocca il coprivite!
    translate([55, 37,  0.0]) stubs_raspberrypi_model_b_v2(5.0);
    //translate([55, 37 , 5.0]) board_raspberrypi_model_b_v2();
    //translate([ 8, 90, 20.5]) board_pcd8544_red();
    //translate([ 5, 12,  5.0]) board_2relays_sainsmart();
    //translate([button_x, button_y, button_z]) rotate(a=90, v=[0, 1, 0]) push_button();
    //translate([psocket_x, -thick, psocket_z]) rotate(a=90, v=[1, 0, 0]) coax_power_jack();
}

include <RigacciOrg.scad>;
translate([-x_size / 2 - thick + overlap, -29, 13])
    rotate(a=270, v=[0,0,1]) rotate(a=90, v=[1,0,0]) {
        //#cube([55, 12.54, 0.5], center=true);
        RigacciOrg(0.5);
    }

include <ccbysa.scad>;
translate([-x_size / 2 - thick + overlap, 34, 13])
    rotate(a=270, v=[0,0,1]) rotate(a=90, v=[1,0,0]) {
        //#cube([35.60, 12.54, 0.5], center=true);
        ccbysa(0.5);
    }

//See:
// http://edutechwiki.unige.ch/en/OpenScad_beginners_tutorial
// https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/

// Global variables.
overcut = 0.1;  // Overcut for solid difference(), to assure complete holes.
overlap = 0.1;  // Intersection for solid union() to avoid the manifold problem.

include <misc_parts.scad>;
include <boards.scad>;
include <rounded_cube.scad>;

// Box internal size.
x_size  = 115.0;
y_size  = 144.0;
z_size  =  29.0;
thick   =   2.2;
chamfer =  13.0;

// Mounting screw holes.
screw_hole1_y = 24;
screw_hole2_y = y_size - 26;
screw_diam    = 3.6;

// Position and size of push button hole.
button_x = x_size;
button_y = 64;
button_z = 16.0;
button_d = 6.2;

// Position and size of power socket hole.
psocket_x = x_size / 2;
psocket_z = 7;
psocket_d = 8.2;

// Position and size for temperature sensor grommet.
tsensor_x  = -thick - 1;
tsensor_y  = 78;
tsensor_z  = 13;
tsensor_h  = thick + 9;
tsensor_d1 = 9.0;
tsensor_d2 = 5.25;

// Positon and size for boiler cable grommet (cable is 5.5 x 3.5 mm).
bcable_x  = 19;
bcable_y  = -thick - 1;
bcable_z  = 9.5;
bcable_h  = thick + 9;
bcable_t  = 1.7; // Grommet thickness
bcable_d1 = 5.4; // Rectangular hole X
bcable_d2 = 3.4; // Rectangular hole Y
bcable_r  = 1.5; // Chamfer radius

//-------------------------------------------------------------------------
// Housing for a rubber foot.
//-------------------------------------------------------------------------
module rubber_foot(d1, d2, h) {
    $fn = 48;
    difference() {
        cylinder(r=(d1 / 2), h=h);
        translate([0, 0, -overcut]) cylinder(r=(d2 / 2), h=(h + overcut * 2));
    }
}

//-------------------------------------------------------------------------
// Housings for rubber feet (grows towards negative z axis).
//-------------------------------------------------------------------------
module box_feet(x, y, margin) {
    d1 = 11.0;
    d2 =  8.2;
    h  =  0.8;
    translate([margin,     margin,     -h]) rubber_foot(d1, d2, h + overlap);
    translate([x - margin, margin,     -h]) rubber_foot(d1, d2, h + overlap);
    translate([x - margin, y - margin, -h]) rubber_foot(d1, d2, h + overlap);
    translate([margin,     y - margin, -h]) rubber_foot(d1, d2, h + overlap);
}

//-------------------------------------------------------------------------
// Flange for screw hole.
//-------------------------------------------------------------------------
module screw_flange(r, t) {
    $fn = 60;
    r1 = r * 1.1;
    difference() {
        intersection() {
            cylinder(r=r1, h=t);
            union() {
                translate([r, r, 0]) cylinder(r=r, h=t);
                translate([r, 0, 0]) cube([r, r, t]);
                translate([0, r, 0]) cube([r, r, t]);}}
        translate([r1 / 2, r1 / 2, -overcut]) cylinder(r=1, h=(t + overcut * 2), $fn=24);
    }
}

//-------------------------------------------------------------------------
// Add a flange to the rounded_box() module.
//-------------------------------------------------------------------------
module rounded_box_flange(x, y, z, r) {
    w = 1.5;
    difference() {
        rounded_cube(x_size, y_size, z, r);
        translate([w, w, -overcut])
            rounded_cube(x_size - w * 2, y_size - w * 2, z + overcut * 2, r);
    }
    translate([0, 0, 0]) rotate(a=0 ,  v=[0, 0, 1]) screw_flange(r, z);
    translate([x, 0, 0]) rotate(a=90,  v=[0, 0, 1]) screw_flange(r, z);
    translate([x, y, 0]) rotate(a=180, v=[0, 0, 1]) screw_flange(r, z);
    translate([0, y, 0]) rotate(a=270, v=[0, 0, 1]) screw_flange(r, z);
}

//-------------------------------------------------------------------------
// Round cable grommet.
//-------------------------------------------------------------------------
module cable_grommet(h, d1, d2) {
    $fn = 32;
    cut_width = 3;
    difference() {
        union() {
            cylinder(r=(d1 / 2), h=h);
            translate([0, 0, h - 2.4]) cylinder(r=((d1 + 1.0) / 2), h=2.4);
        }
        translate([0, 0, -overcut]) cylinder(r=(d2 / 2), h=(h + 2 * overcut));
        translate([(d2 / 4), -(d1 / 2), h - (cut_width + 2.5)])
            cube([(d1 / 2), d1, cut_width]);
    }
}

//-------------------------------------------------------------------------
// Rectangular (with chamfer) cable grommet.
// h = height, x, y = hole inner size, r = chamfer radius, t = thickness
//-------------------------------------------------------------------------
module cable_grommet_rect(h, x, y, r, t) {
    cut_width = 3;
    difference() {
        union() {
            translate([-x / 2, -y / 2, 0]) rounded_cube_border(x, y, h, r, t);
            translate([-x / 2, -y / 2, h - 2.4]) rounded_cube_border(x, y, 2.4, r, t + 0.5);
        }
        translate([-(x / 2) - t - overcut, 0, h - (cut_width + 2.5)])
            cube([x + (t + overcut) * 2, y / 2 + t + overcut, cut_width]);
    }
}

//-------------------------------------------------------------------------
// Drill a screw hole with cuts for horizontal and vertical wall mount.
// Screw body diameter is d, head diameter will be d * 2.
//-------------------------------------------------------------------------
module screw_hole(d, depth) {
    $fn = 32;
    hole_depth = depth + overcut * 2;
    hole_bottom = -(depth + overcut);
    cut_length = d * 2;
    union() {
        translate([0, 0, hole_bottom])          cylinder(r=d, h=hole_depth);
        translate([-(d / 2), 0, hole_bottom])   cube([d, cut_length, hole_depth]);
        translate([0, -(d / 2), hole_bottom])   cube([cut_length, d, hole_depth]);
        translate([0, cut_length, hole_bottom]) cylinder(r=(d / 2), h=hole_depth);
        translate([cut_length, 0, hole_bottom]) cylinder(r=(d / 2), h=hole_depth);
    }
}

//-------------------------------------------------------------------------
// Build a cap to place over a screw hole.
// Screw body diameter = d
// Screw head diameter = d * 2
// Screw head height   = d * 0.6
//-------------------------------------------------------------------------
module screw_hole_cap(d, thick) {
    $fn = 36;
    r2 = 1.4142;
    pin_radius = thick * 1.3;
    pin_heigh = (d * 0.6) + (overlap * 2);
    pin_base = -overlap;
    offset = (((pin_radius * r2) - pin_radius) / r2) + ((pin_radius * 2) / r2) + (d / r2);
    size1 = (offset + overlap) * 2;
    size2 = size1 + d * 2;
    translate([-(size1 / 2), -(size1 / 2), 0]) {
        union() {
            translate([0, 0, d * 0.6]) rounded_cube(size1, size2, thick, pin_radius);
            translate([0, 0, d * 0.6]) rounded_cube(size2, size1, thick, pin_radius);
            translate([pin_radius, pin_radius, pin_base])                 cylinder(r=pin_radius, h=pin_heigh);
            translate([size2 - pin_radius, pin_radius, pin_base])         cylinder(r=pin_radius, h=pin_heigh);
            translate([size2 - pin_radius, size1 - pin_radius, pin_base]) cylinder(r=pin_radius, h=pin_heigh);
            translate([size1 - pin_radius, size2 - pin_radius, pin_base]) cylinder(r=pin_radius, h=pin_heigh);
            translate([pin_radius, size2 - pin_radius, pin_base])         cylinder(r=pin_radius, h=pin_heigh);
        }
    }
}

//-------------------------------------------------------------------------
// Make a box with the requested internal size and rounded corners.
// The origin is the lower-left internal corner.
//-------------------------------------------------------------------------
module rounded_box(x_size, y_size, z_size, chamfer, thick) {
    cover_thick = 2;
    union() {
        translate([-overlap, -overlap, -thick])
            rounded_cube(x_size + overlap * 2, y_size + overlap * 2, thick, chamfer + overlap);
        translate([0, 0, -thick])
            rounded_cube_border(x_size, y_size, z_size + thick, chamfer, thick);
        translate([-overlap, -overlap, z_size - cover_thick - thick])
            rounded_box_flange(x_size + overlap * 2, y_size + overlap * 2, thick, chamfer + overlap);
        translate([0, 0, -thick])
            box_feet(x_size, y_size, 10);
        // Draw the box cover, for dimension testing.
        //translate([0, 0, z_size - cover_thick])
        //    %rounded_cube(x_size, y_size, cover_thick, chamfer);
    }
}

//-------------------------------------------------------------------------
// Make a box with rounded corners, drill all the required holes.
//-------------------------------------------------------------------------
module rounded_box_holes(x_size, y_size, z_size, chamfer, thick) {

    holes_diam = 3.5;

    // Boiler cable grommet.
    translate([bcable_x, bcable_y, bcable_z])
        rotate(a=180, v=[0, 1, 0])
            rotate(a=270, v=[1, 0, 0])
                cable_grommet_rect(bcable_h, bcable_d1, bcable_d2, bcable_r, bcable_t);

    // Temperature sensor cable grommet.
    translate([tsensor_x, tsensor_y, tsensor_z])
        rotate(a=90, v=[1, 0, 0])
            rotate(a=90, v=[0, 1, 0])
                cable_grommet(tsensor_h, tsensor_d1, tsensor_d2);

    difference() {
        rounded_box(x_size, y_size, z_size, chamfer, thick);

        // Bottom venting holes.
        translate([x_size / 2, 0, z_size / 2])
            rotate(a=90, v=[1, 0, 0]) vent_holes(12, 3, holes_diam, thick);

        // Top venting holes.
        translate([x_size / 2, y_size + thick, z_size / 2])
            rotate(a=90, v=[1, 0, 0]) vent_holes(11, 3, holes_diam, thick);

        // Backplane venting holes.
        translate([83, 88, -thick]) vent_holes(8, 6, holes_diam, thick);
        translate([25, 38, -thick]) vent_holes(5, 4, holes_diam, thick);

        // Mounting screw holes.
        translate([x_size / 2, screw_hole1_y, 0]) rotate(a=90, v=[0, 0, 1]) screw_hole(screw_diam, thick);
        translate([x_size / 2, screw_hole2_y, 0]) rotate(a=90, v=[0, 0, 1]) screw_hole(screw_diam, thick);

        // Temperature sensor hole.
        translate([-(thick + overcut), tsensor_y, tsensor_z])
            rotate(a=90, v=[0, 1, 0]) cylinder(r=(tsensor_d2 / 2), h=(thick + overcut * 2), $fn=24);

        // Bush-button hole.
        translate([button_x - overcut, button_y, button_z])
            rotate(a=90, v=[0, 1, 0]) cylinder(r=(button_d / 2), h=(thick + overcut * 2), $fn=24);

        // Power socket hole.
        translate([psocket_x, overcut, psocket_z])
            rotate(a=90, v=[1, 0, 0]) cylinder(r=(psocket_d / 2), h=(thick + overcut * 2), $fn=24);

        // Boiler cable hole.
        translate([bcable_x, bcable_y - overcut, bcable_z])
            rotate(a=270, v=[1, 0, 0]) rounded_cube_centered(bcable_d1, bcable_d2, bcable_h + overcut * 2, bcable_r);

    }

    // Reinforce for power socket hole.
    difference() {
        translate([psocket_x, 0, psocket_z]) rotate(a=90, v=[1, 0, 0]) cylinder(r=(psocket_d / 2) + 2.5, h=thick);
        translate([psocket_x, overcut, psocket_z])
            rotate(a=90, v=[1, 0, 0]) cylinder(r=(psocket_d / 2), h=(thick + overcut * 2), $fn=24);
    }

    // Reinforce for boiler cable hole.
    difference() {
        translate([bcable_x, 0, bcable_z])
            rotate(a=90, v=[1, 0, 0]) rounded_cube_centered(bcable_d1 + 5.5, bcable_d2 + 5.5, thick, 3);
        translate([bcable_x, overcut, bcable_z])
            rotate(a=90, v=[1, 0, 0]) rounded_cube_centered(bcable_d1, bcable_d2, (thick + overcut * 2), bcable_r);
    }

    // Mounting screws holes.
    translate([x_size / 2, screw_hole1_y, 0]) rotate(a=90, v=[0, 0, 1]) #screw_hole_cap(screw_diam, 1.7);
    translate([x_size / 2, screw_hole2_y, 0]) rotate(a=90, v=[0, 0, 1]) #screw_hole_cap(screw_diam, 1.7);
}

//-------------------------------------------------------------------------
// Drill a grid of rows x columns vent holes. Each hole has the
// specified diameter and depth, the grid is centered into the origin.
//-------------------------------------------------------------------------
module vent_holes(x, y, diameter, depth) {
    $fn = 6; // 18 = rounded holes, 6 = hexagonal
    step = diameter * 2;
    radius = diameter / 1.8;  // Divide by 2.0 if rounded holes, 1.8 if hexagonal.
    offset_x = (step * (x - 1)) / 2;
    offset_y = (step * (y - 1)) / 2;
    for (i = [1:x]) {
        for (j = [1:y]) {
            translate([(i - 1) * step - offset_x, (j -1) * step - offset_y, -overcut])
              cylinder(r=radius, h=(depth + overcut * 2));
        }
    }
    for (i = [1:x-1]) {
        for (j = [1:y-1]) {
            translate([(i - 1) * step - offset_x + step / 2, (j -1) * step - offset_y + step / 2, -overcut])
                cylinder(r=radius, h=(depth + overcut * 2));
        }
    }
}

//-------------------------------------------------------------------------
// Screw stub: d1 is the outer diameter, d2 is the screw diameter.
// The stub height must be grather than the depth of the hole.
//-------------------------------------------------------------------------
module stub(d1, height, d2, hole_depth) {
    $fn = 36;
    // The hole for a self-tapping screw is narrower than the screw.
    hole_diameter = d2 * 0.75;
    difference() {
        translate([0, 0, -overlap]) {
            union() {
                cylinder(r=(d1 / 2), h=(height + overlap));
                cylinder(r1=(d1 * 0.7), r2=(d1 / 2), h=(4 + overlap));
            }
        }
        translate([0, 0, height - hole_depth])
            cylinder(r=(hole_diameter / 2), h=(hole_depth + overcut));
    }
}

//-------------------------------------------------------------------------
// Screw stubs for relay board (SainSmart like manufacturer).
//-------------------------------------------------------------------------
module stubs_2relays_sainsmart(height) {
    diameter = 7;
    screw_diameter = 2.5;
    hole_depth = 6;
    // Offset of first (lower left) hole from edge.
    translate([2.75, 2.75, 0]) {
        translate([ 0,      0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([33.5,    0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([0,    45.5, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([33.5, 45.5, 0]) stub(diameter, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Screw stubs for relay board (Keyes manufacturer).
//-------------------------------------------------------------------------
module stubs_2relays_keyes(height) {
    diameter = 7;
    screw_diameter = 3.5;
    hole_depth = 6;
    // Offset of first (lower left) hole from edge.
    translate([3.5, 9, 0]) {
        translate([ 0,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([38,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([0,  40, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([38, 40, 0]) stub(diameter, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Screw stubs for PCD8544 LCD (Nokia 5110/3310), blue PCB model.
//-------------------------------------------------------------------------
module stubs_pcd8544_blue(height) {
    diameter = 6.5;
    screw_diameter = 2.5;
    hole_depth = 6;
    // Offset of first (lower left) hole from edge.
    translate([4.25, 2.25, 0]) {
        translate([ 0,    0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([34.5,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([0,    41, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([34.5, 41, 0]) stub(diameter, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Screw stubs for PCD8544 LCD (Nokia 5110/3310), red PCB model.
//-------------------------------------------------------------------------
module stubs_pcd8544_red(height) {
    diameter = 6.0;
    screw_diameter = 2.0;
    hole_depth = 6;
    // Offset of first (lower left) hole from edge.
    translate([1.75, 2.0, 0]) {
        translate([ 0,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([40,  0, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([ 0, 39, 0]) stub(diameter, height, screw_diameter, hole_depth);
        translate([40, 39, 0]) stub(diameter, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Screw stubs for Raspberry Pi Model B v.2.
//-------------------------------------------------------------------------
module stubs_raspberrypi_model_b_v2(height) {
    screw_diameter = 2.5;
    hole_depth = 6;
    translate([38, 25.5, 0]) {
        translate([    0,    0, 0]) stub(6.5, height, screw_diameter, hole_depth);
        translate([-25.5, 54.5, 0]) stub(6.5, height, screw_diameter, hole_depth);
    }
}

//-------------------------------------------------------------------------
// Main procedure.
//-------------------------------------------------------------------------
translate([-(x_size / 2), -(y_size/2), 0]) {
    rounded_box_holes(x_size, y_size, z_size, chamfer, thick);
    translate([ 5, 12,  0.0]) stubs_2relays_sainsmart(5.0);
    translate([ 8, 90,  0.0]) stubs_pcd8544_red(20.5); // Non diminuire Y sennò tocca il coprivite!
    translate([55, 37,  0.0]) stubs_raspberrypi_model_b_v2(5.0);
    //translate([55, 37 , 5.0]) board_raspberrypi_model_b_v2();
    //translate([ 8, 90, 20.5]) board_pcd8544_red();
    //translate([ 5, 12,  5.0]) board_2relays_sainsmart();
    //translate([button_x, button_y, button_z]) rotate(a=90, v=[0, 1, 0]) push_button();
    //translate([psocket_x, -thick, psocket_z]) rotate(a=90, v=[1, 0, 0]) coax_power_jack();
}

include <RigacciOrg.scad>;
translate([-x_size / 2 - thick + overlap, -29, 13])
    rotate(a=270, v=[0,0,1]) rotate(a=90, v=[1,0,0]) {
        //#cube([55, 12.54, 0.5], center=true);
        RigacciOrg(0.5);
    }

include <ccbysa.scad>;
translate([-x_size / 2 - thick + overlap, 34, 13])
    rotate(a=270, v=[0,0,1]) rotate(a=90, v=[1,0,0]) {
        //#cube([35.60, 12.54, 0.5], center=true);
        ccbysa(0.5);
    }


Add demo for the hexagonBox shape and the repeat operator

/**
 * Samples using the camelSCAD library.
 *
 * A parametric honeycombed style box
 *
 * @author jsconan
 * @license CC0-1.0
 */

// As we need to use some shapes, use the right entry point of the library
use <../shapes.scad>

/**
 * Renders a honeycomb at the origin.
 *
 * @param Vector|Number size - The outer dimensions of the honeycomb
 * @param Number thickness - The thickness of the box walls (default 1). Cannot be greater than 10% of the lowest dimension.
 */
module honeycomb(size, thickness) {
    // Adjust the values to get usable size and thickness
    size = vector3D(size);
    width = min(size[0], size[1]);
    thickness = min(numberOr(thickness, 1), width / 10);
    adjust = max(size[0], size[1]) - width;
    innerWidth = width - thickness * 2;

    difference() {
        // This is the outside of the honeycomb
        hexagonBox(l=width, w=width, h=size[2], adjust=adjust);

        // This is the inside of the honeycomb
        translate([0, 0, thickness]) {
            hexagonBox(l=innerWidth, w=innerWidth, h=size[2], adjust=adjust);
        }
    }

}

// We will render the object using the specifications of this mode
renderMode = "prod";

// Defines the dimensions of the honeycomb
length = 60;
width = 50;
height = 30;
thickness = 2;

// intervals between honeycombs
adjustX = (max(length, width) - min(length, width)) / 4;
spaceX = cos(60) * length / 2 + thickness - adjustX;
spaceY = cos(30) * width - thickness;

// The number of honeycombs to render on both X and Y axis
nbX = 4;
nbY = 4;

// Sets the minimum facet angle and size using the defined render mode.
$fa = facetAngle(renderMode);
$fs = facetSize(renderMode);

// The honeycombed box is drawed by rendering several honeycombs using the repeat2D operator
repeat2D(countX=nbX, countY=nbY, intervalX=[length - spaceX, spaceY / 2, 0], intervalY=[0, spaceY, 0]) {
    honeycomb(size = [length, width, height], thickness=thickness);
}

error: pathspec 'samples/honeycombed.scad' did not match any file(s) known to git


fixed hole mounts to be located at the center

use <controller.scad>
use <screw.scad>

module side_bruse_impl()
{
  for(sig = [-1, +1])
    for(i = [1, 2, 3])
      translate([0, i*18, -1])
        rotate([sig*20, 0, 0])
          cube([3, 2, 26]);
}

module junction_box_impl()
{
  wall = 2;
  extra_depth = 5;
  int_size = [70, 70, 24+3+extra_depth];

  difference()
  {
    // main box
    cube(int_size + [2,2,1]*wall);
    translate([1,1,1]*wall)
      cube(int_size);
    // place for cables
    cable_cut_in = [20, 10, wall];
    translate([(int_size[0]+2*wall-cable_cut_in[0])/2, wall, 0])
      cube(cable_cut_in);
  }

  // screw holes
  dist_from_center = 59/2;
  for(dx = [-1, +1])
  {
    translate([(int_size[0]+2*wall)/2+dx*dist_from_center,
               wall+int_size[1]/2,
               wall])
    {
      difference()
      {
        // main screw corridor
        union()
        {
          cylinder(r=10/2, h=int_size[2]-2);
          translate([12/2/2*(dx-1), -10/2, 0])
            cube([12/2, 10, int_size[2]-2]);
        }
        cylinder(r=(3+1)/2, h=int_size[2]-2, $fs=1);
        // nut cut-in
        translate([0, 0, int_size[2]-2-13])
          scale(1.1)
            hull()
            {
              screw();
              translate([0, 9, 0])
                screw();
              translate([0, 9, 7])
                screw();
            }
      }
    }
  }

  // side bruses for better mounting - left/right
  for(dx = [-3, int_size[0]+2*wall])
    translate([dx, 0, 0])
      side_bruse_impl();
  // side bruses for better mounting - up/down
  for(dy = [-3, int_size[0]+2*wall])
    translate([75, dy, 0])
      rotate([0, 0, 90])
        side_bruse_impl();
}

module junction_box()
{
  difference()
  {
    junction_box_impl();
    translate([-10, -10, -5])
      cube([100,100,5]);
  }
}

if(false)
  translate([-7, -6, 10*2])
    controller();

junction_box();

use <controller.scad>
use <screw.scad>

module side_bruse_impl()
{
  for(sig = [-1, +1])
    for(i = [1, 2, 3])
      translate([0, i*18, -1])
        rotate([sig*20, 0, 0])
          cube([3, 2, 26]);
}

module junction_box_impl()
{
  wall = 2;
  extra_depth = 5;
  int_size = [70, 70, 24+3+extra_depth];

  difference()
  {
    // main box
    cube(int_size + [2,2,1]*wall);
    translate([1,1,1]*wall)
      cube(int_size);
    // place for cables
    cable_cut_in = [20, 10, wall];
    #translate([(int_size[0]+2*wall-cable_cut_in[0])/2, wall, 0])
      cube(cable_cut_in);
  }

  // screw drivers
  dist_from_center = 59/2;
  for(dx = [-1, +1])
  {
    translate([(int_size[0]+2*wall)/2+dx*dist_from_center, wall+30, wall])
    {
      difference()
      {
        // main screw corridor
        union()
        {
          cylinder(r=10/2, h=int_size[2]-2);
          #translate([12/2/2*(dx-1), -10/2, 0])
            cube([12/2, 10, int_size[2]-2]);
        }
        cylinder(r=(3+1)/2, h=int_size[2]-2, $fs=1);
        // nut cut-in
        translate([0, 0, int_size[2]-2-13])
          scale(1.1)
            hull()
            {
              screw();
              translate([0, 9, 0])
                screw();
              translate([0, 9, 7])
                screw();
            }
      }
    }
  }

  // side bruses for better mounting - left/right
  for(dx = [-3, int_size[0]+2*wall])
    translate([dx, 0, 0])
      side_bruse_impl();
  // side bruses for better mounting - up/down
  for(dy = [-3, int_size[0]+2*wall])
    translate([75, dy, 0])
      rotate([0, 0, 90])
        side_bruse_impl();
}

module junction_box()
{
  difference()
  {
    junction_box_impl();
    translate([-10, -10, -5])
      cube([100,100,5]);
  }
}

if(false)
  translate([-7, -6, 10*2])
    controller();

junction_box();


added clearance in case top for solder bumps on header holes

// Serial DMM adapter case
// designed to fit an Arduino nano clone and a DB-9 male plug
//
// Copyright (C) 2016 Theodore C. Yapo

layout = "printing";
//layout = "exploded";

board_width = 18.5;
board_length = 44.5;
board_thickness = 1.85;
usb_lip = 2;
usb_height = 4.25;
usb_width = 8;
usb_length = 9;

module nano_board()
{
  translate([-board_length/2, -board_width/2, 0]){
    color("blue") cube([board_length, board_width, board_thickness]);
  }
  translate([-board_length/2-2.5, -usb_width/2, board_thickness]){
    color([0.85, 0.85, 0.85]) cube([usb_length, usb_width, usb_height]);
  }
}

db9_hole_spacing = 25;
module db9_profile()
{
  corner_r = 3;
  top_w = 19.5;
  bottom_w = 17.5;
  height = 9.5;
  length = 7;
  back_length = 9;
  flange_w = 33.5;
  flange_h = 20;
  flange_r = 1;
  flange_thickness = 1.25;
  fn = 13;
  epsilon = 0.1;

  // pin shroud
  translate([0, 0, -back_clearance]){
    hull(){
      translate([+(-top_w/2 + corner_r), +(-height/2 + corner_r), 0]){
        cylinder($fn = fn, r = corner_r, h = length);
      }
      translate([+(-bottom_w/2 + corner_r), -(-height/2 + corner_r), 0]){
        cylinder($fn = fn, r = corner_r, h = length);
      }
      translate([-(-bottom_w/2 + corner_r), -(-height/2 + corner_r), 0]){
        cylinder($fn = fn, r = corner_r, h = length);
      }
      translate([-(-top_w/2 + corner_r), +(-height/2 + corner_r), 0]){
        cylinder($fn = fn, r = corner_r, h = length);
      }
    }
  }

  // back body
  b_corner_r = 3;
  b_top_w = 22;
  b_bottom_w = 19;
  b_height = 12;
  translate([0, 0, -back_clearance]){
    hull(){
      translate([+(-b_top_w/2 + b_corner_r),
                 +(-b_height/2 + b_corner_r),
                 -back_length-epsilon]){
        cylinder($fn = fn, r = b_corner_r, h = back_length+2*epsilon);
      }
      translate([+(-b_bottom_w/2 + b_corner_r),
                 -(-b_height/2 + b_corner_r),
                 -back_length-epsilon]){
        cylinder($fn = fn, r = b_corner_r, h = back_length+2*epsilon);
      }
      translate([-(-b_bottom_w/2 + b_corner_r),
                 -(-b_height/2 + b_corner_r),
                 -back_length-epsilon]){
        cylinder($fn = fn, r = b_corner_r, h = back_length+2*epsilon);
      }
      translate([-(-b_top_w/2 + b_corner_r),
                 +(-b_height/2 + b_corner_r),
                 -back_length-epsilon]){
        cylinder($fn = fn, r = b_corner_r, h = back_length+2*epsilon);
      }
    }
  }

  // flange
  hull(){
    translate([+(-flange_w/2 + flange_r), +(-flange_h/2 + flange_r), 0]){
      cylinder($fn = fn, r = flange_r, h = flange_thickness);
    }
    translate([+(-flange_w/2 + flange_r), -(-flange_h/2 + flange_r), 0]){
      cylinder($fn = fn, r = flange_r, h = flange_thickness);
    }
    translate([-(-flange_w/2 + flange_r), +(-flange_h/2 + flange_r), 0]){
      cylinder($fn = fn, r = flange_r, h = flange_thickness);
    }
    translate([-(-flange_w/2 + flange_r), -(-flange_h/2 + flange_r), 0]){
      cylinder($fn = fn, r = flange_r, h = flange_thickness);
    }
  }

}

height = 20;
length = 64;
width = 22;
board_lip = 2;
connector_width = 40;
connector_length = 18;
connector_recess = 5;
connector_height = 13;
bulge_length = 10;
bottom_thickness = 3;
nut_dist = 6;
screw_hole_d = 3.25;
screw_hole_x = length/2 - connector_length + 5;
screw_hole_y = (connector_width + width) / 4;

module case_bottom()
{
  difference(){
    union(){
      // body
      translate([-length/2, -width/2, 0]){
        cube([length, width, height/2]);
      }
      // DB9 connector bulge
      translate([length/2 - connector_length, -connector_width/2, 0]){
        cube([connector_length, connector_width, connector_height]);
      }
      // screw clamp bulge
      translate([-length/2, -connector_width/2, 0]){
        cube([bulge_length, connector_width, height/2]);
      }
    }

    // wire channel
    translate([-length/2 + usb_lip,
               -board_width/2 + board_lip,
               height/2]){
      cube([length - board_lip,
            board_width - 2*board_lip,
            height/2]);
    }

    // below-board hollow
    translate([-length/2 + usb_lip,
               -board_width/2 + board_lip,
               bottom_thickness]){
      cube([board_length - board_lip,
            board_width - 2*board_lip,
            height/2]);
    }
    // board recess
    translate([-length/2 + usb_lip,
               -board_width/2,
               height/2 - board_thickness]){
      cube([board_length,
            board_width,
            height/2]);
    }
    // DB9 opening
    translate([length/2-connector_recess, 0, height/2]){
      rotate([0, 90, 0]){
        rotate([0, 0, -90]){
          db9_profile();
        }
      }
    }
    // nut slots
    translate([length/2-nut_dist, -db9_hole_spacing/2, height/2]){
      rotate([0, -90, 0]){
        hull(){
          cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          translate([20, 0, 0]){
            cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          }
        }
      }
    }
    translate([length/2-nut_dist, +db9_hole_spacing/2, height/2]){
      rotate([0, -90, 0]){
        hull(){
          cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          translate([20, 0, 0]){
            cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          }
        }
      }
    }

    // screw holes
    epsilon = 1;
    screw_hole_d = 3.25;
    screw_hole_x1 = length/2 - connector_length + 5;
    screw_hole_y = (connector_width + width) / 4;
    translate([screw_hole_x1, -screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    translate([screw_hole_x1, +screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }

    screw_hole_x2 = -length/2 + 5;
    translate([screw_hole_x2, -screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    translate([screw_hole_x2, +screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }

    // DB connector screw holes
    translate([length/2 -15,  -db9_hole_spacing/2, height/2]){
      rotate([0, 90, 0]){
        cylinder($fn = 8, d = screw_hole_d, h = height);
      }
    }
    translate([length/2 -15,  +db9_hole_spacing/2, height/2]){
      rotate([0, 90, 0]){
        cylinder($fn = 8, d = screw_hole_d, h = height);
      }
    }

  }
}

module case_top()
{
  epsilon = 1;

  difference(){
    union(){
      // body
      translate([-length/2, -width/2, 0]){
        cube([length, width, height/2]);
      }
      // DB9 connector bulge
      translate([length/2 - connector_length, -connector_width/2, 0]){
        cube([connector_length, connector_width, height-connector_height]);
      }
      // screw clamp bulge
      translate([-length/2, -connector_width/2, 0]){
        cube([bulge_length, connector_width, height/2]);
      }
    }

    // DB9 connector bulge trim
    tol = 0.5;
    translate([length/2 - connector_length - tol,
               -connector_width/2,
               height-connector_height]){
      cube([connector_length+epsilon+tol, connector_width, connector_height]);
    }

    // wire channel
    translate([-length/2 + usb_lip,
               -board_width/2 + board_lip,
               height - connector_height]){
      cube([length - board_lip,
            board_width - 2*board_lip,
            height/2]);
    }

    // below-board hollow
    translate([-length/2 + usb_lip,
               -board_width/2 + board_lip,
               bottom_thickness]){
      cube([board_length - board_lip,
            board_width - 2*board_lip,
            height/2]);
    }

    // solder_bump recess
    solder_bump_thickness = 1.25;
    corner_size = 5;
    translate([-length/2 + usb_lip + corner_size,
               -board_width/2,
               height/2 - solder_bump_thickness]){
      cube([board_length - 2*corner_size,
            board_width,
            height/2]);
    }

    // DB9 opening
    translate([length/2-connector_recess, 0, height/2]){
      rotate([0, 90, 0]){
        rotate([0, 0, 90]){
          db9_profile();
        }
      }
    }

    // usb slot
    translate([-length/2-5, -usb_width/2, height/2-usb_height]){
      cube([10, usb_width, usb_height+epsilon]);
    }

    // nut slots
    translate([length/2-nut_dist, -db9_hole_spacing/2, height/2]){
      rotate([0, -90, 0]){
        hull(){
          cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          translate([20, 0, 0]){
            cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          }
        }
      }
    }
    translate([length/2-nut_dist, +db9_hole_spacing/2, height/2]){
      rotate([0, -90, 0]){
        hull(){
          cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          translate([20, 0, 0]){
            cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          }
        }
      }
    }

    // screw holes
    epsilon = 1;
    screw_hole_d = 3.25;
    screw_hole_x1 = length/2 - connector_length + 5;
    screw_hole_y = (connector_width + width) / 4;
    translate([screw_hole_x1, -screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    translate([screw_hole_x1, +screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    screw_hole_x2 = -length/2 + 5;
    translate([screw_hole_x2, -screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    translate([screw_hole_x2, +screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
  }
}

if (layout == "exploded"){
  exploded_dist = 10;

  case_bottom();
  translate([0, 0, 4*exploded_dist]){
    mirror([0, 0, 1]){
      case_top();
    }
  }
  translate([-(length - board_length)/2 + usb_lip,
             0,
             height/2 - board_thickness + exploded_dist]){
    nano_board();
  }
  translate([length/2-connector_recess + exploded_dist,
             0,
             height/2 + exploded_dist]){
    rotate([0, 90, 0]){
      rotate([0, 0, -90]){
        color([0.85, 0.85, 0.85]) db9_profile();
      }
    }
  }
}

if (layout == "printing"){
  s = 25;

  translate([0, +s, 0]){
    case_bottom();
  }
  translate([0, -s, 0]){
    rotate([0, 0, 180]){
      case_top();
    }
  }
}

// Serial DMM adapter case
// designed to fit an Arduino nano clone and a DB-9 male plug
//
// Copyright (C) 2016 Theodore C. Yapo

layout = "printing";
//layout = "exploded";

board_width = 18.5;
board_length = 44.5;
board_thickness = 1.85;
usb_lip = 2;
usb_height = 4.25;
usb_width = 8;
usb_length = 9;

module nano_board()
{
  translate([-board_length/2, -board_width/2, 0]){
    color("blue") cube([board_length, board_width, board_thickness]);
  }
  translate([-board_length/2-2.5, -usb_width/2, board_thickness]){
    color([0.85, 0.85, 0.85]) cube([usb_length, usb_width, usb_height]);
  }
}

db9_hole_spacing = 25;
module db9_profile()
{
  corner_r = 3;
  top_w = 19.5;
  bottom_w = 17.5;
  height = 9.5;
  length = 7;
  back_length = 9;
  flange_w = 33.5;
  flange_h = 20;
  flange_r = 1;
  flange_thickness = 1.25;
  fn = 13;
  epsilon = 0.1;

  // pin shroud
  translate([0, 0, -back_clearance]){
    hull(){
      translate([+(-top_w/2 + corner_r), +(-height/2 + corner_r), 0]){
        cylinder($fn = fn, r = corner_r, h = length);
      }
      translate([+(-bottom_w/2 + corner_r), -(-height/2 + corner_r), 0]){
        cylinder($fn = fn, r = corner_r, h = length);
      }
      translate([-(-bottom_w/2 + corner_r), -(-height/2 + corner_r), 0]){
        cylinder($fn = fn, r = corner_r, h = length);
      }
      translate([-(-top_w/2 + corner_r), +(-height/2 + corner_r), 0]){
        cylinder($fn = fn, r = corner_r, h = length);
      }
    }
  }

  // back body
  b_corner_r = 3;
  b_top_w = 22;
  b_bottom_w = 19;
  b_height = 12;
  translate([0, 0, -back_clearance]){
    hull(){
      translate([+(-b_top_w/2 + b_corner_r),
                 +(-b_height/2 + b_corner_r),
                 -back_length-epsilon]){
        cylinder($fn = fn, r = b_corner_r, h = back_length+2*epsilon);
      }
      translate([+(-b_bottom_w/2 + b_corner_r),
                 -(-b_height/2 + b_corner_r),
                 -back_length-epsilon]){
        cylinder($fn = fn, r = b_corner_r, h = back_length+2*epsilon);
      }
      translate([-(-b_bottom_w/2 + b_corner_r),
                 -(-b_height/2 + b_corner_r),
                 -back_length-epsilon]){
        cylinder($fn = fn, r = b_corner_r, h = back_length+2*epsilon);
      }
      translate([-(-b_top_w/2 + b_corner_r),
                 +(-b_height/2 + b_corner_r),
                 -back_length-epsilon]){
        cylinder($fn = fn, r = b_corner_r, h = back_length+2*epsilon);
      }
    }
  }

  // flange
  hull(){
    translate([+(-flange_w/2 + flange_r), +(-flange_h/2 + flange_r), 0]){
      cylinder($fn = fn, r = flange_r, h = flange_thickness);
    }
    translate([+(-flange_w/2 + flange_r), -(-flange_h/2 + flange_r), 0]){
      cylinder($fn = fn, r = flange_r, h = flange_thickness);
    }
    translate([-(-flange_w/2 + flange_r), +(-flange_h/2 + flange_r), 0]){
      cylinder($fn = fn, r = flange_r, h = flange_thickness);
    }
    translate([-(-flange_w/2 + flange_r), -(-flange_h/2 + flange_r), 0]){
      cylinder($fn = fn, r = flange_r, h = flange_thickness);
    }
  }

}

height = 20;
length = 64;
width = 22;
board_lip = 2;
connector_width = 40;
connector_length = 18;
connector_recess = 5;
connector_height = 13;
bulge_length = 10;
bottom_thickness = 3;
nut_dist = 6;
screw_hole_d = 3.25;
screw_hole_x = length/2 - connector_length + 5;
screw_hole_y = (connector_width + width) / 4;

module case_bottom()
{
  difference(){
    union(){
      // body
      translate([-length/2, -width/2, 0]){
        cube([length, width, height/2]);
      }
      // DB9 connector bulge
      translate([length/2 - connector_length, -connector_width/2, 0]){
        cube([connector_length, connector_width, connector_height]);
      }
      // screw clamp bulge
      translate([-length/2, -connector_width/2, 0]){
        cube([bulge_length, connector_width, height/2]);
      }
    }

    // wire channel
    translate([-length/2 + usb_lip,
               -board_width/2 + board_lip,
               height/2]){
      cube([length - board_lip,
            board_width - 2*board_lip,
            height/2]);
    }

    // below-board hollow
    translate([-length/2 + usb_lip,
               -board_width/2 + board_lip,
               bottom_thickness]){
      cube([board_length - board_lip,
            board_width - 2*board_lip,
            height/2]);
    }
    // board recess
    translate([-length/2 + usb_lip,
               -board_width/2,
               height/2 - board_thickness]){
      cube([board_length,
            board_width,
            height/2]);
    }
    // DB9 opening
    translate([length/2-connector_recess, 0, height/2]){
      rotate([0, 90, 0]){
        rotate([0, 0, -90]){
          db9_profile();
        }
      }
    }
    // nut slots
    translate([length/2-nut_dist, -db9_hole_spacing/2, height/2]){
      rotate([0, -90, 0]){
        hull(){
          cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          translate([20, 0, 0]){
            cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          }
        }
      }
    }
    translate([length/2-nut_dist, +db9_hole_spacing/2, height/2]){
      rotate([0, -90, 0]){
        hull(){
          cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          translate([20, 0, 0]){
            cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          }
        }
      }
    }

    // screw holes
    epsilon = 1;
    screw_hole_d = 3.25;
    screw_hole_x1 = length/2 - connector_length + 5;
    screw_hole_y = (connector_width + width) / 4;
    translate([screw_hole_x1, -screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    translate([screw_hole_x1, +screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }

    screw_hole_x2 = -length/2 + 5;
    translate([screw_hole_x2, -screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    translate([screw_hole_x2, +screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }

    // DB connector screw holes
    translate([length/2 -15,  -db9_hole_spacing/2, height/2]){
      rotate([0, 90, 0]){
        cylinder($fn = 8, d = screw_hole_d, h = height);
      }
    }
    translate([length/2 -15,  +db9_hole_spacing/2, height/2]){
      rotate([0, 90, 0]){
        cylinder($fn = 8, d = screw_hole_d, h = height);
      }
    }

  }
}

module case_top()
{
  epsilon = 1;

  difference(){
    union(){
      // body
      translate([-length/2, -width/2, 0]){
        cube([length, width, height/2]);
      }
      // DB9 connector bulge
      translate([length/2 - connector_length, -connector_width/2, 0]){
        cube([connector_length, connector_width, height-connector_height]);
      }
      // screw clamp bulge
      translate([-length/2, -connector_width/2, 0]){
        cube([bulge_length, connector_width, height/2]);
      }
    }

    // DB9 connector bulge trim
    tol = 0.5;
    translate([length/2 - connector_length - tol,
               -connector_width/2,
               height-connector_height]){
      cube([connector_length+epsilon+tol, connector_width, connector_height]);
    }

    // wire channel
    translate([-length/2 + usb_lip,
               -board_width/2 + board_lip,
               height - connector_height]){
      cube([length - board_lip,
            board_width - 2*board_lip,
            height/2]);
    }

    // below-board hollow
    translate([-length/2 + usb_lip,
               -board_width/2 + board_lip,
               bottom_thickness]){
      cube([board_length - board_lip,
            board_width - 2*board_lip,
            height/2]);
    }

    // DB9 opening
    translate([length/2-connector_recess, 0, height/2]){
      rotate([0, 90, 0]){
        rotate([0, 0, 90]){
          db9_profile();
        }
      }
    }

    // usb slot
    translate([-length/2-5, -usb_width/2, height/2-usb_height]){
      cube([10, usb_width, usb_height+epsilon]);
    }

    // nut slots
    translate([length/2-nut_dist, -db9_hole_spacing/2, height/2]){
      rotate([0, -90, 0]){
        hull(){
          cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          translate([20, 0, 0]){
            cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          }
        }
      }
    }
    translate([length/2-nut_dist, +db9_hole_spacing/2, height/2]){
      rotate([0, -90, 0]){
        hull(){
          cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          translate([20, 0, 0]){
            cylinder($fn = 6, d = 6.25 / cos(30), h = 3);
          }
        }
      }
    }

    // screw holes
    epsilon = 1;
    screw_hole_d = 3.25;
    screw_hole_x1 = length/2 - connector_length + 5;
    screw_hole_y = (connector_width + width) / 4;
    translate([screw_hole_x1, -screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    translate([screw_hole_x1, +screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    screw_hole_x2 = -length/2 + 5;
    translate([screw_hole_x2, -screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
    translate([screw_hole_x2, +screw_hole_y, -epsilon]){
      cylinder($fn = 8, d = screw_hole_d, h = height);
    }
  }
}

if (layout == "exploded"){
  exploded_dist = 10;

  case_bottom();
  translate([0, 0, 4*exploded_dist]){
    mirror([0, 0, 1]){
      case_top();
    }
  }
  translate([-(length - board_length)/2 + usb_lip,
             0,
             height/2 - board_thickness + exploded_dist]){
    nano_board();
  }
  translate([length/2-connector_recess + exploded_dist,
             0,
             height/2 + exploded_dist]){
    rotate([0, 90, 0]){
      rotate([0, 0, -90]){
        color([0.85, 0.85, 0.85]) db9_profile();
      }
    }
  }
}

if (layout == "printing"){
  s = 25;

  translate([0, +s, 0]){
    case_bottom();
  }
  translate([0, -s, 0]){
    rotate([0, 0, 180]){
      case_top();
    }
  }
}