diff --git a/case/CaseBody.scad b/case/CaseBody.scad new file mode 100644 index 0000000..3d7f7a2 --- /dev/null +++ b/case/CaseBody.scad @@ -0,0 +1,150 @@ +include +include + +// test values: +//wallTh = 1.2; + +//noPcbPrev = true; + +if (is_undef(noBodyPrev) || noBodyPrev == false) { + caseBodyDrilled(); +} + + +// ------------------- + +module caseBody() { + + caseBase(); + caseWallsCut(); + pcbBackings(); + drillBoxes(); +} + +module caseBodyDrilled() { + difference() { + caseBody(); + caseDrillVoids(); + } +} + + +// --- base and walls --- + +module caseBase() { + cube([caseW, caseD, baseH]); +} + +module caseBack() { + translate([wallTh, 0, baseH]) + rotate(90, [0,0,1]) + cube([caseD, wallTh, caseH - baseH]); +} + +module caseWallR() { + translate([wallTh, 0, baseH]) + cube([caseW-wallTh*2, wallTh, caseH - baseH]); +} + +module caseWallL() { + translate([wallTh, caseD-wallTh, baseH]) + cube([caseW-wallTh*2, wallTh, caseH - baseH]); +} + +module caseFront() { + translate([caseW, 0, baseH]) + rotate(90, [0,0,1]) + cube([caseD, wallTh, caseH - baseH]); +} + +// --- cuts --- + +module dcCut() { + dcCutD = wallTh*3; + translate([dcCutD/2 + caseW, wallTh + pcbD/2-dcCutW/2-0.3, pcbZ+dcCutBottomPad]) + rotate(90, [0,0,1]) + cube([dcCutW, dcCutD, dcCutH+eps]); +} + +module caseWallRCut() { + translate([pcbBackMargin, + -eps, + baseH + pcbBottomMargin + 2]) + cube([pcbRightTerminalCut, wallRCutD, wallRCutH]); +} + + +module caseWalls() { + caseBack(); + caseWallR(); + caseWallL(); + caseFront(); +} + +module caseWallsCut() { + difference() { + caseWalls(); + dcCut(); + caseWallRCut(); + } +} + +// --- insides --- + +module pcbBackings() { + // rigth + translate([backingX, wallTh, baseH]) { + cube([backingW, backingD, backingH]); + } + + // left + translate([backingX, + caseD-pcbLeftMargin-backingD, + baseH]) { + cube([backingW, backingD+pcbLeftMargin-wallTh, backingH]); + } + + // back + translate([wallTh, wallTh + pcbD/2-espBackingD/2, baseH]) { + cube([pcbBackBackingW, espBackingD, backingH]); + } +} + +module drillTube(h) { + cylinder(h, d=drillBoxW); +} + +module drillBox(h) { + // use center positioning for tube compatiblility + translate([-drillBoxW/2, -drillBoxW/2, 0]) + cube([drillBoxW, drillBoxW, h]); +} + +module drillBoxes() { + translate(drillings[0]) { + drillBox(caseH-baseH); + } + translate(drillings[1]) { + drillBox(caseH-baseH); + } +} + +// --- drillings --- + +module drillVoid(h) { + cylinder(h, d=printedDrillD, $fn=drillFn); +} + +module caseDrillVoids() { + translate(drillings[0]) { + drillVoid(caseH*1.5); + } + translate(drillings[1]) { + drillVoid(caseH*1.5); + } + translate(drillings[2]) { + drillVoid(caseH*0.5); + } +} + + diff --git a/case/CaseBodyExtended.scad b/case/CaseBodyExtended.scad new file mode 100644 index 0000000..0aa14a2 --- /dev/null +++ b/case/CaseBodyExtended.scad @@ -0,0 +1,53 @@ +include +include +include + +noBodyPrev = true; +noDrillingsPrev = true; +noPcbPrev = true; +noRoofPrev = true; + +//noExtPrev = false; +noExtPrev = true; + + +if (is_undef(noCaseBodyExtendedPrev) || noCaseBodyExtendedPrev == false) { + caseBodyExtended(); + + if (!noExtPrev) { + extendedBaseTr() { + placedPcb(); + %caseRoofDrilled(); + } + } +} + + +// ------------------- + +module caseBodyExtended() { + extendedBase(); + extendedBaseTr() { + caseBodyWithSnapHoles(); + } +} + +module caseBodyWithSnapHoles() { + difference() { + caseBodyDrilled(); + for(v = caseSnaps) { + translate([v[0], v[1]-eps, v[2]]) + snapFitFemale([snapW, snapD+eps*2, snapH], snapEc, snapFemalePadding); + } + } +} + +module extendedBaseTr() { + translate([0, coverTh+coverMargin, 0]) + children(); +} + +module extendedBase() { + cube([caseW, coverD, baseH]); +} + diff --git a/case/CaseRoof.scad b/case/CaseRoof.scad new file mode 100644 index 0000000..31cae04 --- /dev/null +++ b/case/CaseRoof.scad @@ -0,0 +1,50 @@ +include +include + +noBodyPrev = true; +noPcbPrev = true; + +if (is_undef(noRoofPrev) || noRoofPrev == false) { + caseRoofDrilled(); + //extraDrillings(); +} + +// ------------------- + +module caseRoof() { + translate([0,0,caseH]) + cube([caseW, caseD, roofTh]); +} + +module casePinCut() { + translate([pinCutX, pinCutY, caseH-roofTh]) + cube([pinCutW, pinCutD, roofTh*3]); +} + +module caseRoofCut() { + difference() { + caseRoof(); + casePinCut(); + caseWallRCut(); + extraDrillings(); + } +} + +module caseRoofDrilled() { + difference() { + caseRoofCut(); + caseDrillVoids(); + } +} + +module extraDrillings() { + for (v = edPos) { + translate([v[0], v[1], caseH-eps]) + rotate(v[2]) + for (r = [0:edRows-1]) + for(c = [0:edCols-1]) + translate([c * edSpacing, r * edSpacing, 0]) { + cylinder(edH, edPrintedRadius, edPrintedRadius, $fn = 50); + } + } +} diff --git a/case/Cover.scad b/case/Cover.scad new file mode 100644 index 0000000..678d7ca --- /dev/null +++ b/case/Cover.scad @@ -0,0 +1,98 @@ +include +include +include + +noBodyPrev = true; +noDrillingsPrev = true; +noPcbPrev = true; +noRoofPrev = true; +noCaseBodyExtendedPrev = true; +noLedHookPrev = true; + +//noExtPrev = false; +noExtPrev = true; + +if (is_undef(noCoverPrev) || noCoverPrev == false) { + translate([0, 0, baseH]) + cover(); + + if (!noExtPrev) { + caseBodyExtended(); + extendedBaseTr() { + placedPcb(); + caseRoofDrilled(); + } + } +} + + +// ------------------- + +module coverCore() { + cube([caseW, coverD, coverH]); +} + +module coverFrontCut() { + translate([caseW+eps, coverTh, -eps]) { + rotate(90, [0,0,1]) + cube([caseD + coverMargin*2, + coverTh + eps, + caseH - baseH + roofTh + coverMargin]); + } +} + +module coverBackCut() { + translate([coverTh+eps, coverTh, -eps]) + rotate(90, [0,0,1]) + cube([caseD + coverMargin*2, + coverTh + eps*2, + caseH - baseH + roofTh + coverMargin]); +} + +module coverRoofCut() { + translate([coverLedPos[0], coverLedPos[1], baseH]) + cylinder(h = coverH, d = coverLedHoleD, $fn=50); + +} + +module coverVoid() { + translate([coverTh, coverTh, -eps]) + cube([caseW-coverTh*2+eps, + caseD+coverMargin*2, + coverH - coverTh+eps]); +} + +module coverCuts() { + coverFrontCut(); + coverBackCut(); + coverRoofCut(); +} + +module coverLedHook() { + ledHook(ledHookSize, ledHookTh, ledHookSlitW); +} + +module cover() { + difference() { + coverCore(); + coverCuts(); + coverVoid(); + } + + // snaps + translate([coverSnaps[0].x+snapW, coverSnaps[0].y+snapD-eps, coverSnaps[0].z-baseH]) + rotate([0,0,180]) + snapFitMaleF([snapW, snapD+eps*2, snapH], snapEc); + + translate([coverSnaps[1].x, coverSnaps[1].y-eps, coverSnaps[1].z-baseH]) + snapFitMaleF([snapW, snapD+eps*2, snapH], snapEc); + + // led hook + if (integrateCoverLedHook) { + translate([coverLedPos[0] - ledHookSize.x/2, + coverLedPos[1] - ledHookSize.y/2, + coverH - ledHookSize.z - coverTh+eps]) + coverLedHook(); + } +} + diff --git a/case/LedHook.scad b/case/LedHook.scad new file mode 100644 index 0000000..6d25c7f --- /dev/null +++ b/case/LedHook.scad @@ -0,0 +1,23 @@ +include + +if (is_undef(noLedHookPrev) || noLedHookPrev == false) { + ledHookSeparate(ledHookSize, ledHookTh, ledHookSlitW, eps); +} + +module ledHook(wdh, th, slitW, eps = 0.001) { + difference() { + cube(wdh); + translate([-eps, -th, th]) { + cube([wdh.x+eps*2, wdh.y, wdh.z]); + } + translate([wdh.x / 2 - slitW / 2, -eps, -eps]) + cube([slitW, wdh.y, th+eps*2]); + } +} + +module ledHookSeparate(wdh, th, slitW, eps = 0.001) { + ledHook(wdh, th, slitW, eps); + translate([0, wdh.y-th-eps, wdh.z-th]) + cube([wdh.x, wdh.y, th]); +} + diff --git a/case/RfBoard.scad b/case/RfBoard.scad new file mode 100644 index 0000000..5ff44df --- /dev/null +++ b/case/RfBoard.scad @@ -0,0 +1,34 @@ + +module buttonBlock() { + cube([4, 8, 3]); +} + +module ucBlock() { + cube([8, 8, 3]); +} + +module rfBoard() { + color("red") + translate([0,0,0.5]) + import("rf-mapping.svg"); + color("yellow") { + translate([25, 10, 1]) { + buttonBlock(); + } + translate([25, 25, 1]) { + buttonBlock(); + } + translate([25, 40, 1]) { + buttonBlock(); + } + } + color("black") { + translate([5, 30, 1]) { + ucBlock(); + } + translate([12, 15, 1]) { + ucBlock(); + } + } +} + diff --git a/case/SnapFit.scad b/case/SnapFit.scad new file mode 100644 index 0000000..763dca3 --- /dev/null +++ b/case/SnapFit.scad @@ -0,0 +1,38 @@ + +//snapFitMale([100, 30, 30], 10); + +//snapFitMaleF([100, 30, 30], 10); + + +module snapFitMale(wdh, edgeCutD) { + eps = 0.001; + d = wdh[1] + edgeCutD; + a = atan(wdh[2] / d); + + translate([0, -edgeCutD,0]) { + difference() { + cube([wdh[0], d, wdh[2]]); + + translate([-eps, 0,0]) { + rotate([a,0,0]) { + cube([wdh[0]+eps*2, d*2, wdh[2]*2]); + } + } + + translate([-eps, 0, -eps]) { + cube([wdh[0]+eps*2, edgeCutD, wdh[2] + eps]); + } + } // diff + } // bring to 0,0,0 +} + +module snapFitMaleF(wdh, edgeCutD) { + translate([wdh[0], 0, wdh[2]]) + rotate([0,180,0]) + snapFitMale(wdh,edgeCutD); +} + +module snapFitFemale(wdh, edgeCutD, pad = 0) { + d = wdh[1] + edgeCutD; + cube([wdh[0], d, wdh[2]+pad]); +} \ No newline at end of file diff --git a/case/TargetPcb.scad b/case/TargetPcb.scad new file mode 100644 index 0000000..d69de26 --- /dev/null +++ b/case/TargetPcb.scad @@ -0,0 +1,24 @@ +include + +if (is_undef(noPcbPrev) || noPcbPrev == false) { + placedPcb(); +} + +// ------------------- + +module pcb() { + translate([32.01, 18.255, 4.14]) { + rotate(-90, [0,0,1]) { + rotate(90, [1,0,0]) { + color(pcbColor, pcbAlpha) + import("mqtrigger.stl"); + } + } + } +} + +module placedPcb() { + translate([pcbX, pcbY, pcbZ]) { + pcb(); + } +} \ No newline at end of file diff --git a/case/config.scad b/case/config.scad new file mode 100644 index 0000000..e02bae7 --- /dev/null +++ b/case/config.scad @@ -0,0 +1,125 @@ +// MqTrigger case config + +eps = 0.01; + +// --- missing target PCB (.stl) values --- + +pcbW = 60; +pcbD = 43; +pcbBottomMargin = 5; +pcbFrontMargin = 1; +pcbColor = "green"; +pcbAlpha = 0.2; + +// --- case body --- + +caseW = 71; +caseD = 55.8; +caseH = 20; + +baseH = 2; +wallTh = 2; + +dcCutW = 11; +dcCutH = 12; +dcCutBottomPad = 1; + +wallRCutH = caseH*0.8; +wallRCutD = 15; + +// pcb helpers +pcbBackMargin = caseW-pcbW-wallTh; +pcbLeftMargin = caseD-pcbD-wallTh; +pcbX = caseW-pcbW-wallTh-pcbFrontMargin; +pcbY = wallTh; +pcbZ = baseH + pcbBottomMargin; +pcbRightTerminalCut = pcbW-4.5; +pcbBackBackingW = caseW-pcbW-wallTh*2 + 4; + +// --- pcb backings (support) --- + +backingW = 15; +backingD = 3; +backingH = pcbBottomMargin*0.95; +backingX = pcbBackMargin+pcbW*0.35; +espBackingD = 10; +espBackingW = 10.7; + +// --- drilling params --- + +drillD = 2.5; +drillPad = 1.5; +drillPrintMargin = -0.5; +printedDrillD = drillD + drillPrintMargin; +drillBoxW = 3+drillPad*2; +drillFn = 50; + +// --- drilling coordinates --- + +drillings = [ + // back right corner + [wallTh+drillBoxW/2, wallTh+drillBoxW/2, baseH], + + // front left cornder + [caseW-wallTh-drillBoxW/2, caseD-wallTh-drillBoxW/2, baseH], + + // hole in the pcb backing + [pcbBackMargin+1.55, pcbY+pcbD/2+0.3, baseH] +]; + +// --- roof --- + +roofTh = wallTh; +pinCutW = 17; +pinCutD = 10; +pinCutX = caseW-wallTh-pinCutW-pcbFrontMargin; +pinCutY = caseD-pinCutD-8; + +// roof extra drillings +edSpacing = 12; +edRadius = 2.5; +edPrintedRadius = edRadius + drillPrintMargin; +edH = 5; +edRows = 2; +edCols = 3; + + + +// x pos, y pos, z rot +edPos = [ + [edSpacing+wallTh*4, caseD - (edSpacing*2+wallTh*4) , 90], +]; + +// --- cover --- + +coverMargin = 0.1; //wallTh*2; //0.2; +coverTh = wallTh; +coverH = caseH + 20 + coverTh; +coverD = caseD+(coverTh+coverMargin)*2; + +echo("CoverH: ", coverH); +echo("CoverD: ", coverD); + +coverLedHoleD = 4 + drillPrintMargin; +coverLedPos = [caseW - pinCutW, coverTh + pinCutY + pinCutD/2]; + +snapW = 10; +snapD = wallTh; +snapH = 2; +snapEc = 0.2; // edge cut +snapFemalePadding = 0.1; + +caseSnaps = [ + [caseW/2 - snapW/3, 0, 3], + [caseW/2 - snapW/3, caseD-snapD, 3] +]; + +coverSnaps = [ + [caseW/2 - snapW/3, coverTh-eps, 3], + [caseW/2 - snapW/3, coverD-coverTh-snapD+eps, 3] +]; + +ledHookSize = [8, 10, 12]; +ledHookSlitW = 1; +ledHookTh = 2; +integrateCoverLedHook = false; diff --git a/case/mqtrigger.stl b/case/mqtrigger.stl new file mode 100644 index 0000000..7c005e9 Binary files /dev/null and b/case/mqtrigger.stl differ