├── .devcontainer
├── devcontainer.json
└── dockerfile
├── .gitignore
├── LICENSE
├── README.md
├── TODO.md
├── assembly-guide
├── README.md
└── gifs
│ ├── addMagnetsToMagnetModules.gif
│ ├── addMagnetsToSideWall.gif
│ ├── attachSideConnectorModulesToYBars.gif
│ ├── attachXBarWithYBar.gif
│ ├── attachXYPlates.gif
│ ├── attachXYTrays.gif
│ ├── connectXYTrayWithMainRails.gif
│ ├── insertDowelsIntoSideWall.gif
│ ├── insertFeet.gif
│ ├── propUpBottomXYTraywithSideWalls.gif
│ ├── screwFeet.gif
│ ├── screwXBarAndYBar.gif
│ ├── slideHexNutToFeet.gif
│ ├── slideHexNutsIntoYBar.gif
│ └── slideHexNutsIntoYBarXYPlate.gif
├── config
├── common.scad
├── dowel.scad
├── magnet.scad
├── print.scad
└── rackFrame.scad
├── helper
├── apply.scad
├── common.scad
├── dovetail.scad
├── filet.scad
├── keystone1.scad
├── keystone2.scad
├── math.scad
├── matrix.scad
├── screws.scad
└── sine.scad
├── media
├── bom
│ ├── dowel.gif
│ ├── fhcs_long.gif
│ ├── fhcs_medium.gif
│ ├── fhcs_short.gif
│ ├── glue.gif
│ ├── hex_nut.gif
│ └── magnet.gif
├── features
│ ├── slideOpt.gif
│ ├── stackConnectorOpt.gif
│ └── swivelOpt.gif
└── renders
│ ├── output.png
│ └── rackDisplayRounded.png
├── misc
├── animate.sh
└── bomAnimations.scad
├── rack-mount
├── angle-bracket
│ ├── README.md
│ ├── animate.gif
│ ├── animate.scad
│ └── entry.scad
├── catalog
│ ├── 120mm-Rear-Case-Fan.scad
│ ├── 120mm-fan-tray_mod.scad
│ ├── LG_Slim_DVD_Tray.scad
│ ├── Minisforum_NAB9-tray_mod.scad
│ ├── Minisforum_UM890PRO-tray_mod.scad
│ ├── README.md
│ ├── Unifi-8-PoE-Switch_Tray+Adapter.scad
│ ├── beelink-EQi12-box_mod.scad
│ ├── beelink-EQi12-tray_mod.scad
│ ├── beelink-mini-s-tray.scad
│ ├── brush-strip-plate.scad
│ ├── mele-quieter-tray.scad
│ ├── parts
│ │ └── sfxPSU.scad
│ └── rpi-sbc-simple-box
│ │ ├── case.scad
│ │ ├── frontPlate.scad
│ │ └── top.scad
├── common.scad
├── dimensionHelper.scad
├── enclosed-box
│ ├── README.md
│ ├── animate.gif
│ ├── animate.scad
│ ├── entry.scad
│ ├── frontBoxHolder.scad
│ ├── helper.scad
│ └── sideRail.scad
├── patch-panel
│ ├── README.md
│ ├── animate.gif
│ ├── animate.scad
│ ├── entry.scad
│ └── patchPanel.scad
├── plateBase.scad
├── rackEars.scad
└── tray
│ ├── README.md
│ ├── animate.gif
│ ├── animate.scad
│ ├── entry.scad
│ └── tray.scad
├── rack
├── assembly
│ ├── addMagnetsToMagnetModules.scad
│ ├── addMagnetsToSideWall.scad
│ ├── attachSideConnectorModulesToYBars.scad
│ ├── attachXBarWithYBar.scad
│ ├── attachXYPlates.scad
│ ├── attachXYTrays.scad
│ ├── common.scad
│ ├── connectXYTrayWithMainRails.scad
│ ├── finalBuilds.scad
│ ├── insertDowelsIntoSideWall.scad
│ ├── insertFeet.scad
│ ├── propUpBottomXYTraywithSideWalls.scad
│ ├── screwFeet.scad
│ ├── screwXBarAndYBar.scad
│ ├── slideHexNutToFeet.scad
│ ├── slideHexNutsIntoYBar.scad
│ └── slideHexNutsIntoYBarXYPlate.scad
├── connector
│ ├── basePlateYBarConnectors.scad
│ ├── connectors.scad
│ ├── mainRailYBarConnectors.scad
│ ├── sideModuleYBarConnectors.scad
│ ├── stackYBarConnectors.scad
│ ├── transformations.scad
│ └── xBarYBarConnectors.scad
├── mainRail.scad
├── print
│ ├── eval_P.scad
│ ├── hingeModule.scad
│ ├── magnetModuleLeft_P.scad
│ ├── magnetModuleRight_P.scad
│ ├── mainRail_P.scad
│ ├── rackFeet_P.scad
│ ├── rackJoiner_P.scad
│ ├── sideWallLeft_P.scad
│ ├── sideWallRight_P.scad
│ ├── stackConnectorBottom_P.scad
│ ├── xBar_P.scad
│ ├── xyPlate_P.scad
│ ├── yBarLeft_P.scad
│ └── yBarRight_P.scad
├── sharedVariables.scad
├── side
│ ├── hingeModule.scad
│ ├── magnetModule.scad
│ ├── sideWallBase.scad
│ ├── sideWallLeft.scad
│ ├── sideWallMagnetMount.scad
│ ├── sideWallRight.scad
│ └── sideWallVariables.scad
├── stackEnds.scad
├── xBar.scad
├── xyPlate.scad
└── yBar.scad
├── rbuild.py
└── stl
├── micro
└── rack
│ ├── eval_P.stl
│ ├── hingeModule.stl
│ ├── magnetModuleLeft_P.stl
│ ├── magnetModuleRight_P.stl
│ ├── mainRail_P.stl
│ ├── rackFeet_P.stl
│ ├── rackJoiner_P.stl
│ ├── sideWallLeft_P.stl
│ ├── sideWallRight_P.stl
│ ├── stackConnectorBottom_P.stl
│ ├── xBar_P.stl
│ ├── xyPlate_P.stl
│ ├── yBarLeft_P.stl
│ ├── yBarRight_P.stl
│ └── yBar_P.stl
├── mini
└── rack
│ ├── eval_P.stl
│ ├── hingeModule.stl
│ ├── magnetModuleLeft_P.stl
│ ├── magnetModuleRight_P.stl
│ ├── mainRail_P.stl
│ ├── rackFeet_P.stl
│ ├── rackJoiner_P.stl
│ ├── sideWallLeft_P.stl
│ ├── sideWallRight_P.stl
│ ├── stackConnectorBottom_P.stl
│ ├── xBar_P.stl
│ ├── xyPlate_P.stl
│ ├── yBarLeft_P.stl
│ ├── yBarRight_P.stl
│ └── yBar_P.stl
└── nano
└── rack
├── eval_P.stl
├── hingeModule.stl
├── magnetModuleLeft_P.stl
├── magnetModuleRight_P.stl
├── mainRail_P.stl
├── rackFeet_P.stl
├── rackJoiner_P.stl
├── sideWallLeft_P.stl
├── sideWallRight_P.stl
├── stackConnectorBottom_P.stl
├── xBar_P.stl
├── xyPlate_P.stl
├── yBarLeft_P.stl
├── yBarRight_P.stl
└── yBar_P.stl
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2 | // README at: https://github.com/devcontainers/templates/tree/main/src/debian
3 | {
4 | "build": { "dockerfile": "dockerfile" },
5 | "features": {
6 | "ghcr.io/devcontainers/features/python:1": {
7 | "installTools": true,
8 | "version": "latest"
9 | }
10 | },
11 |
12 | "customizations": {
13 | },
14 |
15 | "remoteUser": "vscode",
16 | "mounts": [
17 | "source=rackstack-bashhistory,target=/commandhistory,type=volume"
18 | ]
19 | }
--------------------------------------------------------------------------------
/.devcontainer/dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/devcontainers/base:bookworm
2 |
3 | RUN wget -qO- https://files.openscad.org/OBS-Repository-Key.pub | sudo tee /etc/apt/trusted.gpg.d/obs-openscad-nightly.asc \
4 | && echo "deb https://download.opensuse.org/repositories/home:/t-paul/Debian_12/ ./" >> /etc/apt/sources.list.d/openscad.list \
5 | && apt-get update && export DEBIAN_FRONTEND=noninteractive \
6 | && apt-get -y install --no-install-recommends openscad openscad-nightly libpng-dev libjpeg-dev libtiff-dev
7 |
8 |
9 | RUN apt-get -y install --no-install-recommends imagemagick
10 |
11 | RUN curl -sL http://www.lcdf.org/gifsicle/gifsicle-1.91.tar.gz | tar -zx \
12 | && cd gifsicle-1.91 \
13 | && ./configure --disable-gifview \
14 | && make install
15 |
16 | ARG USERNAME=vscode
17 | RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
18 | && mkdir /commandhistory \
19 | && touch /commandhistory/.bash_history \
20 | && chown -R $USERNAME /commandhistory \
21 | && echo "$SNIPPET" >> "/home/$USERNAME/.bashrc"
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | [#]*
3 | .idea
4 |
5 | **/stl/*
6 | !/stl/mini/
7 | !/stl/micro/
8 | !/stl/nano/
9 |
10 | **/tmp/
11 |
12 | .DS_Store
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Zhao Wang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rackstack
2 |
3 | 
4 |
5 | ### A modular 3d-printable mini rack system
6 | - ***Mount Anything:*** Perfect for organizing SBCs, mini PCs, small switches, power hubs, etc.
7 | - ***Fully customizable:*** Fully written in OpenSCAD. Everything, from the dimensions of the rack, to the roundness of the corners, can be modified with a simple code change.
8 | - ***Printable from home:*** Designed to be printed with conventional FDM printers. Requires minimal supports when printing, and final assembly needs only a few easy-to-source parts.
9 | - ***No cage nuts:*** Sliding hex nut design for the front rails allows one to easily mount items, without dealing with cage nuts.
10 | - ***Stackable:*** Individual racks can be easily stacked and fastened together. Mix and match different color and design combinations!
11 |
12 | ## Assembly
13 |
14 | Pre-generated STLs for roughly 200mm^3 (mini), 180mm^3 (micro), and 100mm^3 (nano) rack frames can be found in the [stl](stl) dir.
15 | These STLs are generated from the files in [rack/print](rack/print) - further information about printing these parts
16 | (supports, orientation) can be found in these files.
17 |
18 | ### Assembly Instructions
19 | Please see [the assembly guide](./assembly-guide).
20 |
21 | ### BOM - Required Tools:
22 | - 3d FDM Printer - build size requirements depend on configured rack profile
23 | - M3 Allen Key (for constructing the rack)
24 | - M4 Allen Key (for mounting rack-mount items)
25 |
26 | ### BOM - Single Rack:
27 |
28 | | Item | Name | Quantity | Comment |
29 | |---------------------------------------------------------------|---------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------|
30 | |
| M3x12 FHCS | 12 | Extras are useful and inexpensive. If you plan on eventually stacking multiple racks together, don't hesitate to get a lot more. |
31 | |
| M3x16 FHCS | 16 | ☝️ |
32 | |
| M3 hex nut | 28 | ☝️ |
33 | |
| 3x10 steel dowel pin | 4 | 3mm diameter, 10mm height |
34 | |
| 6x2 neodymium disc magnet | 8 | 6mm diameter, 2mm height |
35 | |
| super glue | \>= 2ml | Used to glue magnets to plastic |
36 |
37 |
38 | ### Printing - Single Rack:
39 | | Part | Quantity |
40 | |------------------------------------------------------|----------|
41 | | [Left Y-Bar](./rack/print/yBarLeft_P.scad) | 2 |
42 | | [Right Y-Bar](./rack/print/yBarRight_P.scad) | 2 |
43 | | [X-Bar](./rack/print/xBar_P.scad) | 4 |
44 | | [Main Rail](./rack/print/mainRail_P.scad) | 4 |
45 | | [Left Side Wall](./rack/print/sideWallLeft_P.scad) | 1 |
46 | | [Right Side Wall](./rack/print/sideWallRight_P.scad) | 1 |
47 | | [XY-Plate](./rack/print/xyPlate_P.scad) | 2 |
48 | | [Feet](./rack/print/rackFeet_P.scad) (optional) | 2 |
49 |
50 |
51 | #### Notes:
52 | - ⚠️ Before printing the actual parts. It's recommended to print this evaluation part: [eval_P.scad](./rack/print/eval_P.scad) to test tolerances.
53 | If you find the fits too tight/loose, you can adjust them [here](./config/print.scad). Please make sure also adjust the layer height in that file, too.
54 | - Omitted actual plastic for printing. Any conventional 3d printing plastic should do (PLA, PETG, ABS),
55 | but beware of PLA's thermal limits. Higher infill is recommended for all parts.
56 | - For joining two racks, you will need to print 4 [rackJoiners](./rack/print/rackJoiner_P.scad), as well as 8 M3 hex nuts, and 8 M3x12 FHCS.
57 | - Main front rails use M4 hex nuts and screws.
58 | - Side rails are mounted using M3 hex nuts and screws.
59 |
60 |
61 | ## Configuring + Generating STLs
62 | A python script: [rbuild.py](./rbuild.py) is provided to generate different project stls. **Before running the script**, please
63 | configure the path to the OpenSCAD binary in [rbuild.py](./rbuild.py).
64 |
65 | Requirements:
66 | - `openscad` CLI binary
67 | - `python3`
68 |
69 | ### Examples:
70 | Generate all project files for the `micro` profile:
71 |
72 | `python3 rbuild.py -b all -c micro`
73 |
74 | This will build all the parts defined in [rack/print](./rack/print), and put the STLs in [stl/micro](./stl/micro).
75 | You can also provide a `-dz {n}` parameter to adjust the height of the generated rack. Configuring other rack
76 | variables can be done in [config/rackframe.scad](./config/rackFrame.scad).
77 |
78 | For generating a specific part, and putting it into a new `stl/custom` target directory:
79 |
80 | `python3 rbuild.py -b yBar -c micro -t custom`
81 |
82 | `rbuild.py` also support an optional `--nightly` flag, which will run a nightly build of OpenSCAD. Please make sure the
83 | path to the nightly build is also configured in [rbuild.py](./rbuild.py).
84 |
85 |
86 | ### ⚠️ Important:
87 | Before committing to a full print, please try printing an evaluation print: [eval_P.scad](./rack/print/eval_P.scad) to test tolerances.
88 | It is very likely you will need to edit the default tolerances in [print.scad](./config/print.scad) for a nice fit.
89 |
90 |
91 | ## Trays, Boxes, etc
92 |
93 | Some parametric rack mount systems can be found in [rack-mount](./rack-mount). The following rack-mount systems
94 | are currently supported:
95 | - [Enclosed Box](./rack-mount/enclosed-box): For mounting box-shaped objects, without the need for any mounting holes on the box.
96 | - [Tray](./rack-mount/tray): Simple tray mounted using only the front rails. Can be configured to have screw mounts at the bottom of the tray.
97 | - [Patch Panel](./rack-mount/patch-panel): Linear patch panel array. Number of keystone slots can be configured.
98 | - [Angle Brackets](./rack-mount/angle-bracket): Simple Angle Bracket mounting system. Derived from the Enclosed Box system.
99 |
100 | ## Rack Mount Catalog
101 |
102 | There is a small catalog of various pre-configured rack-mountable parts in the [catalog](./rack-mount/catalog) directory. Please feel free to add anything even remotely
103 | useful!
104 |
105 | ## Designing rack-mount items
106 |
107 | Some useful variables for designing your own rack-mount items can be found in [rack-mount/dimensionHelper.scad](./rack-mount/dimensionHelper.scad).
108 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # case-project TODO list
2 |
3 | ### Actual TODO
4 |
5 | - Finish refactoring files to use the application style, like in `yBar.scad`.
6 | - Figure out why sidewall build is so slow.
7 | - Clean up `sharedVariables.scad`.
8 | - Parallel builds with cli tool.
9 | - Beef up rack-mount designs.
10 | - Make handles.
11 |
12 | ### Ideas
13 | - Start using matrices for transformations. Enforce strict local/global hierarchy of matrix transformations. (Kinda done)
14 | - GitHub CI for OpenSCAD stl building
15 | - Instead of using names like 'mainRailSlotToInnerYZFace', experiment with a central distance/dimension directory. Like:
16 | ```openscad
17 | // Define identifiers:
18 | mainRailSlot = "mainRailSlotIdentifier";
19 | yBarInnerYZ = "yBarInnerYZFaceIdentifier";
20 |
21 | // Define distance
22 | setDx(mainRailSlot, yBarInnerYZ, 3);
23 |
24 | // Define dimensions
25 | setX(mainRailSlot, 10);
26 | setX(yBarInnerYZ, 0);
27 |
28 | // Then, you can get distances like:
29 | dx(mainRailSlot, yBarInnerYZ); // == 3
30 | dx(yBarInnerYZ, mainRailSlot); // == 3
31 |
32 | dx(mainRailSlot, blah); //throw error
33 |
34 | // And you could possible chain distances like:
35 |
36 | dx(yBarInnerYZ, mainRailSlot, sideConnectorSlot);
37 | // which would eval to:
38 | // dx(yBarInnerYZ, mainRailSlot) + x(mainRailSlot) + dx(mainRailSlot, sideConnectorSlot);
39 | // OR
40 | dx(yBarInnerYZ, mainRailSlot, sideConnectorSlot, includeFirst=true, includeLast=true);
41 | // which would eval to:
42 | // x(yBarInnerYZ) + dx(yBarInnerYZ, mainRailSlot, sideConnectorSlot) + x(sideConnectorSlot);
43 | ```
44 | Hmm after looking into it a bit it seems that OpenScad's non-reassign rule is going to get in the way. Might still be
45 | worthwhile implement variable subsystem?
46 |
47 |
--------------------------------------------------------------------------------
/assembly-guide/README.md:
--------------------------------------------------------------------------------
1 | # Rack Assembly Instructions
2 |
3 | **Note**: Please see
4 | - [BOM](../README.md#bom---single-rack) for required materials, beyond the actual 3D printed parts.
5 | - [Print BOM](../README.md#printing---single-rack) for all the required 3D printed parts for a single rack.
6 |
7 | ## Instructions:
8 | Slide in M3 hex nuts into the Y-bars - 4 times. Each corner should have 3 hex nuts:
9 | 
10 |
11 | Glue magnets into magnet side-modules on the Y-bars - 4 times:
12 | 
13 |
14 | Glue top and bottom magnets into side walls - 2 times:
15 | 
16 |
17 | Insert top and bottom dowel rods into side walls - 2 times:
18 | 
19 |
20 | Slide Y-bars into X-bars. Do this 2 times. You should end up with 2 trays. Orientation on the Y-bars matters here; make sure that the magnets are on the same side:
21 | 
22 |
23 | Screw together Y-bars and X-bars using 4 M3x16 FHCS screws (one screw per corner) - 2 times:
24 | 
25 |
26 |
27 |
28 |
29 |
30 | Screw in the main rails with M3x16 FHCS screws.
31 | 
32 |
33 | Prop us the side wall using the side modules. Make sure the dowels are inserted properly, and the magnets align:
34 | 
35 |
36 | Slide in the other (top) tray. Make sure the magnets and dowels align. Screw in the main rails with M3x16 FHCS screws:
37 | 
38 |
39 | Attach the top and bottom plates with 4 M3x12 screws each:
40 | 
41 | 
42 |
43 | Slide in hex nuts into feet - 2 times:
44 | 
45 |
46 | Insert feet into the bottom of the rack:
47 | 
48 |
49 | Screw in feet using 4 M3x12 FHCS screws:
50 | 
51 |
52 |
53 | **FIN**
54 |
--------------------------------------------------------------------------------
/assembly-guide/gifs/addMagnetsToMagnetModules.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/addMagnetsToMagnetModules.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/addMagnetsToSideWall.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/addMagnetsToSideWall.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/attachSideConnectorModulesToYBars.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/attachSideConnectorModulesToYBars.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/attachXBarWithYBar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/attachXBarWithYBar.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/attachXYPlates.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/attachXYPlates.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/attachXYTrays.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/attachXYTrays.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/connectXYTrayWithMainRails.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/connectXYTrayWithMainRails.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/insertDowelsIntoSideWall.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/insertDowelsIntoSideWall.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/insertFeet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/insertFeet.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/propUpBottomXYTraywithSideWalls.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/propUpBottomXYTraywithSideWalls.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/screwFeet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/screwFeet.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/screwXBarAndYBar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/screwXBarAndYBar.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/slideHexNutToFeet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/slideHexNutToFeet.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/slideHexNutsIntoYBar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/slideHexNutsIntoYBar.gif
--------------------------------------------------------------------------------
/assembly-guide/gifs/slideHexNutsIntoYBarXYPlate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/assembly-guide/gifs/slideHexNutsIntoYBarXYPlate.gif
--------------------------------------------------------------------------------
/config/common.scad:
--------------------------------------------------------------------------------
1 | // Config aggregator file + some extra configs
2 | include <./dowel.scad>
3 | include <./magnet.scad>
4 | include <./rackFrame.scad>
5 | include <./print.scad>
6 |
7 |
8 | sideWallVentilation = true;
--------------------------------------------------------------------------------
/config/dowel.scad:
--------------------------------------------------------------------------------
1 | /*
2 | Dowel pin config used in side wall hinge module and side wall
3 | */
4 |
5 | dowelPinR = 1.5;
6 | dowelPinH = 10;
7 |
--------------------------------------------------------------------------------
/config/magnet.scad:
--------------------------------------------------------------------------------
1 | include <./print.scad>
2 |
3 | // Dimensions for small cylindrical neodymium magnets that I bought off Amazon
4 | magnetR = 3;
5 | magnetH = 1.7;
6 |
7 | magnetRSlack = 0.1;
8 | magnetHSlack = 0.05;
9 |
10 | magnetRSlacked = magnetR + magnetRSlack;
11 | magnetHSlacked = magnetH + magnetHSlack;
--------------------------------------------------------------------------------
/config/print.scad:
--------------------------------------------------------------------------------
1 | // Print settings config file
2 |
3 | /**********************************************************************************************************************
4 | Slack config to standardize different usages of slack/tolerance values.
5 |
6 | The purpose of this config is to introduce some consistency with how slack values defined in code. E.g. Why is the
7 | slack value defined as 0.3 in this file, but 0.4 in another? This will also allow model-level adjustments for tighter
8 | fitting parts, for when it might not convenient to adjust the actual 3d printer (using a 3d printer at a makerspace,
9 | for example).
10 |
11 | Some important details:
12 | - The general philosophy for slack applications in this project is to subtract space from sockets, while not
13 | modifying the plugs.
14 | - Values are signed. Positive values can be interpreted as how much to remove from the socket along some dimension.
15 | - These values depend on print orientation and it's assumed parts are printed in their recommended orientations.
16 | */
17 | xySlack = 0.25;
18 |
19 | radiusXYSlack = xySlack/2;
20 |
21 | zSlack = 0.0;
22 |
23 | overhangSlack = 0.5;
24 |
25 | supportedOverhangSlack = 0.5;
26 |
27 | // special slack cases, change if neccessary
28 | xBarYBarDovetailSlack = xySlack;
29 |
30 | /**********************************************************************************************************************
31 | Printer/slicer config, mainly used for calculating some special overhangs.
32 | */
33 | defaultLayerHeight = 0.3;
34 |
--------------------------------------------------------------------------------
/config/rackFrame.scad:
--------------------------------------------------------------------------------
1 | // Manually set this variable to toggle rack profile
2 | profileName = "default";
3 |
4 | fixedSideModules = true;
5 |
6 | _profileConfigs = [
7 | // You can introduce a custom profile like:
8 | /*
9 | ["custom", [
10 | ["maxUnitWidth", 180],
11 | ["maxUnitDepth", 120],
12 | ["numRailScrews", 10]
13 | ]], // To generate the stls for this custom profile, you would do:
14 | // $ python3 rbuild.py -b all -c custom
15 | */
16 | ["default", [ // Default config. Will be overwritten by any other profiles
17 | ["maxUnitWidth", 180],
18 | ["maxUnitDepth", 180],
19 | ["numRailScrews", 12],
20 | ["screwDiff", 10],
21 | ["mainRailScrewType", "m4"],
22 | ["mainRailSideMountScrewType", "m4"],
23 | ["rackFrameScrewType", "m3"],
24 | ["baseRoundness", 5],
25 | ]],
26 | ["nano", [
27 | ["maxUnitWidth", 105],
28 | ["maxUnitDepth", 105],
29 | ["numRailScrews", 10]
30 | ]],
31 | ["micro", [
32 | ["maxUnitWidth", 180],
33 | ["maxUnitDepth", 180],
34 | ["numRailScrews", 12]
35 | ]],
36 | ["mini", [
37 | ["maxUnitWidth", 205],
38 | ["maxUnitDepth", 205],
39 | ["numRailScrews", 16]
40 | ]]
41 | ];
42 |
43 | function _getConfigValueRaw(profile, varName) = profile[search([varName], profile)[0]][1];
44 | function _getProfileRaw(profileName) = _profileConfigs[search([profileName], _profileConfigs)[0]][1];
45 |
46 | function _getConfigValueOrThrowError(val) = val == undef? assert(false, "blah") 0: val;
47 | function _getConfigValueOrDefault(val, default) = val == undef? default: val;
48 |
49 | function getConfigValue(profile, varName) =
50 | _getConfigValueOrDefault(
51 | _getConfigValueRaw(profile, varName),
52 | _getConfigValueOrThrowError(_getConfigValueRaw(getProfile("default"), varName))
53 | );
54 |
55 | function getProfile(profileName) = _getConfigValueOrThrowError(_getProfileRaw(profileName));
56 |
57 | function getConfig(name) = getConfigValue(profile, name);
58 |
59 | profile = getProfile(profileName);
60 |
61 | // Maximum width for rack-mount units. Change this according your max expected enclosure width.
62 | // Changing this will directly affect the required build volume.
63 | maxUnitWidth = getConfig("maxUnitWidth");
64 |
65 | // Maximum (recommended) unit depth. There technically isn't a max unit depth because there's no physical bound on
66 | // how far a rack unit can extrude back. This parameter basically controls the distance between the front of the front
67 | // rails and the back of the back rails. Changing this will directly affect the required build volume.
68 | maxUnitDepth = getConfig("maxUnitDepth");
69 |
70 | // Vertical distance between the midpoint of adjacent screws mounts. Affects build volume.
71 | screwDiff = getConfig("screwDiff");
72 |
73 | // Number screw slots on the main rail. Affects build volume.
74 | numRailScrews = getConfig("numRailScrews");
75 |
76 | // Screw type used for rackmount units. See screws.scad.
77 | mainRailScrewType = getConfig("mainRailScrewType");
78 |
79 | // Screw type used to affix side rails.
80 | mainRailSideMountScrewType = getConfig("mainRailSideMountScrewType");
81 |
82 | // Screw type used for constructing the actual rack frame.
83 | rackFrameScrewType = getConfig("rackFrameScrewType");
84 | // Currently, only m3 screws are supported here (tolerance issues)
85 | assert(rackFrameScrewType == "m3");
86 |
87 | // Fillet radius for main rack profile
88 | baseRoundness = getConfig("baseRoundness");
89 |
--------------------------------------------------------------------------------
/helper/apply.scad:
--------------------------------------------------------------------------------
1 | // Modules for apply pattern
2 |
3 | module apply_p() {
4 | union() {
5 | children(0);
6 | children(1);
7 | }
8 | }
9 |
10 | module apply_n() {
11 | difference() {
12 | children(1);
13 | children(0);
14 | }
15 | }
16 |
17 | module apply_pn() {
18 | difference() {
19 | union() {
20 | children(0);
21 | children(2);
22 | }
23 | children(1);
24 | }
25 | }
26 |
27 | module apply_np() {
28 | difference() {
29 | union() {
30 | children(1);
31 | children(2);
32 | }
33 | children(0);
34 | }
35 | }
--------------------------------------------------------------------------------
/helper/common.scad:
--------------------------------------------------------------------------------
1 | // Helper aggregator
2 |
3 | include <./apply.scad>
4 | include <./dovetail.scad>
5 | include <./filet.scad>
6 | include <./keystone1.scad>
7 | include <./keystone2.scad>
8 | include <./math.scad>
9 | include <./matrix.scad>
10 | include <./screws.scad>
11 | include <./sine.scad>
12 |
13 | $fn=64;
14 |
--------------------------------------------------------------------------------
/helper/dovetail.scad:
--------------------------------------------------------------------------------
1 | include <./math.scad>
2 |
3 | // centered on z axis
4 | module dovetail(
5 | topWidth,
6 | bottomWidth,
7 | height,
8 | length,
9 | headExtension=0,
10 | baseExtension=0,
11 | frontFaceLength = 0,
12 | frontFaceScale = 0,
13 | backFaceLength = 0,
14 | backFaceScale = 0,
15 | ) {
16 |
17 | translate(v=[0,0,frontFaceLength])
18 | linear_extrude(length-(frontFaceLength+backFaceLength))
19 | dovetailFace(topWidth,bottomWidth,height,headExtension,baseExtension);
20 |
21 | translate(v=[0,0,frontFaceLength])
22 | mirror(v=[0,0,1])
23 | linear_extrude(frontFaceLength, scale=[frontFaceScale, frontFaceScale])
24 | dovetailFace(topWidth,bottomWidth,height,headExtension,baseExtension);
25 |
26 | translate(v=[0,0,length-backFaceLength])
27 | linear_extrude(backFaceLength, scale=[backFaceScale,1])
28 | dovetailFace(topWidth,bottomWidth,height,headExtension,baseExtension);
29 |
30 |
31 |
32 | module dovetailFace(topWidth, bottomWidth, height, headExtension, baseExtension) {
33 |
34 | union() {
35 | // base
36 | polygon(points =
37 | [[-bottomWidth/2, 0],
38 | [-topWidth/2, height],
39 | [topWidth/2, height],
40 | [bottomWidth/2, 0]]
41 | );
42 |
43 | polygon(points =
44 | [[-bottomWidth/2, -baseExtension],
45 | [-bottomWidth/2,0 ],
46 | [bottomWidth/2, 0],
47 | [bottomWidth/2, -baseExtension]]
48 | );
49 |
50 | translate(v=[0,height])
51 | polygon(points =
52 | [[-topWidth/2, headExtension],
53 | [-topWidth/2,0 ],
54 | [topWidth/2, 0],
55 | [topWidth/2, headExtension]]
56 | );
57 | }
58 | }
59 |
60 |
61 | }
--------------------------------------------------------------------------------
/helper/filet.scad:
--------------------------------------------------------------------------------
1 | include <./math.scad>
2 |
3 | module sphericalFiletEdge(width, depth, height, roundness) {
4 | rd = roundness;
5 |
6 | intersection() {
7 | minkowski() {
8 | sphere(r = rd);
9 |
10 | translate(v = [rd, rd, rd])
11 | cube(size = [width*2, depth - 2*rd, height*2]);
12 | }
13 |
14 | cube(size = [width, depth, height]);
15 | }
16 | }
17 |
18 | module cylindricalFiletEdge(width, depth, height, roundness) {
19 | rd = roundness;
20 |
21 | intersection() {
22 | minkowski() {
23 | rotate(a = [90, 0, 0])
24 | cylinder(r = rd, h = eps);
25 |
26 | translate(v = [rd, 0, rd])
27 | cube(size = [width, depth, height]);
28 | }
29 |
30 | cube(size = [width, depth, height]);
31 | }
32 | }
33 |
34 | module cylindricalFiletNegative(p0, p1, n, r) {
35 | l = norm(p1-p0);
36 |
37 | alignTo(p0=p0, p1=p1, p2=p0-n)
38 | rotate(a=[45,0,0])
39 | rotate(a=[0,90,0])
40 | zFiletNegative(length = l, r = r);
41 | }
42 |
43 | module zFiletNegative(length, r) {
44 |
45 | p1 = [0,0,0];
46 | p2 = [0,0,length];
47 | n1 = [-1,-1,0] / norm([-1,-1,0]);
48 | dr = sqrt(2*r^2);
49 |
50 | difference() {
51 |
52 | hull() {
53 | translate(v=[0,0,0])
54 | cube(size=[r,r,r]);
55 |
56 | translate(v = p2-[0,0,0.1])
57 | cube(size=[r,r,0.1]);
58 |
59 | }
60 |
61 | hull() {
62 | translate(v = p1-n1*dr)
63 | cylinder(r = r, h=0.0001, $fn = 32);
64 |
65 |
66 | translate(v = p2-n1*dr)
67 | cylinder(r = r, h=0.0001, $fn = 32);
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/helper/keystone1.scad:
--------------------------------------------------------------------------------
1 | include <../config/common.scad>
2 |
3 | // rj45 slot-to-slot keystone jack model and negative
4 | keystoneMainBodyWidth = 15.0;
5 | keystoneMainBodyHeight = 16.90;
6 | keystoneMainBodyDepth = 32.90;
7 |
8 | heightWithHookBody = 20.2;
9 | heightWithHookCatch = 21.30;
10 | widthWithSideLugs = 15.96;
11 | sideLugWidth = (widthWithSideLugs - keystoneMainBodyWidth) / 2.0;
12 |
13 | heightWithBottomLug = 17.5;
14 |
15 | frontToHookCatch = 8.35;
16 | frontToBottomLugBack = 8.23;
17 | frontToSideLugFront = 10.63;
18 |
19 | module rj45Keystone() {
20 | // main keystone body (no hooks or lugs)
21 | cube(size=[keystoneMainBodyWidth + xySlack, keystoneMainBodyDepth + xySlack, keystoneMainBodyHeight]);
22 |
23 | // slot for top hook
24 | translate(v=[0,frontToHookCatch,0])
25 | cube(size=[keystoneMainBodyWidth + xySlack, keystoneMainBodyDepth-frontToHookCatch + xySlack, heightWithHookBody]);
26 |
27 | cube(size=[keystoneMainBodyWidth + xySlack, frontToHookCatch + xySlack, heightWithHookCatch]);
28 |
29 | // slots for side lugs
30 | translate(v=[-sideLugWidth, frontToSideLugFront,0])
31 | cube(size=[widthWithSideLugs + xySlack, keystoneMainBodyDepth-frontToSideLugFront + xySlack, keystoneMainBodyHeight]);
32 |
33 | // slots for bottom lugs
34 | translate(v=[0,0,-(heightWithBottomLug-keystoneMainBodyHeight)])
35 | cube(size=[keystoneMainBodyWidth + xySlack, frontToBottomLugBack + xySlack, keystoneMainBodyHeight]);
36 |
37 | }
38 |
39 | module rj45KeystoneJack_N() {
40 | translate(v=[0,-4,0.5]) // why?
41 | intersection() {
42 | translate(v=[-2.5,4,-4])
43 | cube(size=[20,6,28]);
44 | rj45Keystone();
45 | }
46 | }
47 |
48 | module keystone1(outerWidth, outerHeight) {
49 | rotate([0, 0, 180]) // To keep the same direction with keystone2
50 | difference() {
51 | translate([0, 0, 5.9 / 2])
52 | cube([outerWidth, outerHeight, 5.9], center = true);
53 |
54 | translate([-(keystoneMainBodyWidth + xySlack) / 2, (heightWithHookCatch + heightWithBottomLug - keystoneMainBodyHeight) / 2, 0])
55 | rotate([90, 0, 0])
56 | rj45KeystoneJack_N();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/helper/keystone2.scad:
--------------------------------------------------------------------------------
1 | include <../config/common.scad>
2 |
3 | // These all constants are obtained by measuring rj45 keystone modules
4 | // in hand. frontToRearDepth and rearPanelThickness are adjusted after testing.
5 | // Before printing the Patch Panel, print a keystone2(outerWidth = 19,
6 | // outerHeight = 27) to test if it fits.
7 | frontWidth = 14.5;
8 | frontHeight = 16.2;
9 |
10 | frontToRearDepth = 8.4;
11 |
12 | rearWidth = frontWidth;
13 | rearHeight = 19.55;
14 | rearPanelThickness = 2 - supportedOverhangSlack;
15 |
16 | maximumWidth = frontWidth;
17 | maximumHeight = 22.15;
18 |
19 | lugHeight = 1.3;
20 |
21 | module keystone2(plateThickness = 1, outerWidth, outerHeight) {
22 | assert(outerWidth > maximumWidth);
23 | assert(outerHeight > maximumHeight);
24 |
25 | difference() {
26 | // Outer cube
27 | translate([-outerWidth / 2, -outerHeight / 2, 0])
28 | cube([outerWidth, outerHeight, frontToRearDepth + rearPanelThickness]);
29 |
30 | // Front panel hole
31 | translate([-(frontWidth + xySlack) / 2, -(frontHeight + xySlack) / 2, 0])
32 | cube([frontWidth + xySlack, frontHeight + xySlack, plateThickness]);
33 |
34 | // Middle cavity
35 | translate([-(maximumWidth + xySlack) / 2, -frontHeight / 2 - lugHeight - xySlack / 2, plateThickness])
36 | cube([rearWidth + xySlack, outerHeight + 1000, frontToRearDepth - plateThickness]);
37 |
38 | // Rear panel hole
39 | translate([-(rearWidth + xySlack) / 2, -(frontHeight + xySlack) / 2, frontToRearDepth])
40 | cube([rearWidth + xySlack, rearHeight + xySlack, rearPanelThickness]);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/helper/math.scad:
--------------------------------------------------------------------------------
1 | // Some misc math-y utils
2 |
3 | $fn=64;
4 | eps=0.001;
5 | rh=1; // preview render helper :)
6 | inf10 = 10;
7 | inf50 = 50;
8 | inf1000 = 1000;
9 | inf = inf1000;
10 |
11 | function unit(v) = v/norm(v);
12 |
13 | function lerp(a, b, t) = (b * t + a * (1 - t));
14 |
15 | /* Example usage:
16 | for (i=mirror4XY(midpoint=[0,0,0], offsetX=90, offsetY=90))
17 | { translate(v=i) something(); }
18 | */
19 | module mirror4XY(p, dx, dy) {
20 |
21 | px = p[0];
22 | py = p[1];
23 |
24 | translate(v=[px, py, 0])
25 | children(0);
26 |
27 | translate(v=[px+dx, py, 0])
28 | children(0);
29 |
30 | translate(v=[px, py+dy, 0])
31 | children(0);
32 |
33 | translate(v=[px+dx, py+dy, 0])
34 | children(0);
35 | }
36 |
37 | /* Generate a 4x4 matrix that causes a change of basis
38 | such that the origin is at point p0, the x axis is aligned
39 | from p0 to p1 and point p2 is in the first quadrant.
40 | Copied and pasted from https://trmm.net/Basis/
41 | */
42 | module alignTo(p0,p1,p2) {
43 |
44 | x = unit(p1-p0);
45 | yp = unit(p2-p0);
46 | z = unit(cross(x,yp));
47 | y = unit(cross(z,x));
48 |
49 | multmatrix([
50 | [x[0], y[0], z[0], p0[0]],
51 | [x[1], y[1], z[1], p0[1]],
52 | [x[2], y[2], z[2], p0[2]],
53 | [ 0, 0, 0, 1]
54 | ])
55 | children();
56 | }
57 |
58 | module halfspace(vpos, p) {
59 |
60 | ref = [0,0,-1];
61 |
62 | if (cross(ref, vpos) == [0,0,0]) {
63 | translate(p)
64 | translate(v=[0,0, (ref*vpos) * -inf/2])
65 | cube(size=[inf, inf, inf], center=true);
66 | } else {
67 | translate(p)
68 | alignPlanar(a=ref, b = vpos)
69 | translate(v = [0, 0, -inf/2])
70 | cube(size = [inf, inf, inf], center = true);
71 | }
72 |
73 | }
74 |
75 | module alignPlanar(a,b) {
76 | rot_axis = cross(a,b);
77 | angle = acos(a*b/(norm(a)*norm(b)));
78 |
79 | rotate(v=rot_axis, a=angle)
80 | children(0);
81 | }
--------------------------------------------------------------------------------
/helper/matrix.scad:
--------------------------------------------------------------------------------
1 | // Common matrix transformations
2 |
3 | identity = [
4 | [1,0,0,0],
5 | [0,1,0,0],
6 | [0,0,1,0],
7 | [0,0,0,1],
8 | ];
9 |
10 | function scale(v) = [
11 | [v[0],0,0,0],
12 | [0,v[1],0,0],
13 | [0,0,v[2],0],
14 | [0,0,0,1]
15 | ];
16 |
17 | function rotatex(a) = [
18 | [1,0,0,0],
19 | [0,cos(a),-sin(a),0],
20 | [0,sin(a),cos(a),0],
21 | [0,0,0,1]
22 | ];
23 |
24 | function rotatey(a) = [
25 | [cos(a),0,sin(a),0],
26 | [0,1,0,0],
27 | [-sin(a),0,cos(a),0],
28 | [0,0,0,1]
29 | ];
30 |
31 | function rotatez(a) = [
32 | [cos(a),-sin(a),0,0],
33 | [sin(a),cos(a),0,0],
34 | [0,0,1,0],
35 | [0,0,0,1]
36 | ];
37 |
38 | function rotate(a,v) =
39 | (v == undef)
40 | ? rotatez(a[2])*rotatey(a[1])*rotatex(a[0])
41 | : rotateanv(a,v/sqrt(v*v));
42 |
43 | function translate(v) = [
44 | [1,0,0,v[0]],
45 | [0,1,0,v[1]],
46 | [0,0,1,v[2]],
47 | [0,0,0,1]
48 | ];
49 |
50 | function mirrorabc(a,b,c) = [
51 | [1-2*a*a,-2*a*b,-2*a*c,0],
52 | [-2*a*b,1-2*b*b,-2*b*c,0],
53 | [-2*a*c,-2*b*c,1-2*c*c,0],
54 | [0,0,0,1]
55 | ];
56 |
57 | function mirrornv(nv) = mirrorabc(nv[0],nv[1],nv[2]);
58 |
59 | function mirror(v) = mirrornv(v/sqrt(v*v));
60 |
61 |
62 | // taken from https://github.com/openscad/openscad/issues/1040#issuecomment-233208606
63 | function det4x4(a) =
64 | a[0][0]*a[1][1]*a[2][2]*a[3][3] + a[0][0]*a[1][2]*a[2][3]*a[3][1] + a[0][0]*a[1][3]*a[2][1]*a[3][2]
65 | + a[0][1]*a[1][0]*a[2][3]*a[3][2] + a[0][1]*a[1][2]*a[2][0]*a[3][3] + a[0][1]*a[1][3]*a[2][2]*a[3][0]
66 | + a[0][2]*a[1][0]*a[2][1]*a[3][3] + a[0][2]*a[1][1]*a[2][3]*a[3][0] + a[0][2]*a[1][3]*a[2][0]*a[3][1]
67 | + a[0][3]*a[1][0]*a[2][2]*a[3][1] + a[0][3]*a[1][1]*a[2][0]*a[3][2] + a[0][3]*a[1][2]*a[2][1]*a[3][0]
68 | - a[0][0]*a[1][1]*a[2][3]*a[3][2] - a[0][0]*a[1][2]*a[2][1]*a[3][3] - a[0][0]*a[1][3]*a[2][2]*a[3][1]
69 | - a[0][1]*a[1][0]*a[2][2]*a[3][3] - a[0][1]*a[1][2]*a[2][3]*a[3][0] - a[0][1]*a[1][3]*a[2][0]*a[3][2]
70 | - a[0][2]*a[1][0]*a[2][3]*a[3][1] - a[0][2]*a[1][1]*a[2][0]*a[3][3] - a[0][2]*a[1][3]*a[2][1]*a[3][0]
71 | - a[0][3]*a[1][0]*a[2][1]*a[3][2] - a[0][3]*a[1][1]*a[2][2]*a[3][0] - a[0][3]*a[1][2]*a[2][0]*a[3][1];
72 |
73 | function invb00(a) = a[1][1]*a[2][2]*a[3][3] + a[1][2]*a[2][3]*a[3][1] + a[1][3]*a[2][1]*a[3][2] - a[1][1]*a[2][3]*a[3][2] - a[1][2]*a[2][1]*a[3][3] - a[1][3]*a[2][2]*a[3][1];
74 |
75 | function invb01(a) = a[0][1]*a[2][3]*a[3][2] + a[0][2]*a[2][1]*a[3][3] + a[0][3]*a[2][2]*a[3][1] - a[0][1]*a[2][2]*a[3][3] - a[0][2]*a[2][3]*a[3][1] - a[0][3]*a[2][1]*a[3][2];
76 |
77 | function invb02(a) = a[0][1]*a[1][2]*a[3][3] + a[0][2]*a[1][3]*a[3][1] + a[0][3]*a[1][1]*a[3][2] - a[0][1]*a[1][3]*a[3][2] - a[0][2]*a[1][1]*a[3][3] - a[0][3]*a[1][2]*a[3][1];
78 |
79 | function invb03(a) = a[0][1]*a[1][3]*a[2][2] + a[0][2]*a[1][1]*a[2][3] + a[0][3]*a[1][2]*a[2][1] - a[0][1]*a[1][2]*a[2][3] - a[0][2]*a[1][3]*a[2][1] - a[0][3]*a[1][1]*a[2][2];
80 |
81 | function invb10(a) = a[1][0]*a[2][3]*a[3][2] + a[1][2]*a[2][0]*a[3][3] + a[1][3]*a[2][2]*a[3][0] - a[1][0]*a[2][2]*a[3][3] - a[1][2]*a[2][3]*a[3][0] - a[1][3]*a[2][0]*a[3][2];
82 |
83 | function invb11(a) = a[0][0]*a[2][2]*a[3][3] + a[0][2]*a[2][3]*a[3][0] + a[0][3]*a[2][0]*a[3][2] - a[0][0]*a[2][3]*a[3][2] - a[0][2]*a[2][0]*a[3][3] - a[0][3]*a[2][2]*a[3][0];
84 |
85 | function invb12(a) = a[0][0]*a[1][3]*a[3][2] + a[0][2]*a[1][0]*a[3][3] + a[0][3]*a[1][2]*a[3][0] - a[0][0]*a[1][2]*a[3][3] - a[0][2]*a[1][3]*a[3][0] - a[0][3]*a[1][0]*a[3][2];
86 |
87 | function invb13(a) = a[0][0]*a[1][2]*a[2][3] + a[0][2]*a[1][3]*a[2][0] + a[0][3]*a[1][0]*a[2][2] - a[0][0]*a[1][3]*a[2][2] - a[0][2]*a[1][0]*a[2][3] - a[0][3]*a[1][2]*a[2][0];
88 |
89 | function invb20(a) = a[1][0]*a[2][1]*a[3][3] + a[1][1]*a[2][3]*a[3][0] + a[1][3]*a[2][0]*a[3][1] - a[1][0]*a[2][3]*a[3][1] - a[1][1]*a[2][0]*a[3][3] - a[1][3]*a[2][1]*a[3][0];
90 |
91 | function invb21(a) = a[0][0]*a[2][3]*a[3][1] + a[0][1]*a[2][0]*a[3][3] + a[0][3]*a[2][1]*a[3][0] - a[0][0]*a[2][1]*a[3][3] - a[0][1]*a[2][3]*a[3][0] - a[0][3]*a[2][0]*a[3][1];
92 |
93 | function invb22(a) = a[0][0]*a[1][1]*a[3][3] + a[0][1]*a[1][3]*a[3][0] + a[0][3]*a[1][0]*a[3][1] - a[0][0]*a[1][3]*a[3][1] - a[0][1]*a[1][0]*a[3][3] - a[0][3]*a[1][1]*a[3][0];
94 |
95 | function invb23(a) = a[0][0]*a[1][3]*a[2][1] + a[0][1]*a[1][0]*a[2][3] + a[0][3]*a[1][1]*a[2][0] - a[0][0]*a[1][1]*a[2][3] - a[0][1]*a[1][3]*a[2][0] - a[0][3]*a[1][0]*a[2][1];
96 |
97 | function invb30(a) = a[1][0]*a[2][2]*a[3][1] + a[1][1]*a[2][0]*a[3][2] + a[1][2]*a[2][1]*a[3][0] - a[1][0]*a[2][1]*a[3][2] - a[1][1]*a[2][2]*a[3][0] - a[1][2]*a[2][0]*a[3][1];
98 |
99 | function invb31(a) = a[0][0]*a[2][1]*a[3][2] + a[0][1]*a[2][2]*a[3][0] + a[0][2]*a[2][0]*a[3][1] - a[0][0]*a[2][2]*a[3][1] - a[0][1]*a[2][0]*a[3][2] - a[0][2]*a[2][1]*a[3][0];
100 |
101 | function invb32(a) = a[0][0]*a[1][2]*a[3][1] + a[0][1]*a[1][0]*a[3][2] + a[0][2]*a[1][1]*a[3][0] - a[0][0]*a[1][1]*a[3][2] - a[0][1]*a[1][2]*a[3][0] - a[0][2]*a[1][0]*a[3][1];
102 |
103 | function invb33(a) = a[0][0]*a[1][1]*a[2][2] + a[0][1]*a[1][2]*a[2][0] + a[0][2]*a[1][0]*a[2][1] - a[0][0]*a[1][2]*a[2][1] - a[0][1]*a[1][0]*a[2][2] - a[0][2]*a[1][1]*a[2][0];
104 |
105 | function inv4x4(a)= (1/det4x4(a))*[
106 | [invb00(a),invb01(a),invb02(a),invb03(a)],
107 | [invb10(a),invb11(a),invb12(a),invb13(a)],
108 | [invb20(a),invb21(a),invb22(a),invb23(a)],
109 | [invb30(a),invb31(a),invb32(a),invb33(a)]];
110 |
111 |
--------------------------------------------------------------------------------
/helper/screws.scad:
--------------------------------------------------------------------------------
1 | /* Some common screw dimensions and helper functions/modules */
2 |
3 | include <../config/common.scad>
4 | include <./math.scad>
5 |
6 | /********************************************************************************/
7 | // M3 dimensions
8 | m3HoleRadiusSlack = radiusXYSlack;
9 | m3Diameter = 3.0;
10 | m3Radius = m3Diameter / 2.0;
11 | m3RadiusSlacked = m3Radius + m3HoleRadiusSlack;
12 |
13 | m3CounterSunkHeadRadius = 3;
14 | m3CounterSunkHeadLength = 1.7;
15 |
16 | m3HexNutWidthAcrossFlats = 5.41;
17 | m3HexNutWidthAcrossCorners = FtoG(m3HexNutWidthAcrossFlats);
18 | m3HexNutThickness = 2.2;
19 |
20 | /********************************************************************************/
21 | // M4 dimensions
22 | m4HoleRadiusSlack = radiusXYSlack;
23 | m4Diameter = 4.0;
24 | m4Radius = m4Diameter / 2.0;
25 | m4RadiusSlacked = m4Radius + m4HoleRadiusSlack;
26 |
27 | m4CounterSunkHeadRadius = 4;
28 | m4CounterSunkHeadLength = 2.3;
29 |
30 | m4HexNutWidthAcrossFlats = 6.89;
31 | m4HexNutWidthAcrossCorners = FtoG(m4HexNutWidthAcrossFlats);
32 | m4HexNutThickness = 3.07;
33 |
34 | /********************************************************************************/
35 |
36 | function screwRadiusSlacked(screwType) =
37 | (screwType == "m3")
38 | ? m3RadiusSlacked
39 | : (screwType == "m4")
40 | ? m4RadiusSlacked
41 | : error("Unsupported screw type");
42 |
43 | function hexNutThickness(screwType) =
44 | (screwType == "m3")
45 | ? m3HexNutThickness
46 | : (screwType == "m4")
47 | ? m4HexNutThickness
48 | : error("Unsupported screw type");
49 |
50 |
51 | module counterSunkHead_N(screwType, screwExtension=0, headExtension=0) {
52 |
53 | if (screwType == "m3") {
54 | translate(v = [0, 0, -m3CounterSunkHeadLength])
55 | union() {
56 | cylinder(r1 = m3RadiusSlacked, r2 = m3CounterSunkHeadRadius, h = m3CounterSunkHeadLength);
57 |
58 | translate(v = [0, 0, -screwExtension])
59 | cylinder(r = m3RadiusSlacked, h = screwExtension);
60 |
61 | translate(v = [0, 0, m3CounterSunkHeadLength])
62 | cylinder(r = m3CounterSunkHeadRadius, h = headExtension);
63 | }
64 | } else if (screwType == "m4") {
65 | translate(v = [0, 0, -m4CounterSunkHeadLength])
66 | union() {
67 | cylinder(r1 = m4RadiusSlacked, r2 = m4CounterSunkHeadRadius, h = m4CounterSunkHeadLength);
68 |
69 | translate(v = [0, 0, -screwExtension])
70 | cylinder(r = m4RadiusSlacked, h = screwExtension);
71 |
72 | translate(v = [0, 0, m4CounterSunkHeadLength])
73 | cylinder(r = m4CounterSunkHeadRadius, h = headExtension);
74 | }
75 | } else {
76 | error("Unsupported screw type");
77 | }
78 | }
79 |
80 | module hexNut(screwType, center=true) {
81 | color([1, 1, 1])
82 | if (screwType == "m3") {
83 | translate(v = [0, 0,-m3HexNutThickness/2])
84 | difference() {
85 | cylinder(r=m3HexNutWidthAcrossCorners/2, h=m3HexNutThickness, $fn=6);
86 | cylinder(r=m3Radius,h=inf10, center=true);
87 | }
88 | } else if (screwType == "m4") {
89 | translate(v = [0, 0,-m4HexNutThickness/2])
90 | difference() {
91 | cylinder(r=m4HexNutWidthAcrossCorners/2, h=m4HexNutThickness, $fn=6);
92 | cylinder(r=m4Radius,h=inf10, center=true);
93 | }
94 | } else {
95 | error("Unsupported screw type");
96 | }
97 | }
98 |
99 | module hexNutPocket_N(screwType, openSide=true, backSpace=inf10, bridgeFront=false, bridgeBack=false ) {
100 |
101 | heightSlack = bridgeFront || bridgeBack ? overhangSlack: xySlack;
102 |
103 | if (screwType == "m3") {
104 | hexNutPocketHelper_N(m3RadiusSlacked, (m3HexNutWidthAcrossCorners+xySlack) / 2, m3HexNutThickness + heightSlack, openSide=openSide, backSpace=backSpace, bridgeFront=bridgeFront, bridgeBack=bridgeBack);
105 | } else if (screwType == "m4") {
106 | hexNutPocketHelper_N(m4RadiusSlacked, (m4HexNutWidthAcrossCorners+xySlack) / 2, m4HexNutThickness + heightSlack, openSide=openSide, backSpace=backSpace, bridgeFront=bridgeFront, bridgeBack=bridgeBack);
107 | } else {
108 | error("Unsupported screw type");
109 | }
110 | }
111 |
112 | module hexNutPocketHelper_N(innerRadius, widthAcrossCorners, thickness, openSide=true, backSpace=inf10, bridgeFront=false, bridgeBack=false) {
113 |
114 | assert (!(bridgeFront && bridgeBack));
115 | assert (!(openSide && bridgeFront));
116 |
117 | union() {
118 | hull() {
119 | // hexagonal prism representing where the nut should fit
120 | cylinder(r = widthAcrossCorners, h = thickness, center = true, $fn = 6);
121 |
122 | // negative volume for sliding in the nut
123 | translate(v = [inf50, 0, 0])
124 | cylinder(r = widthAcrossCorners, h = thickness, center = true, $fn = 6);
125 | }
126 |
127 | // negative volume for screw
128 | union() {
129 | // screw lead spacing
130 | translate(v = [0, 0, -backSpace])
131 | cylinder(r = innerRadius, h = backSpace, $fn = 32);
132 |
133 | cylinder(r=innerRadius, h=inf50, $fn=32);
134 |
135 | if (bridgeFront) {
136 | union() {
137 | // first bridge layer
138 | translate(v=[0,0,thickness/2 + defaultLayerHeight/2])
139 | cube(size=[2*innerRadius, GtoF(widthAcrossCorners)*2, defaultLayerHeight], center=true);
140 | // second bridge layer
141 | translate(v=[0,0,thickness/2 + defaultLayerHeight])
142 | cube(size=[2*innerRadius, 2*innerRadius, defaultLayerHeight], center=true);
143 | }
144 | }
145 |
146 | if (bridgeBack) {
147 | union() {
148 | // first bridge layer
149 | translate(v=[0,0,-(thickness/2 + defaultLayerHeight/2)])
150 | cube(size=[2*innerRadius, GtoF(widthAcrossCorners)*2, defaultLayerHeight], center=true);
151 | // second bridge layer
152 | translate(v=[0,0,-(thickness/2 + defaultLayerHeight)])
153 | cube(size=[2*innerRadius, 2*innerRadius, defaultLayerHeight], center=true);
154 | }
155 | }
156 | }
157 |
158 | if (openSide) {
159 | hull() {
160 | translate(v = [inf50, 0, 0])
161 | cylinder(r = innerRadius, h = inf50, $fn = 32);
162 | cylinder(r = innerRadius, h = inf50, $fn = 32);
163 | }
164 | }
165 | }
166 | }
167 |
168 | // Convert a regular hexagon widthAcrossFlats to widthAcrossCorners
169 | function FtoG(widthAcrossFlats) = widthAcrossFlats * (2 / sqrt(3));
170 |
171 | // Convert a regular hexagon widthAcrossCorners to widthAcrossFlats
172 | function GtoF(widthAcrossCorners) = widthAcrossCorners * (sqrt(3) / 2);
173 |
--------------------------------------------------------------------------------
/helper/sine.scad:
--------------------------------------------------------------------------------
1 |
2 | length = 100;
3 | resolution = 128;
4 | amplitude = 4.0;
5 | period = PI;
6 | shift = 0.0;
7 |
8 | function radToDeg(r) = r * (180 / PI);
9 | function sinR(r) = sin(radToDeg(r));
10 |
11 |
12 | //sigmoid = function(x) exp(x) / (exp(x) + 1);
13 | //dsigmoid = function(x) sigmoid(x) * (1-sigmoid(x));
14 | //amplitudeFunction = function(x) 5*dsigmoid(x - 3) + 1;
15 | amplitudeFunction = function(x) 1;
16 |
17 | module sineWave(length, resolution, amplitudeFunction, period, shift) {
18 | dx = length / resolution;
19 | p = period / (2*PI);
20 |
21 | for (i = [1:resolution]) {
22 | idx_prev = (i - 1) * dx;
23 | idx_curr = i * dx;
24 | hull() {
25 | translate(v = [idx_prev, amplitudeFunction(idx_prev) * sinR(p * idx_prev + shift), 0])
26 | cube(size = [0.1, 2, 2]);
27 |
28 | translate(v = [idx_curr, amplitudeFunction(idx_curr) * sinR(p * idx_curr + shift), 0])
29 | cube(size = [0.1, 2, 2]);
30 |
31 | translate(v = [idx_curr, -10, 0])
32 | cube(size=[0.1,2,2]);
33 | translate(v = [idx_prev, -10, 0])
34 | cube(size=[0.1,2,2]);
35 | }
36 | }
37 | }
38 |
39 | module sineWaveHull(length, resolution, amplitudeFunction, period, shift, hullDiff) {
40 | dx = length / resolution;
41 | p = period / (2*PI);
42 |
43 | for (i = [1:resolution]) {
44 | idx_prev = (i - 1) * dx;
45 | idx_curr = i * dx;
46 | hull() {
47 | translate(v = [idx_prev, amplitudeFunction(idx_prev) * sinR(p * idx_prev + shift), 0])
48 | cube(size = [0.1, 2, 2]);
49 |
50 | translate(v = [idx_curr, amplitudeFunction(idx_curr) * sinR(p * idx_curr + shift), 0])
51 | cube(size = [0.1, 2, 2]);
52 |
53 | translate(v = [idx_curr, -hullDiff, 0])
54 | cube(size=[0.1,2,2]);
55 | translate(v = [idx_prev, -hullDiff, 0])
56 | cube(size=[0.1,2,2]);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/media/bom/dowel.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/bom/dowel.gif
--------------------------------------------------------------------------------
/media/bom/fhcs_long.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/bom/fhcs_long.gif
--------------------------------------------------------------------------------
/media/bom/fhcs_medium.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/bom/fhcs_medium.gif
--------------------------------------------------------------------------------
/media/bom/fhcs_short.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/bom/fhcs_short.gif
--------------------------------------------------------------------------------
/media/bom/glue.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/bom/glue.gif
--------------------------------------------------------------------------------
/media/bom/hex_nut.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/bom/hex_nut.gif
--------------------------------------------------------------------------------
/media/bom/magnet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/bom/magnet.gif
--------------------------------------------------------------------------------
/media/features/slideOpt.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/features/slideOpt.gif
--------------------------------------------------------------------------------
/media/features/stackConnectorOpt.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/features/stackConnectorOpt.gif
--------------------------------------------------------------------------------
/media/features/swivelOpt.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/features/swivelOpt.gif
--------------------------------------------------------------------------------
/media/renders/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/renders/output.png
--------------------------------------------------------------------------------
/media/renders/rackDisplayRounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/media/renders/rackDisplayRounded.png
--------------------------------------------------------------------------------
/misc/animate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # simple bash script to animate the frame dump from openscad
3 |
4 | name="anim"
5 | png_dir="./assembly-guide/gifs/tmp"
6 | target_dir="./assembly-guide/gifs"
7 |
8 | if [ -n "$1" ]; then
9 | name="$1"
10 | fi
11 |
12 | if [ -n "$2" ]; then
13 | png_dir="$2"
14 | fi
15 |
16 | if [ -n "$3" ]; then
17 | target_dir="$3"
18 | fi
19 |
20 | filename_without_extension="${name%.*}"
21 |
22 | # needs tomorrow night openscad theme
23 | # convert -resize 20% -delay 6 -loop 0 -transparent "#1d1f21" -dispose previous frame000*.png "$filename_without_extension".gif
24 |
25 | convert -delay 6 -loop 0 -dispose previous "$png_dir"/"$filename_without_extension"000*.png "$target_dir"/"$filename_without_extension".gif
26 |
27 | #gifsicle -O3 --colors=64 --scale 0.5 -i "$target_dir"/"$filename_without_extension".gif -o "$target_dir"/"$filename_without_extension".gif
28 | gifsicle -O3 --colors=64 --no-warnings --scale 0.5 -i "$target_dir"/"$filename_without_extension".gif -o "$target_dir"/"$filename_without_extension".gif
--------------------------------------------------------------------------------
/misc/bomAnimations.scad:
--------------------------------------------------------------------------------
1 | include <../helper/screws.scad>
2 | include <../helper/magnet.scad>
3 | include <../helper/dowel.scad>
4 |
5 | $vpr=[85,0,25];
6 | //$vpd=40;
7 | $vpd=30;
8 | //$vpd=25;
9 | $vpf=20;
10 |
11 |
12 | glue(tilt=15,r=360*$t);
13 | //m3FHCS(length=8,tilt=45,r=360*$t);
14 | // magnet(tilt=90, r=360*$t);
15 | // hingeDowel(tilt=90,r=360*$t);
16 | // m3Hex(tilt=90,r=360*$t);
17 |
18 | metalColor = [0.8,0.8,0.8];
19 |
20 | module m3FHCS(length, tilt, r) {
21 | rotate(a=[0,0,r])
22 | rotate(a=[tilt,0,0])
23 | translate(v=[0,0,length/2])
24 | color(metalColor) {
25 | difference() {
26 | counterSunkHead_N("m3", screwExtension = length-m3CounterSunkHeadLength, headExtension = 0.5);
27 | cylinder($fn = 6, r = 1.2);
28 | }
29 | }
30 | }
31 |
32 | module m3Hex(tilt, r) {
33 |
34 | rotate(a=[0,0,r])
35 | rotate(a=[tilt,0,0])
36 | color(metalColor)
37 | hexNut("m3");
38 | }
39 |
40 | module hingeDowel(tilt, r) {
41 | rotate(a=[0,0,r])
42 | rotate(a=[tilt,0,0])
43 | translate(v=[0,0,-dowelPinH/2])
44 | color(metalColor)
45 | cylinder(h = dowelPinH, r = dowelPinR);
46 | }
47 |
48 |
49 | module magnet(tilt, r) {
50 | rotate(a=[0,0,r])
51 | rotate(a=[tilt,0,0])
52 | translate(v=[0,0,-magnetH/2])
53 | color(metalColor)
54 | cylinder(r = magnetR, h = magnetH);
55 | }
56 |
57 | module glue(tilt,r) {
58 |
59 | rotate(a=[0,0,r])
60 | rotate(a=[0,tilt,0])
61 |
62 | union() {
63 | // cap
64 | color([0.3,0.3,1])
65 | translate(v = [0, 0, 4])
66 | union() {
67 | cylinder(r1 = 0.8, r2 = 0.6, h = 2);
68 |
69 | gills = 8;
70 | for (i = [0:gills]) {
71 | translate(v = [0, 0, -0.1])
72 | rotate(a = [0, 0, 360/gills*i])
73 | rotate(a = [0, -6.5, 0])
74 | cube(size = [0.9, 0.1, 2]);
75 | }
76 | }
77 |
78 | // body
79 | color([0.9,0.5,0.1])
80 | hull() {
81 | translate(v = [0, 0, 4])
82 | cylinder(r = 0.4, h = 0.1);
83 |
84 | translate(v = [0, 0, 3])
85 | scale(v = [1.2, 1, 1])
86 | cylinder(r = 1, h = 0.1);
87 |
88 | scale(v = [1.5, 1, 1])
89 | cylinder(r = 1, h = 0.1);
90 | translate(v = [0, 0, -3])
91 | cube(size = [4, 0.2, 0.1], center = true);
92 | }
93 | }
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/rack-mount/angle-bracket/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Angle Bracket System
3 |
4 |
5 | 
6 |
7 | Please see [entry.scad](./entry.scad) for config and building. Make sure the correct rack profile is configured in [rackFrame.scad](../../config/rackFrame.scad).
8 |
9 | ### BOM:
10 |
11 | | Item | Name | Quantity | Comment |
12 | |---------------------------------------------------------------|---------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------|
13 | |
| M3x12 FHCS | 8 | Extras are useful and inexpensive. If you plan on eventually stacking multiple racks together, don't hesitate to get a lot more. |
14 | |
| M3 hex nut | 8 | ☝️ |
--------------------------------------------------------------------------------
/rack-mount/angle-bracket/animate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/rack-mount/angle-bracket/animate.gif
--------------------------------------------------------------------------------
/rack-mount/angle-bracket/animate.scad:
--------------------------------------------------------------------------------
1 | use <./entry.scad>
2 |
3 | $vpt = [120,-30,63];
4 | $vpr = [74,0,25];
5 | $vpd = 550;
6 | $vpf = 22.50;
7 |
8 | animateAngleBrackets(at=$t);
9 |
10 |
11 | module animateAngleBrackets(at=$t) {
12 |
13 | x = 150;
14 | y = 70;
15 | dx = abs(lerp(a=-20, b=20, t=at));
16 | dy = abs(lerp(a=-50, b=50, t=at));
17 |
18 | u = abs(at - 0.5) > 0.25 ? 3 : 4;
19 |
20 | angleBrackets(visualize=true, boxWidth=x+dx, boxDepth=y+dy, u=u);
21 |
22 | }
23 |
24 |
25 |
--------------------------------------------------------------------------------
/rack-mount/angle-bracket/entry.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 |
3 | use <../enclosed-box/sideRail.scad>
4 |
5 |
6 | /*
7 | Simple angle bracket mounting system. Mainly derived the enclosed box system.
8 | */
9 | module angleBrackets (
10 | // begin config ////////////////////////////////////////////////////////////////////////////////////////////////////////
11 |
12 | // Does not affect any part dimensions. Set this to true to visualize how a box would be mounted.
13 | visualize = false,
14 |
15 |
16 | thickness = 3,
17 | boxWidth = 160,
18 | boxDepth = 120,
19 | sideVent = false,
20 | u = 3
21 |
22 | // end config //////////////////////////////////////////////////////////////////////////////////////////////////////////
23 | ) {
24 |
25 | sideSupportRailBase(top=false, defaultThickness=thickness, railSideThickness=thickness, supportedZ=10*u-2*thickness, supportedY=boxDepth, supportedX=boxWidth, sideVent=sideVent);
26 |
27 | rightRailTrans = visualize
28 | ? translate(v=[boxWidth,0,0]) * mirror(v=[1,0,0])
29 | : translate(v=[30,0,0]) * mirror(v=[1,0,0]);
30 |
31 | multmatrix(rightRailTrans)
32 | sideSupportRailBase(top=false, defaultThickness=thickness, railSideThickness=thickness, supportedZ=10*u-2*thickness, supportedY=boxDepth, supportedX=boxWidth, sideVent=sideVent);
33 | }
34 |
35 |
36 | angleBrackets();
37 |
--------------------------------------------------------------------------------
/rack-mount/catalog/120mm-Rear-Case-Fan.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a 120mm Case Fan.
5 | Not compatible with nano rack configuration.
6 | Designed to be mounted on the back in a reverse position, with the fan sitting on the outside of the case rather than the inside.
7 | Mesh Screens are advised on the fore and aft of the fan.
8 | Powered by USB to 3 or 2-pin connectors.
9 | MINIMUM HEIGHT IS 13 TOTAL U's, which is showcased as u = 12 in rackstack.
10 |
11 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
12 | */
13 |
14 |
15 | difference () {
16 | bottomScrewTray (
17 | u = 12,
18 | trayWidth = 130,
19 | trayDepth = 35,
20 | trayThickness = 3,
21 | frontLipHeight = 126,
22 | backLipHeight = 126,
23 | // mountPoints = [[15, 15], [15+105, 15],[15, 15+105], [15+105, 15+105]],
24 | frontThickness = 3,
25 | sideThickness = 3,
26 | mountPointElevation = 1,
27 | mountPointType = "m4",
28 | sideSupport = true,
29 | trayLeftPadding = 25
30 | );
31 |
32 | translate (v=[-5,10,-5])
33 | rotate (a=[90,0,0]) {
34 | // Center Cutout
35 | translate(v=[67.5, 67.5, -25])
36 | rotate(a=[90,0,0])
37 | rotate(a=[0,90,90])
38 | cylinder(h=60, r1=60, r2=60, $fn=75);
39 |
40 | // fan screw hole 1
41 | translate(v=[15, 15, -25])
42 | rotate(a=[90,0,0])
43 | rotate(a=[0,90,90])
44 | cylinder(h=65, r1=2.5, r2=2.5, $fn=25);
45 |
46 | // fan screw hole 2
47 | translate(v=[15+105, 15, -25])
48 | rotate(a=[90,0,0])
49 | rotate(a=[0,90,90])
50 | cylinder(h=45, r1=2.5, r2=2.5, $fn=25);
51 |
52 | // fan screw hole 3
53 | translate(v=[15+105, 15+105, -25])
54 | rotate(a=[90,0,0])
55 | rotate(a=[0,90,90])
56 | cylinder(h=65, r1=2.5, r2=2.5, $fn=25);
57 |
58 | // fan screw hole 4
59 | translate(v=[15, 15+105, -25])
60 | rotate(a=[90,0,0])
61 | rotate(a=[0,90,90])
62 | cylinder(h=65, r1=2.5, r2=2.5, $fn=25);
63 | }
64 | }
--------------------------------------------------------------------------------
/rack-mount/catalog/120mm-fan-tray_mod.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a 120mm Case Fan.
5 | Not compatible with nano rack configuration.
6 |
7 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
8 | */
9 |
10 |
11 | difference () {
12 | bottomScrewTray (
13 | u = 2,
14 | trayWidth = 140,
15 | trayDepth = 140,
16 | trayThickness = 3,
17 | frontLipHeight = 26,
18 | backLipHeight = 6,
19 | mountPoints = [[15, 15], [15+105, 15],[15, 15+105], [15+105, 15+105]],
20 | frontThickness = 3,
21 | sideThickness = 3,
22 | mountPointElevation = 1,
23 | mountPointType = "m4",
24 | sideSupport = true,
25 | trayLeftPadding = 15
26 | );
27 |
28 | // Center Cutout
29 | translate(v=[67.5, 67.5, -50])
30 | rotate(a=[90,0,0])
31 | rotate(a=[0,90,90])
32 | cylinder(h=60, r1=60, r2=60, $fn=75);
33 |
34 | // fan screw hole 1
35 | translate(v=[15, 15, -5])
36 | rotate(a=[90,0,0])
37 | rotate(a=[0,90,90])
38 | cylinder(h=15.5, r1=2.5, r2=2.5, $fn=25);
39 |
40 | // fan screw hole 2
41 | translate(v=[15+105, 15, -5])
42 | rotate(a=[90,0,0])
43 | rotate(a=[0,90,90])
44 | cylinder(h=15.5, r1=2.5, r2=2.5, $fn=25);
45 |
46 | // fan screw hole 3
47 | translate(v=[15+105, 15+105, -5])
48 | rotate(a=[90,0,0])
49 | rotate(a=[0,90,90])
50 | cylinder(h=15.5, r1=2.5, r2=2.5, $fn=25);
51 |
52 | // fan screw hole 4
53 | translate(v=[15, 15+105, -5])
54 | rotate(a=[90,0,0])
55 | rotate(a=[0,90,90])
56 | cylinder(h=15.5, r1=2.5, r2=2.5, $fn=25);
57 | }
--------------------------------------------------------------------------------
/rack-mount/catalog/LG_Slim_DVD_Tray.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a LG Slim Portable DVD Writer.
5 |
6 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
7 |
8 | Remember to use Velcro strips to secure the drive to the tray!
9 | */
10 |
11 | bottomScrewTray (
12 | u = 1,
13 | trayWidth = 150,
14 | trayDepth = 145,
15 | trayThickness = 3,
16 | frontLipHeight = 0,
17 | backLipHeight = 0,
18 | // mountPoints = [[27.5, 34], [107, 34]],
19 | frontThickness = 3,
20 | sideThickness = 3,
21 | mountPointElevation = 1,
22 | mountPointType = "m3",
23 | sideSupport = true,
24 | trayLeftPadding = 15
25 | );
26 |
--------------------------------------------------------------------------------
/rack-mount/catalog/Minisforum_NAB9-tray_mod.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a MinisForum NAB9 mini PC.
5 | Not compatible with nano rack configuration.
6 |
7 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
8 | */
9 |
10 | difference () {
11 | bottomScrewTray (
12 | u = 5,
13 | trayWidth = 140,
14 | trayDepth = 140,
15 | trayThickness = 3,
16 | frontLipHeight = 3,
17 | backLipHeight = 5,
18 | mountPoints = [[20, 70], [20+95.25, 70]],
19 | frontThickness = 3,
20 | sideThickness = 3,
21 | mountPointElevation = 1,
22 | mountPointType = "m4",
23 | sideSupport = true,
24 | trayLeftPadding = 15
25 | );
26 |
27 | // Side perforations for airflow
28 | translate(v=[-4, 5, 18]) {
29 | rotate(a=[0,90,0])
30 | rotate(a=[0,0,45])
31 | cube(size=[18, 18, 155]);
32 |
33 | translate(v=[0, 28, -04])
34 | rotate(a=[0,90,0])
35 | rotate(a=[0,0,45])
36 | cube(size=[12,12,150]);
37 |
38 | translate(v=[0, 48, -06.5])
39 | rotate(a=[0,90,0])
40 | rotate(a=[0,0,45])
41 | cube(size=[8,8,150]);
42 |
43 |
44 | // Bottom perforations for airflow
45 | // Front Right Cube
46 | translate(v=[60, 40, -50])
47 | rotate(a=[90,0,0])
48 | rotate(a=[0,90,90])
49 | cube(size=[12,12,135]);
50 |
51 | // Front Center Cube
52 | translate(v=[80, 35, -50])
53 | rotate(a=[90,0,45])
54 | rotate(a=[0,90,90])
55 | cube(size=[12,12,135]);
56 |
57 | // Front Left Cube
58 | translate(v=[95, 40, -50])
59 | rotate(a=[90,0,0])
60 | rotate(a=[0,90,90])
61 | cube(size=[12,12,135]);
62 |
63 | // Center Right Cube
64 | translate(v=[50.5, 65, -50])
65 | rotate(a=[90,0,45])
66 | rotate(a=[0,90,90])
67 | cube(size=[12,12,135]);
68 |
69 | // Center Left Cube
70 | translate(v=[110, 65, -50])
71 | rotate(a=[90,0,45])
72 | rotate(a=[0,90,90])
73 | cube(size=[12,12,135]);
74 |
75 | // Rear Left Cube
76 | translate(v=[60, 75, -50])
77 | rotate(a=[90,0,0])
78 | rotate(a=[0,90,90])
79 | cube(size=[12,12,135]);
80 |
81 | // Rear Center Cube
82 | translate(v=[80, 92, -50])
83 | rotate(a=[90,0,45])
84 | rotate(a=[0,90,90])
85 | cube(size=[12,12,135]);
86 |
87 | // Rear Right Cube
88 | translate(v=[96, 75, -50])
89 | rotate(a=[90,0,0])
90 | rotate(a=[0,90,90])
91 | cube(size=[12,12,135]);
92 |
93 | // Far Rear Right Cube
94 | translate(v=[100, 110, -50])
95 | rotate(a=[90,0,0])
96 | rotate(a=[0,90,90])
97 | cube(size=[12,25,135]);
98 |
99 | // Far Rear Left Cube
100 | translate(v=[67.5, 110, -50])
101 | rotate(a=[90,0,0])
102 | rotate(a=[0,90,90])
103 | cube(size=[12,25,135]);
104 |
105 | // Far Front Right Cube
106 | translate(v=[100, 3, -50])
107 | rotate(a=[90,0,0])
108 | rotate(a=[0,90,90])
109 | cube(size=[12,25,135]);
110 |
111 | // Far Front Left Cube
112 | translate(v=[67.5, 3, -50])
113 | rotate(a=[90,0,0])
114 | rotate(a=[0,90,90])
115 | cube(size=[12,25,135]);
116 |
117 | // Side Front Right Cube
118 | translate(v=[125, 25, -50])
119 | rotate(a=[90,0,0])
120 | rotate(a=[0,90,90])
121 | cube(size=[25,12,135]);
122 |
123 | // Side Front Left Cube
124 | translate(v=[30, 25, -50])
125 | rotate(a=[90,0,0])
126 | rotate(a=[0,90,90])
127 | cube(size=[25,12,135]);
128 |
129 | // Side Rear Right Cube
130 | translate(v=[125, 80, -50])
131 | rotate(a=[90,0,0])
132 | rotate(a=[0,90,90])
133 | cube(size=[25,12,135]);
134 |
135 | // Side Rear Left Cube
136 | translate(v=[30, 80, -50])
137 | rotate(a=[90,0,0])
138 | rotate(a=[0,90,90])
139 | cube(size=[25,12,135]);
140 |
141 | }
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/rack-mount/catalog/Minisforum_UM890PRO-tray_mod.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a MinisForum UM890 PRO mini pc.
5 | Not compatible with nano rack configuration.
6 |
7 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
8 | */
9 |
10 | difference () {
11 | bottomScrewTray (
12 | u = 6,
13 | trayWidth = 140,
14 | trayDepth = 140,
15 | trayThickness = 3,
16 | frontLipHeight = 3,
17 | backLipHeight = 5,
18 | mountPoints = [[67.5, 115], [67.5, 115-95.25]],
19 | frontThickness = 3,
20 | sideThickness = 3,
21 | mountPointElevation = 1,
22 | mountPointType = "m4",
23 | sideSupport = true,
24 | trayLeftPadding = 15
25 | );
26 |
27 | // Side perforations for airflow
28 | translate(v=[-4, 5, 25]) {
29 | rotate(a=[0,90,0])
30 | rotate(a=[0,0,45])
31 | cube(size=[25, 25, 155]);
32 |
33 |
34 | translate(v=[0, 38.25, -08])
35 | rotate(a=[0,90,0])
36 | rotate(a=[0,0,45])
37 | cube(size=[15,15,150]);
38 |
39 | translate(v=[0, 65, -12])
40 | rotate(a=[0,90,0])
41 | rotate(a=[0,0,45])
42 | cube(size=[10,10,150]);
43 |
44 | // Bottom perforations for airflow
45 | // Front Right Cube
46 | translate(v=[60, 40, -50])
47 | rotate(a=[90,0,0])
48 | rotate(a=[0,90,90])
49 | cube(size=[12,12,135]);
50 |
51 | // Front Center Cube
52 | translate(v=[80, 35, -50])
53 | rotate(a=[90,0,45])
54 | rotate(a=[0,90,90])
55 | cube(size=[12,12,135]);
56 |
57 | // Front Left Cube
58 | translate(v=[95, 40, -50])
59 | rotate(a=[90,0,0])
60 | rotate(a=[0,90,90])
61 | cube(size=[12,12,135]);
62 |
63 | // Center Right Cube
64 | translate(v=[50.5, 65, -50])
65 | rotate(a=[90,0,45])
66 | rotate(a=[0,90,90])
67 | cube(size=[12,12,135]);
68 |
69 | // Center Left Cube
70 | translate(v=[110, 65, -50])
71 | rotate(a=[90,0,45])
72 | rotate(a=[0,90,90])
73 | cube(size=[12,12,135]);
74 |
75 | // Rear Left Cube
76 | translate(v=[60, 75, -50])
77 | rotate(a=[90,0,0])
78 | rotate(a=[0,90,90])
79 | cube(size=[12,12,135]);
80 |
81 | // Rear Center Cube
82 | translate(v=[80, 92, -50])
83 | rotate(a=[90,0,45])
84 | rotate(a=[0,90,90])
85 | cube(size=[12,12,135]);
86 |
87 | // Rear Right Cube
88 | translate(v=[96, 75, -50])
89 | rotate(a=[90,0,0])
90 | rotate(a=[0,90,90])
91 | cube(size=[12,12,135]);
92 |
93 | // Far Rear Right Cube
94 | translate(v=[110, 110, -50])
95 | rotate(a=[90,0,0])
96 | rotate(a=[0,90,90])
97 | cube(size=[12,25,135]);
98 |
99 | // Far Rear Left Cube
100 | translate(v=[57.5, 110, -50])
101 | rotate(a=[90,0,0])
102 | rotate(a=[0,90,90])
103 | cube(size=[12,25,135]);
104 |
105 | // Far Front Right Cube
106 | translate(v=[110, 3, -50])
107 | rotate(a=[90,0,0])
108 | rotate(a=[0,90,90])
109 | cube(size=[12,25,135]);
110 |
111 | // Far Front Left Cube
112 | translate(v=[57.5, 3, -50])
113 | rotate(a=[90,0,0])
114 | rotate(a=[0,90,90])
115 | cube(size=[12,25,135]);
116 |
117 | // Side Front Right Cube
118 | translate(v=[125, 25, -50])
119 | rotate(a=[90,0,0])
120 | rotate(a=[0,90,90])
121 | cube(size=[25,12,135]);
122 |
123 | // Side Front Left Cube
124 | translate(v=[30, 25, -50])
125 | rotate(a=[90,0,0])
126 | rotate(a=[0,90,90])
127 | cube(size=[25,12,135]);
128 |
129 | // Side Rear Right Cube
130 | translate(v=[125, 80, -50])
131 | rotate(a=[90,0,0])
132 | rotate(a=[0,90,90])
133 | cube(size=[25,12,135]);
134 |
135 | // Side Rear Left Cube
136 | translate(v=[30, 80, -50])
137 | rotate(a=[90,0,0])
138 | rotate(a=[0,90,90])
139 | cube(size=[25,12,135]);
140 |
141 | }
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/rack-mount/catalog/README.md:
--------------------------------------------------------------------------------
1 | # Rack Mount Catalog
2 |
3 | A hodgepodge of various pre-configured rack mount parts.
4 |
5 | Please feel free to submit a pull request for any new parts you end up creating! Code quality is no object here.
6 |
--------------------------------------------------------------------------------
/rack-mount/catalog/Unifi-8-PoE-Switch_Tray+Adapter.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a Unifi Lite 8PoE Switch.
5 | Included mounting adapter, mounting adapter seats two M3 Hex nuts using two M3x8 screws.
6 | DO NOT USE INCLUDED SCREWS FROM UNIFI, this will damage the switch.
7 |
8 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
9 | */
10 |
11 |
12 | ///////////////////////////////////////
13 | /////////// MOUNTING TRAY ////////////
14 | /////////////////////////////////////
15 | difference () {
16 | bottomScrewTray (
17 | u = 3,
18 | trayWidth = 175,
19 | trayDepth = 110,
20 | trayThickness = 3,
21 | frontLipHeight = 7.5,
22 | backLipHeight = 7.5,
23 | mountPoints = [[54, 40], [54+60.325, 40]],
24 | frontThickness = 3,
25 | sideThickness = 3,
26 | mountPointElevation = 1,
27 | mountPointType = "m3",
28 | sideSupport = true,
29 | trayLeftPadding = 2.5
30 | );
31 |
32 | // Front Center Cube
33 | translate(v=[87.5, 20, -50])
34 | rotate(a=[90,0,45])
35 | rotate(a=[0,90,90])
36 | cube(size=[12,12,135]);
37 |
38 | // Center Right Cube
39 | translate(v=[58, 50, -50])
40 | rotate(a=[90,0,45])
41 | rotate(a=[0,90,90])
42 | cube(size=[12,12,135]);
43 |
44 | // Center Left Cube
45 | translate(v=[117.5, 50, -50])
46 | rotate(a=[90,0,45])
47 | rotate(a=[0,90,90])
48 | cube(size=[12,12,135]);
49 |
50 | // Rear Left Cube
51 | translate(v=[67.5, 60, -50])
52 | rotate(a=[90,0,0])
53 | rotate(a=[0,90,90])
54 | cube(size=[12,12,135]);
55 |
56 | // Rear Center Cube
57 | translate(v=[87.5, 77, -50])
58 | rotate(a=[90,0,45])
59 | rotate(a=[0,90,90])
60 | cube(size=[12,12,135]);
61 |
62 | // Rear Right Cube
63 | translate(v=[103.5, 60, -50])
64 | rotate(a=[90,0,0])
65 | rotate(a=[0,90,90])
66 | cube(size=[12,12,135]);
67 |
68 |
69 | // Side Front Right Cube
70 | translate(v=[132.5, 10, -50])
71 | rotate(a=[90,0,0])
72 | rotate(a=[0,90,90])
73 | cube(size=[25,12,135]);
74 |
75 | // Side Front Left Cube
76 | translate(v=[37.5, 10, -50])
77 | rotate(a=[90,0,0])
78 | rotate(a=[0,90,90])
79 | cube(size=[25,12,135]);
80 |
81 | // Side Rear Right Cube
82 | translate(v=[132.5, 65, -50])
83 | rotate(a=[90,0,0])
84 | rotate(a=[0,90,90])
85 | cube(size=[25,12,135]);
86 |
87 | // Side Rear Left Cube
88 | translate(v=[38.5, 65, -50])
89 | rotate(a=[90,0,0])
90 | rotate(a=[0,90,90])
91 | cube(size=[25,12,135]);
92 |
93 | }
94 |
95 | ///////////////////////////////////////
96 | ////////// MOUNTING ADAPTER //////////
97 | /////////////////////////////////////
98 |
99 | // Seat Teeth
100 | translate (v= [0,1.5,0.1,]){
101 | translate(v=[54.25 + 15 -1.25, 5.5 + 13.51875, 10+2.25]) {
102 | cube(size=[1.5875, 6.5, 1.5875]);
103 | }
104 | translate(v=[54.25 + 20 -1.25, 5.5 + 13.51875, 10+2.25]) {
105 | cube(size=[1.5875, 6.5, 1.5875]);
106 | }
107 | translate(v=[54.25 + 25 -1.25, 5.5 + 13.51875, 10+2.25]) {
108 | cube(size=[1.5875, 6.5, 1.5875]);
109 | }
110 |
111 | translate(v=[54.25 + 15 -1.25 + 22, 5.5 + 13.51875, 10+2.25]) {
112 | cube(size=[1.5875, 6.5, 1.5875]);
113 | }
114 | translate(v=[54.25 + 20 -1.25 + 22, 5.5 + 13.51875, 10+2.25]) {
115 | cube(size=[1.5875, 6.5, 1.5875]);
116 | }
117 | translate(v=[54.25 + 25 -1.25 + 22, 5.5 + 13.51875, 10+2.25]) {
118 | cube(size=[1.5875, 6.5, 1.5875]);
119 | }
120 | }
121 |
122 | // Seat Key
123 | difference () {
124 | translate(v=[54.25, 5.5 + 13.51875, 10+3.175]) {
125 | cube(size=[59.53125, 9.5, 1.5875]);
126 | }
127 | translate(v=[45 + 38.89375, 19, 12]) {
128 | cube(size=[1.5875, 10, 4.7625]);
129 | }
130 | }
131 |
132 | // Body
133 | difference () {
134 | translate(v=[45, 28.5, 9 + 0.5125]) {
135 | cube(size=[77.7875, 23.01875, 5.7625 - 0.5125]);
136 | }
137 |
138 |
139 | // Cut aways
140 | translate(v=[45, 22, 0]) {
141 | rotate(a=[0,0,45]){
142 | translate(v=[-.25, -.25, 9]) {
143 | cube(size=[9.7525, 9.7525, 10]);
144 | }
145 | }
146 | }
147 |
148 | translate(v=[45+ 77.7875, 22, 0]) {
149 | rotate(a=[0,0,45]){
150 | translate(v=[-.25, -.25, 9]) {
151 | cube(size=[9.7525, 9.7525, 10]);
152 | }
153 | }
154 | }
155 | // Screw holes
156 | translate(v=[54, 40, -10]) {
157 | cylinder(h=65, r1=1.65, r2=1.65, $fn=25);
158 | }
159 |
160 | translate(v=[54+60.325, 40, -10]) {
161 | cylinder(h=65, r1=1.65, r2=1.65, $fn=25);
162 | }
163 | translate(v=[54+60.325, 40, 12]) {
164 | cylinder(h=65, r1=3.25, r2=3.25, $fn=6);
165 | }
166 | translate(v=[54, 40, 12]) {
167 | cylinder(h=65, r1=3.25, r2=3.25, $fn=6);
168 | }
169 | }
--------------------------------------------------------------------------------
/rack-mount/catalog/beelink-EQi12-box_mod.scad:
--------------------------------------------------------------------------------
1 | include <../../rack/sharedVariables.scad>
2 | include <../common.scad>
3 | include <../enclosed-box/helper.scad>
4 |
5 | use <../enclosed-box/sideRail.scad>
6 | use <../enclosed-box/frontBoxHolder.scad>
7 |
8 | /*
9 | Enclosed box mounting system:
10 | Helper file to use semi-enclosed side rails and a front plate to mount a box.
11 | This system does not require any mounting holes on the enclosed box.
12 |
13 | !!! Please also make sure that the correct rack frame preset is set in rackFrame.scad !!!
14 | */
15 | module enclosedBoxSystem (
16 |
17 | // begin config ////////////////////////////////////////////////////////////////////////////////////////////////////////
18 |
19 | // Does not affect any part dimensions. Set this to true to visualize how a box would be mounted.
20 | visualize = false,
21 | zOrientation = "middle", // ["middle" | "bottom"]
22 | recessSideRail = false,
23 |
24 | boxWidth = 126,
25 | boxHeight = 44.5,
26 | boxDepth = 126,
27 |
28 | railDefaultThickness = 1.5,
29 | railSideThickness = 3,
30 |
31 | frontPlateThickness = 3,
32 | frontPlateCutoutYSpace = 3,
33 | frontPlateCutoutXSpace = 5,
34 |
35 | // end config //////////////////////////////////////////////////////////////////////////////////////////////////////////
36 |
37 | ) {
38 | leftRailTrans = identity;
39 | rightRailTrans = visualize
40 | ? translate(v = [boxWidth, 0, 0])*mirror(v = [1, 0, 0])
41 | : translate(v = [sideRailBaseWidth*2, 0, 0])*mirror(v = [1, 0, 0]);
42 |
43 | u = findU(boxHeight, railDefaultThickness);
44 | railBottomThickness = railBottomThickness(u, boxHeight, railDefaultThickness, zOrientation);
45 | frontBoxHolderTrans = visualize
46 | ? translate(v = [railSideThickness-(railSupportsDx-boxWidth)/2, 0, sideRailLowerMountPointToBottom-
47 | railBottomThickness])*mirror(v = [0, 1, 0])*rotate(a = [90, 0, 0])
48 | : mirror(v = [0, 1, 0])*translate(v = [0, uDiff, frontPlateThickness-railBottomThickness]);
49 |
50 | if (visualize) {
51 | %cube(size = [boxWidth, boxDepth, boxHeight]);
52 | }
53 |
54 | multmatrix(leftRailTrans)
55 | sideSupportRailBase(top = true, recess = recessSideRail, defaultThickness = railDefaultThickness, supportedZ =
56 | boxHeight, supportedY = boxDepth, supportedX = boxWidth, zOrientation = zOrientation, railSideThickness =
57 | railSideThickness);
58 |
59 | multmatrix(rightRailTrans)
60 | sideSupportRailBase(top = true, recess = recessSideRail, defaultThickness = railDefaultThickness, supportedZ =
61 | boxHeight, supportedY = boxDepth, supportedX = boxWidth, zOrientation = zOrientation, railSideThickness =
62 | railSideThickness);
63 |
64 | multmatrix(frontBoxHolderTrans)
65 | frontBoxHolder(
66 | cutoutOffsetX = (rackMountScrewWidth-(boxWidth-2*frontPlateCutoutXSpace))/2, cutoutOffsetY = railBottomThickness+
67 | frontPlateCutoutYSpace,
68 | cutoutX = boxWidth-2*frontPlateCutoutXSpace, cutoutY = boxHeight-2*frontPlateCutoutYSpace,
69 | zOrientation = zOrientation, supportedZ = boxHeight, supportWidth = max(10, boxWidth-(sideRailBaseWidth+10)),
70 | supportRailDefaultThickness = railDefaultThickness, plateThickness = frontPlateThickness
71 | );
72 | }
73 |
74 | enclosedBoxSystem();
75 |
--------------------------------------------------------------------------------
/rack-mount/catalog/beelink-EQi12-tray_mod.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a beelink mini-s series mini pc.
5 |
6 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
7 | */
8 |
9 | difference () {
10 | bottomScrewTray (
11 | u = 5,
12 | trayWidth = 140,
13 | trayDepth = 140,
14 | trayThickness = 3,
15 | frontLipHeight = 3,
16 | backLipHeight = 5,
17 | frontThickness = 3,
18 | sideThickness = 3,
19 | mountPointElevation = 1,
20 | mountPointType = "m4",
21 | sideSupport = true,
22 | trayLeftPadding = 15
23 | );
24 |
25 |
26 | // Side perforations for airflow
27 | translate(v=[-4, 5, 18]) {
28 | rotate(a=[0,90,0])
29 | rotate(a=[0,0,45])
30 | cube(size=[18, 18, 155]);
31 |
32 | translate(v=[0, 28, -04])
33 | rotate(a=[0,90,0])
34 | rotate(a=[0,0,45])
35 | cube(size=[12,12,150]);
36 |
37 | translate(v=[0, 48, -06.5])
38 | rotate(a=[0,90,0])
39 | rotate(a=[0,0,45])
40 | cube(size=[8,8,150]);
41 |
42 |
43 | // Bottom perforations for airflow
44 | // Front Right Cube
45 | translate(v=[60, 40, -50])
46 | rotate(a=[90,0,0])
47 | rotate(a=[0,90,90])
48 | cube(size=[12,12,135]);
49 |
50 | // Front Center Cube
51 | translate(v=[80, 35, -50])
52 | rotate(a=[90,0,45])
53 | rotate(a=[0,90,90])
54 | cube(size=[12,12,135]);
55 |
56 | // Front Left Cube
57 | translate(v=[95, 40, -50])
58 | rotate(a=[90,0,0])
59 | rotate(a=[0,90,90])
60 | cube(size=[12,12,135]);
61 |
62 | // Center Right Cube
63 | translate(v=[50.5, 65, -50])
64 | rotate(a=[90,0,45])
65 | rotate(a=[0,90,90])
66 | cube(size=[12,12,135]);
67 |
68 | // Center Left Cube
69 | translate(v=[110, 65, -50])
70 | rotate(a=[90,0,45])
71 | rotate(a=[0,90,90])
72 | cube(size=[12,12,135]);
73 |
74 | // Rear Left Cube
75 | translate(v=[60, 75, -50])
76 | rotate(a=[90,0,0])
77 | rotate(a=[0,90,90])
78 | cube(size=[12,12,135]);
79 |
80 | // Rear Center Cube
81 | translate(v=[80, 92, -50])
82 | rotate(a=[90,0,45])
83 | rotate(a=[0,90,90])
84 | cube(size=[12,12,135]);
85 |
86 | // Rear Right Cube
87 | translate(v=[96, 75, -50])
88 | rotate(a=[90,0,0])
89 | rotate(a=[0,90,90])
90 | cube(size=[12,12,135]);
91 |
92 | // Far Rear Right Cube
93 | translate(v=[100, 110, -50])
94 | rotate(a=[90,0,0])
95 | rotate(a=[0,90,90])
96 | cube(size=[12,25,135]);
97 |
98 | // Far Rear Left Cube
99 | translate(v=[67.5, 110, -50])
100 | rotate(a=[90,0,0])
101 | rotate(a=[0,90,90])
102 | cube(size=[12,25,135]);
103 |
104 | // Far Front Right Cube
105 | translate(v=[100, 3, -50])
106 | rotate(a=[90,0,0])
107 | rotate(a=[0,90,90])
108 | cube(size=[12,25,135]);
109 |
110 | // Far Front Left Cube
111 | translate(v=[67.5, 3, -50])
112 | rotate(a=[90,0,0])
113 | rotate(a=[0,90,90])
114 | cube(size=[12,25,135]);
115 |
116 | // Side Front Right Cube
117 | translate(v=[125, 25, -50])
118 | rotate(a=[90,0,0])
119 | rotate(a=[0,90,90])
120 | cube(size=[25,12,135]);
121 |
122 | // Side Front Left Cube
123 | translate(v=[30, 25, -50])
124 | rotate(a=[90,0,0])
125 | rotate(a=[0,90,90])
126 | cube(size=[25,12,135]);
127 |
128 | // Side Rear Right Cube
129 | translate(v=[125, 80, -50])
130 | rotate(a=[90,0,0])
131 | rotate(a=[0,90,90])
132 | cube(size=[25,12,135]);
133 |
134 | // Side Rear Left Cube
135 | translate(v=[30, 80, -50])
136 | rotate(a=[90,0,0])
137 | rotate(a=[0,90,90])
138 | cube(size=[25,12,135]);
139 |
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/rack-mount/catalog/beelink-mini-s-tray.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a beelink mini-s series mini pc.
5 |
6 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
7 | */
8 |
9 | difference () {
10 | bottomScrewTray (
11 | u = 4,
12 | trayWidth = 130,
13 | trayDepth = 110,
14 | trayThickness = 3,
15 | frontLipHeight = 3,
16 | backLipHeight = 5,
17 | mountPoints = [[44, 8], [44+35, 8]],
18 | frontThickness = 3,
19 | sideThickness = 3,
20 | mountPointElevation = 1,
21 | mountPointType = "m3",
22 | sideSupport = true,
23 | trayLeftPadding = 15
24 | );
25 |
26 |
27 | // perforations for airflow
28 | translate(v=[-4, 5, 18]) {
29 | rotate(a=[0,90,0])
30 | rotate(a=[0,0,45])
31 | cube(size=[18, 18, 135]);
32 |
33 |
34 | translate(v=[0, 28, -4])
35 | rotate(a=[0,90,0])
36 | rotate(a=[0,0,45])
37 | cube(size=[12,12,135]);
38 |
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/rack-mount/catalog/brush-strip-plate.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 | use <../plateBase.scad>
3 |
4 |
5 | /*
6 | A 4U (50mm tall) panel for nylon brush stripping to hide cable shame.
7 |
8 | Brush Weather Stripping (0.35" Wide x 0.35" Thick): https://amzn.to/3CLpWMp
9 | */
10 |
11 |
12 |
13 |
14 | plateU=4;
15 | plateThickness=3;
16 | brushstripWidth=8.89;
17 | brushstripLength=8.89;
18 | //How far from the edge of the plate the Brush Strip Hole will begin
19 | brushstripOffset=15;
20 | //How far the ledges that the brush strip affix too
21 | brushstripHoleOverlap=5;
22 |
23 |
24 | /* Reckless copying and pasting begins here */
25 | screwToXEdge=4.5;
26 | screwToYEdge=4.5;
27 | uDiff = screwDiff;
28 | filletR=2;
29 | screwDx = rackMountScrewWidth;
30 | screwDy = uDiff * plateU;
31 | plateLength = screwDx + 2*screwToXEdge;
32 | plateHeight = screwDy + 2*screwToYEdge;
33 | railDefaultThickness = 1.5;
34 | /* End of Reckless copying and pasting? */
35 |
36 |
37 | brushstripLedgeX=plateLength - ((brushstripOffset-brushstripHoleOverlap)*2);
38 | brushstripLedgeY=5;
39 | brushstripLedgeZ=brushstripWidth*1.2;
40 |
41 | brushstripHoleX=plateLength - (brushstripOffset*2);
42 | brushstripHoleY=brushstripLength*2;
43 | brushstripHoleZ=plateThickness*2;
44 | midPlateY=(plateHeight)/2;
45 |
46 | echo("Plate Height: ", plateHeight);
47 | echo("Plate Length: ", plateLength);
48 | echo("Vertical distance between 2 main rail holes: ", screwDiff);
49 | echo("Horizontal distance between 2 opposing main rail holes: ", rackMountScrewWidth);
50 | echo("Distance between main rail screw, and main rail inner edge:", railScrewHoleToInnerEdge);
51 | echo("Max supported rack-mount width: ", maxUnitWidth);
52 | echo("Max recommended rack-mount depth: ", maxUnitDepth);
53 |
54 |
55 | difference(){
56 | plateBase(U=plateU, plateThickness=plateThickness, screwToXEdge=4.5, screwToYEdge=5.0, screwType="m4", filletR=2);
57 | translate([brushstripOffset,midPlateY-(brushstripHoleY/2),0]) brushstripHole();
58 | }
59 | translate([-screwToXEdge+(brushstripOffset-brushstripHoleOverlap),midPlateY-screwToYEdge+(brushstripHoleY/2),0]) cube([brushstripLedgeX, brushstripLedgeY, brushstripLedgeZ]);
60 | translate([-screwToXEdge+(brushstripOffset-brushstripHoleOverlap),midPlateY-screwToYEdge-(brushstripHoleY/2)- brushstripLedgeY,0]) cube([brushstripLedgeX, brushstripLedgeY, brushstripLedgeZ]);
61 |
62 | module brushstripHole(){
63 | translate([-screwToXEdge,-screwToYEdge,-(plateThickness+1)]) cube([brushstripHoleX, brushstripHoleY, brushstripHoleZ]);
64 | }
--------------------------------------------------------------------------------
/rack-mount/catalog/mele-quieter-tray.scad:
--------------------------------------------------------------------------------
1 | use <../tray/tray.scad>
2 |
3 | /*
4 | Simple tray for a mele quieter series mini pc.
5 |
6 | Please make sure to configure the correct rack frame dimensions in rackFrame.scad.
7 | */
8 |
9 | bottomScrewTray (
10 | u = 2,
11 | trayWidth = 145,
12 | trayDepth = 88,
13 | trayThickness = 3,
14 | frontLipHeight = 3,
15 | backLipHeight = 2,
16 | mountPoints = [[27.5, 34], [107, 34]],
17 | frontThickness = 3,
18 | sideThickness = 3,
19 | mountPointElevation = 1,
20 | mountPointType = "m3",
21 | sideSupport = true,
22 | trayLeftPadding = 10
23 | );
24 |
--------------------------------------------------------------------------------
/rack-mount/catalog/parts/sfxPSU.scad:
--------------------------------------------------------------------------------
1 |
2 | module sfxPowerSupply() {
3 |
4 | length = 125.0;
5 | width = 100.0;
6 | height = 64;
7 | screwD = 3.5;
8 |
9 | eps = 0.001;
10 |
11 | // body
12 | color([0,1,0]) cube(size=[length, width, height]);
13 |
14 | // main fan
15 | translate([62.5, 50,0])
16 | color([0,1,1])
17 | circle(d=88);
18 |
19 |
20 | // open faces
21 | translate([10,-eps, 7])
22 | color([0,1,1])
23 | cube(size=[length-20, eps, height-7]);
24 |
25 |
26 | // screw holes
27 | color([1,0,1])
28 | translate([length-6, eps, height-6])
29 | rotate(a=[90,0,0])
30 | circle(d=screwD);
31 |
32 | color([1,0,1])
33 | translate([6, eps, height-6])
34 | rotate(a=[90,0,0])
35 | circle(d=screwD);
36 |
37 | color([1,0,1])
38 | translate([6, eps, 6])
39 | rotate(a=[90,0,0])
40 | circle(d=screwD);
41 |
42 | color([1,0,1])
43 | translate([length-6, eps, 6])
44 | rotate(a=[90,0,0])
45 | circle(d=screwD);
46 |
47 | color([1,0,1])
48 | translate([6, eps, height-(6+25.5)])
49 | rotate(a=[90,0,0])
50 | circle(d=screwD);
51 |
52 | color([1,0,1])
53 | translate([length-6, eps, height-(6+25.5)])
54 | rotate(a=[90,0,0])
55 | circle(d=screwD);
56 |
57 |
58 | }
59 |
60 | sfxPowerSupply();
--------------------------------------------------------------------------------
/rack-mount/catalog/rpi-sbc-simple-box/case.scad:
--------------------------------------------------------------------------------
1 | include <../../../config/common.scad>
2 | include <../../../helper/common.scad>
3 |
4 | // All coordinates are in [x,y], or [x,y,z] format
5 | pcbDimensions = [56.0, 85.1]; // [x,y]
6 | pcbThickness = 1.42;
7 |
8 | // [+x, -x, +y, -y]
9 | pcbCaseSpace = [5, 2, 5, 2];
10 | pcbRise = 3;
11 | caseWallThickness = 2;
12 | caseBottomThickness = 2;
13 | mountPointDiameter = 5;
14 |
15 | mountPoints = [
16 | [3.65, 23.3,0],
17 | [3.65 + 49, 23.3,0],
18 | [3.65, 23.3 + 58,0],
19 | [3.65 + 49, 23.3 + 58,0]
20 | ];
21 |
22 |
23 | module pcb() {
24 | cube(size=[pcbDimensions[0], pcbDimensions[1], pcbThickness]);
25 | }
26 |
27 | module pcbCaseBottom_() {
28 | translate(v=[-pcbCaseSpace[1]-caseWallThickness, -pcbCaseSpace[3]-caseWallThickness, -caseBottomThickness-pcbRise])
29 | difference() {
30 | cube(size=[
31 | pcbDimensions[0]+pcbCaseSpace[0]+pcbCaseSpace[1] + 2*caseWallThickness,
32 | pcbDimensions[1]+pcbCaseSpace[2]+pcbCaseSpace[3] + 2*caseWallThickness,
33 | 26 // 3u case, subtracted for and other bullshit
34 | ]);
35 | translate(v=[caseWallThickness, caseWallThickness, caseBottomThickness])
36 | cube(size=[
37 | pcbDimensions[0]+pcbCaseSpace[0]+pcbCaseSpace[1],
38 | pcbDimensions[1]+pcbCaseSpace[2]+pcbCaseSpace[3],
39 | 26 // 3u case, subtracted 4 for lid and bullshit
40 | ]);
41 | }
42 | }
43 |
44 | module pcbCaseWithRisers_() {
45 | union() {
46 | translate(v=[0,0,-pcbRise]){
47 |
48 | difference () {
49 | mountPoints_N(pcbRise, mountPointDiameter/1.5, mountPointDiameter/2, 32, false);
50 | mountPoints_N(pcbRise + 2, 1.95/2 - 0.05, 1.95/2 - 0.05, 32, false);
51 | }
52 | }
53 | pcbCaseBottom_();
54 | }
55 | }
56 |
57 |
58 | module cutoutProfileAirflow_N() {
59 |
60 | // bottom cutouts
61 | union() {
62 | for (i=[0:11]) {
63 | translate(v=[pcbDimensions[0]/2.0, i*6 + 10,0])
64 | minkowski() {
65 | cube(size=[30,1,20], center=true);
66 | cylinder(h=1,r=1);
67 | }
68 | }
69 | }
70 |
71 | // back cutout
72 | translate(v=[5,pcbDimensions[1]+5,-1])
73 | minkowski() {
74 | cube(size=[50,90,15], center=false);
75 | rotate(a=[90,0,0])
76 | cylinder(h=1,r=2);
77 | }
78 |
79 | // front cutout
80 | translate(v=[pcbDimensions[0],2.5,1])
81 | cube(size=[inf50, 80, 15]);
82 | }
83 |
84 | module mountPoints_N(cylHeight, cylRad1, cylRad2, cylFn, center) {
85 | for (i=[0:3]) {
86 | p = mountPoints[i];
87 | translate(v=[p[0], p[1], p[2]])
88 | cylinder(r1=cylRad1, r2=cylRad2, h=cylHeight, $fn=cylFn, center=center);
89 | }
90 |
91 | }
92 |
93 | // fucked up
94 | module cutoutProfile_N() {
95 | color([1,0,1])
96 | union() {
97 | // front I/O
98 | mirror(v=[0,1,0])
99 | translate(v=[1, -eps*100, pcbThickness-4])
100 | cube(size=[58.0 + 0.1, inf50, 21 + 0.1]);
101 |
102 | // side I/O
103 | translate(v=[-48-3, (pcbDimensions[1]-54)-10, pcbThickness-4])
104 | cube(size=[inf50, 64, 19]);
105 | }
106 |
107 | }
108 |
109 |
110 | module mainCase() {
111 | difference() {
112 |
113 | union() {
114 | pcbCaseWithRisers_();
115 |
116 | // lugs
117 | // -4
118 | translate(v = [pcbDimensions[0]+caseWallThickness+pcbCaseSpace[0], -caseWallThickness-pcbCaseSpace[3], -pcbRise-
119 | caseBottomThickness])
120 | cube(size = [2, 5, 5]);
121 |
122 | // 87.1
123 | translate(v = [pcbDimensions[0]+caseWallThickness+pcbCaseSpace[0], pcbDimensions[1]+pcbCaseSpace[2]-5+
124 | caseWallThickness, -pcbRise-caseBottomThickness])
125 | cube(size = [2, 5, 5]);
126 |
127 | // -> 87.1 + 4 = 91.1
128 | }
129 |
130 | union() {
131 | cutoutProfile_N();
132 | cutoutProfileAirflow_N();
133 | }
134 | }
135 | }
136 |
137 | mainCase();
138 |
--------------------------------------------------------------------------------
/rack-mount/catalog/rpi-sbc-simple-box/frontPlate.scad:
--------------------------------------------------------------------------------
1 | include <../../../config/common.scad>
2 | include <../../../helper/common.scad>
3 | include <../../../rack-mount/plateBase.scad>
4 |
5 | vU = 2;
6 | uHeight = 10;
7 |
8 | plateScrewDiffV = uHeight*vU;
9 | plateScrewDiffH = 180;
10 |
11 | plateScrewToHEdge = 4.5;
12 | plateScrewToVEdge = 5.5;
13 |
14 | frontPlateThickness = 2.5;
15 |
16 | frontPlateV = plateScrewDiffV + 2*plateScrewToHEdge;
17 | frontPlateH = plateScrewDiffH + 2*plateScrewToVEdge;
18 |
19 |
20 | plateScrewToBoxMin = 6;
21 |
22 |
23 | length = 150;
24 | resolution = 250;
25 | period = PI/6;
26 | shift = 0.0;
27 | amplitudeFunction = function(x) 2;
28 |
29 | module _frontPlateBody() {
30 |
31 | translate(v=[5,-3,-1])
32 | rotate(a=[180,0,0])
33 | sineWaveHull(length, resolution, amplitudeFunction, period+0.02, 2, 5);
34 |
35 | translate(v=[5,-3,4-1])
36 | rotate(a=[180,0,0])
37 | sineWaveHull(length, resolution, amplitudeFunction, period, 2 , 5);
38 |
39 | translate(v=[5,-3,8-1])
40 | rotate(a=[180,0,0])
41 | sineWaveHull(length, resolution, amplitudeFunction, period+0.03, 2.5, 5);
42 |
43 | translate(v=[5,-3,12-1])
44 | rotate(a=[180,0,0])
45 | sineWaveHull(length, resolution, amplitudeFunction, period+0.1, 3.3, 5);
46 |
47 | translate(v=[5,-3,16-1])
48 | rotate(a=[180,0,0])
49 | sineWaveHull(length, resolution, amplitudeFunction, period+0.1, 5, 5);
50 |
51 | translate(v=[5,-3,20-1])
52 | rotate(a=[180,0,0])
53 | sineWaveHull(length, resolution, amplitudeFunction, period+0.1, 6, 5);
54 |
55 | translate(v=[5,-3,24-1])
56 | rotate(a=[180,0,0])
57 | sineWaveHull(length, resolution, amplitudeFunction, period+0.08, 7, 5);
58 | }
59 |
60 | module _plateHole() {
61 | rotate(a=[90,0,0])
62 | cylinder(r=m4RadiusSlacked, h=inf, center=true);
63 | }
64 |
65 |
66 | module frontPlate() {
67 | difference() {
68 | _frontPlateBody();
69 |
70 | union() {
71 | // TODO: introduce helper modules for this pattern
72 | _plateHole();
73 |
74 | translate(v=[plateScrewDiffH,0,0])
75 | _plateHole();
76 |
77 | translate(v=[0,0,plateScrewDiffV])
78 | _plateHole();
79 |
80 | translate(v=[plateScrewDiffH,0,plateScrewDiffV])
81 | _plateHole();
82 |
83 | }
84 | }
85 | }
86 |
87 |
88 | difference() {
89 | difference() {
90 |
91 | difference() {
92 | union() {
93 | plateBase(U=2, plateThickness=2.5, screwType="m4", filletR=2);
94 | rotate(a = [- 90, 0, 0])
95 | frontPlate();
96 | }
97 |
98 | union() {
99 | translate(v=[1,0,0])
100 | rotate(a=[0,-15, 0])
101 | translate(v=[0,-50,0])
102 | cube(size=[100, 100, 30]);
103 |
104 | translate(v=[160-1,0,0])
105 | mirror(v=[1,0,0]) {
106 | rotate(a = [0, - 15, 0])
107 | translate(v = [0, - 50, 0])
108 | cube(size = [100, 100, 30]);
109 | }
110 | }
111 |
112 | }
113 | // lug holes
114 | union() {
115 | translate(v=[150,-3,-frontPlateThickness])
116 | cube(size=[5.2, 5.2, 3]);
117 | translate(v=[150-91.1,-3,-frontPlateThickness])
118 | cube(size=[5.2, 5.2, 3]);
119 | }
120 | }
121 | for (i=[0:5]) {
122 | translate(v=[5,i*4 - 0.75,-10])
123 | cube(size=[150, 1.5, 20]);
124 | }
125 | }
--------------------------------------------------------------------------------
/rack-mount/catalog/rpi-sbc-simple-box/top.scad:
--------------------------------------------------------------------------------
1 |
2 | difference() {
3 | union() {
4 | cube(size=[67,95.7,1]);
5 | translate(v=[2,2,1])
6 | cube(size=[63.2,92,3]);
7 | }
8 |
9 | union() {
10 | translate(v=[3.5, 3.8,1])
11 | cube(size=[60,88,3]);
12 |
13 | for(i=[0:7]) {
14 | translate(v=[33.5,i*10 + 12,0])
15 | minkowski() {
16 | cylinder(h=1,r=1);
17 | cube(size=[50,5,10], center=true);
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/rack-mount/common.scad:
--------------------------------------------------------------------------------
1 |
2 | include <../rack/sharedVariables.scad>
3 | include <../helper/common.scad>
4 | include <../config/common.scad>
5 |
6 | /*
7 | QoL redefinitions/variables/reimports for rack mount items
8 | */
9 |
10 | uDiff = screwDiff;
11 |
12 | rackMountScrewXDist = 4.5;
13 | rackMountScrewZDist = 4.5;
14 |
15 | mainRailSideSupportToInnerEdge = frontFaceWidth - railSideMountThickness;
16 | railSupportsDx = 2*mainRailSideSupportToInnerEdge + maxUnitWidth;
--------------------------------------------------------------------------------
/rack-mount/dimensionHelper.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 |
3 | // OpenSCAD script to output some helpful dimensions for creating new rack-mount items:
4 |
5 | echo("Vertical distance between 2 main rail holes: ", screwDiff);
6 | echo("Horizontal distance between 2 opposing main rail holes: ", rackMountScrewWidth);
7 |
8 | echo("Distance between main rail screw, and main rail inner edge:", railScrewHoleToInnerEdge);
9 |
10 | echo("Max supported rack-mount width: ", maxUnitWidth);
11 | echo("Max recommended rack-mount depth: ", maxUnitDepth);
12 |
13 |
--------------------------------------------------------------------------------
/rack-mount/enclosed-box/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Enclosed Box Mounting System
4 |
5 | 
6 |
7 | Please see [entry.scad](./entry.scad) for config and building. Make sure the correct rack profile is configured in [rackFrame.scad](../../config/rackFrame.scad).
8 |
9 | - This system comprises three parts: two side rails, and a front plate.
10 | - This system is useful for mounting heavier box-shaped things. It works by first sliding in the box inside the side rails (which secures `x`, `z`, and one half of the `y` axis), and then mounting the front plate along the main rails (fully securing the `y` axis).
11 | - Side rails will most likely require supports to print.
12 | - For wider boxes (nearing the `maxUnitWidth` of the rack), you will have to set `recessSideRail` to true. This is so the side rails do not collide with the main rack rails.
13 |
14 | ### BOM:
15 |
16 | | Item | Name | Quantity | Comment |
17 | |---------------------------------------------------------------|---------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------|
18 | |
| M3x12 FHCS | 8 | Extras are useful and inexpensive. If you plan on eventually stacking multiple racks together, don't hesitate to get a lot more. |
19 | |
| M3 hex nut | 8 | ☝️ |
20 | |
| M4x12 FHCS | 4 | ☝️ |
21 | |
| M4 hex nut | 4 | ☝️ |
--------------------------------------------------------------------------------
/rack-mount/enclosed-box/animate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/rack-mount/enclosed-box/animate.gif
--------------------------------------------------------------------------------
/rack-mount/enclosed-box/animate.scad:
--------------------------------------------------------------------------------
1 | use <./entry.scad>
2 |
3 | $vpt = [120,-30,63];
4 | $vpr = [74,0,25];
5 | $vpd = 550;
6 | $vpf = 22.50;
7 |
8 | animateEnclosedBoxSystem(at=$t);
9 |
10 | module animateEnclosedBoxSystem(at=$t) {
11 |
12 | zOrientation = "middle";
13 | x=150;
14 | y=70;
15 | z=20;
16 | dx = abs(lerp(a=-20, b=20, t=at));
17 | dy = abs(lerp(a=-50, b=50, t=at));
18 | dz = abs(lerp(a=-15, b=15, t=at));
19 |
20 | enclosedBoxSystem(visualize=true, zOrientation=zOrientation, boxWidth=x+dx, boxDepth=y+dy, boxHeight=z+dz);
21 | }
22 |
--------------------------------------------------------------------------------
/rack-mount/enclosed-box/entry.scad:
--------------------------------------------------------------------------------
1 | include <../../rack/sharedVariables.scad>
2 | include <../common.scad>
3 | include <./helper.scad>
4 |
5 | use <./sideRail.scad>
6 | use <./frontBoxHolder.scad>
7 |
8 | /*
9 | Enclosed box mounting system:
10 | Helper file to use semi-enclosed side rails and a front plate to mount a box.
11 | This system does not require any mounting holes on the enclosed box.
12 |
13 | !!! Please also make sure that the correct rack frame preset is set in rackFrame.scad !!!
14 | */
15 | module enclosedBoxSystem (
16 |
17 | // begin config ////////////////////////////////////////////////////////////////////////////////////////////////////////
18 |
19 | // Does not affect any part dimensions. Set this to true to visualize how a box would be mounted.
20 | visualize = false,
21 | zOrientation = "middle", // ["middle" | "bottom"]
22 | recessSideRail = false,
23 |
24 | boxWidth = 160,
25 | boxHeight = 27,
26 | boxDepth = 120,
27 |
28 | railDefaultThickness = 1.5,
29 | railSideThickness = 3,
30 |
31 | frontPlateThickness = 3,
32 | frontPlateCutoutYSpace = 3,
33 | frontPlateCutoutXSpace = 5,
34 |
35 | // end config //////////////////////////////////////////////////////////////////////////////////////////////////////////
36 |
37 | ) {
38 | leftRailTrans = identity;
39 | rightRailTrans = visualize
40 | ? translate(v = [boxWidth, 0, 0])*mirror(v = [1, 0, 0])
41 | : translate(v = [sideRailBaseWidth*2, 0, 0])*mirror(v = [1, 0, 0]);
42 |
43 | u = findU(boxHeight, railDefaultThickness);
44 | railBottomThickness = railBottomThickness(u, boxHeight, railDefaultThickness, zOrientation);
45 | frontBoxHolderTrans = visualize
46 | ? translate(v = [railSideThickness-(railSupportsDx-boxWidth)/2, 0, sideRailLowerMountPointToBottom-
47 | railBottomThickness])*mirror(v = [0, 1, 0])*rotate(a = [90, 0, 0])
48 | : mirror(v = [0, 1, 0])*translate(v = [0, uDiff, frontPlateThickness-railBottomThickness]);
49 |
50 | if (visualize) {
51 | %cube(size = [boxWidth, boxDepth, boxHeight]);
52 | }
53 |
54 | multmatrix(leftRailTrans)
55 | sideSupportRailBase(top = true, recess = recessSideRail, defaultThickness = railDefaultThickness, supportedZ =
56 | boxHeight, supportedY = boxDepth, supportedX = boxWidth, zOrientation = zOrientation, railSideThickness =
57 | railSideThickness);
58 |
59 | multmatrix(rightRailTrans)
60 | sideSupportRailBase(top = true, recess = recessSideRail, defaultThickness = railDefaultThickness, supportedZ =
61 | boxHeight, supportedY = boxDepth, supportedX = boxWidth, zOrientation = zOrientation, railSideThickness =
62 | railSideThickness);
63 |
64 | multmatrix(frontBoxHolderTrans)
65 | frontBoxHolder(
66 | cutoutOffsetX = (rackMountScrewWidth-(boxWidth-2*frontPlateCutoutXSpace))/2, cutoutOffsetY = railBottomThickness+
67 | frontPlateCutoutYSpace,
68 | cutoutX = boxWidth-2*frontPlateCutoutXSpace, cutoutY = boxHeight-2*frontPlateCutoutYSpace,
69 | zOrientation = zOrientation, supportedZ = boxHeight, supportWidth = max(10, boxWidth-(sideRailBaseWidth+10)),
70 | supportRailDefaultThickness = railDefaultThickness, plateThickness = frontPlateThickness
71 | );
72 | }
73 |
74 | enclosedBoxSystem();
75 |
--------------------------------------------------------------------------------
/rack-mount/enclosed-box/frontBoxHolder.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 | include <./helper.scad>
3 | use <../plateBase.scad>
4 |
5 | // To be used with closed sideRails to fully encapsulate a box
6 |
7 | module frontBoxHolder(plateThickness=3, cutoutOffsetX, cutoutOffsetY, cutoutX, cutoutY, supportedZ, supportWidth, supportDepth=5, supportRailDefaultThickness, zOrientation) {
8 |
9 | //assert(supportedZ + 2*supportThickness <= boxPlateScrewToYEdge*2 + u*uDiff);
10 | //assert(supportWidth < rackMountScrewWidth); // not tight, need to include screw radii
11 |
12 | u = findU(supportedZ, supportRailDefaultThickness);
13 | supportRailBottomThickness = railBottomThickness(u, supportedZ, supportRailDefaultThickness, zOrientation);
14 |
15 | difference() {
16 | union() {
17 | plateBase(U=u, plateThickness=plateThickness, screwToXEdge=boxPlateScrewToXEdge, screwToYEdge=boxPlateScrewToYEdge, screwType=mainRailScrewType, filletR=2);
18 |
19 | // bottom support
20 | translate(v=[(rackMountScrewWidth-supportWidth)/2, -boxPlateScrewToYEdge,0])
21 | cube(size=[supportWidth, supportRailBottomThickness, supportDepth]);
22 |
23 | // top support
24 | translate(v=[(rackMountScrewWidth-supportWidth)/2, -boxPlateScrewToYEdge+supportRailBottomThickness+supportedZ,0])
25 | cube(size=[supportWidth, supportRailDefaultThickness, supportDepth]);
26 | }
27 |
28 | union() {
29 | translate(v=[cutoutOffsetX, cutoutOffsetY-boxPlateScrewToYEdge,-inf/2])
30 | minkowski() {
31 | r=2;
32 | cylinder(r=r,h=inf);
33 | translate(v=[r, r, 0])
34 | cube(size = [cutoutX-2*r, cutoutY-2*r, inf]);
35 | }
36 |
37 | }
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/rack-mount/enclosed-box/helper.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 |
3 | // Some utility functions, as well as global functions to make code cleaner
4 |
5 | sideRailLowerMountPointToBottom = uDiff/2;
6 | sideRailBaseWidth = 15;
7 | // distance between front and back main rail screw mounts
8 | sideRailScrewMountDist = yBarDepth - 2*(frontScrewSpacing + railFrontThickness + railSlotToXZ);
9 |
10 | boxPlateScrewToXEdge = 4.5; // wow these are named poorly
11 | boxPlateScrewToYEdge = 5;
12 |
13 |
14 | function findU(boxHeight, minRailThickness) = max(1, ceil((boxHeight + 2*minRailThickness)/uDiff) - 1);
15 |
16 | function railBottomThickness(u, boxHeight, minRailThickness, zOrientation) =
17 | (zOrientation == "middle")
18 | ? (((u+1) * uDiff) - boxHeight)/2
19 | : (zOrientation == "bottom")
20 | ? minRailThickness
21 | : minRailThickness;
--------------------------------------------------------------------------------
/rack-mount/enclosed-box/sideRail.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 | include <./helper.scad>
3 |
4 | // sideSupportRailBase(top=true, defaultThickness=1.5, supportedZ=27.2, supportedY=101.5, supportedX=159);
5 |
6 |
7 | module sideSupportRailBase(top=true, recess=false, supportedZ, supportedY, supportedX, zOrientation="middle", defaultThickness=2, railSideThickness=4, sideVent=true) {
8 |
9 | mountBlockDepth = 10;
10 | screwMountGlobalDz = screwDiff / 2.0; // vertical distance between local origin and main rail screw mount
11 | sideRailScrewToMainRailFrontDx = frontScrewSpacing+railFrontThickness;
12 | railLength = max(sideRailScrewMountDist + sideRailScrewToMainRailFrontDx + mountBlockDepth/2, supportedY+defaultThickness);
13 | railBaseThickness = defaultThickness; // default thickness value
14 | railBackThickness = 3;
15 | // Minimum U to enclose box, while also have a minimum defaultThickness for top and bottom.
16 | u = findU(supportedZ, railBaseThickness);
17 | railBottomThickness = railBottomThickness(u, supportedZ, railBaseThickness, zOrientation);
18 |
19 | assert(supportedX <= maxUnitWidth, "Configured supported width is too high for rack profile");
20 | assert (zOrientation == "middle" || zOrientation == "bottom", "Z-Orientation not supported");
21 | assert(railBottomThickness >= railBaseThickness);
22 | // require recessed rail if supportedX is close to maxUnitWidth
23 | assert(recess || (supportedX+2*railSideThickness <= maxUnitWidth), "Configured supported width requires recessed side rail.");
24 |
25 | railSideHeight = supportedZ + railBaseThickness + railBottomThickness + overhangSlack;
26 | frontMountPad = (sideRailScrewToMainRailFrontDx-mountBlockDepth/2);
27 |
28 | translate(v=[-railSideThickness, 0, -railBottomThickness])
29 | applyMainRailMounts()
30 | sideSupportRailBase();
31 |
32 | module applyMainRailMounts() {
33 |
34 | mountBlockExtension = (railSupportsDx - supportedX)/2 - railSideThickness;
35 | minHexNutPocketToXYDist = sideRailLowerMountPointToBottom;
36 | minHexNutPocketToXZDist = mountBlockDepth/2;
37 | minHexNutPocketToYZDist = 4;
38 | screwU = floor((railSideHeight) / uDiff)-1;
39 |
40 | apply_pn() {
41 | mountBlockPositive();
42 | mountBlockNegative();
43 | children(0);
44 | }
45 |
46 | module mountBlockPositive() {
47 | translate(v = [0, frontMountPad, 0])
48 | singleMountBlockPositive();
49 | translate(v=[0,frontMountPad+sideRailScrewMountDist, 0])
50 | singleMountBlockPositive();
51 | }
52 |
53 | module mountBlockNegative() {
54 | translate(v = [0, frontMountPad, 0])
55 | singleMountBlockNegative();
56 | translate(v=[0,frontMountPad+sideRailScrewMountDist, 0])
57 | singleMountBlockNegative();
58 | }
59 |
60 | module singleMountBlockPositive() {
61 | translate(v = [-mountBlockExtension, 0, 0])
62 | cube(size = [mountBlockExtension, mountBlockDepth, railSideHeight]);
63 | }
64 |
65 | module singleMountBlockNegative() {
66 | nutPocket();
67 |
68 | translate(v = [0, 0, uDiff*screwU])
69 | nutPocket();
70 |
71 | module nutPocket() {
72 | translate(v=[-mountBlockExtension+minHexNutPocketToYZDist, minHexNutPocketToXZDist, minHexNutPocketToXYDist])
73 | rotate(a=[-90,0,90])
74 | hexNutPocket_N(rackFrameScrewType, openSide=false, backSpace=min((railSideThickness-1)+mountBlockExtension-minHexNutPocketToYZDist,15));
75 | }
76 | }
77 | }
78 |
79 |
80 | module sideSupportRailBase() {
81 |
82 | difference () {
83 | union() {
84 | cube(size = [sideRailBaseWidth, railLength, railBottomThickness]);
85 |
86 | cube(size = [railSideThickness, railLength, railSideHeight]);
87 |
88 | // back support
89 | translate(v = [0, max(railLength-railBackThickness, supportedY), 0])
90 | cube(size = [sideRailBaseWidth, railBackThickness, railSideHeight]);
91 |
92 | // back support for box
93 | translate(v = [0, supportedY, 0])
94 | cube(size = [sideRailBaseWidth, railBackThickness, railSideHeight]);
95 |
96 | // top support
97 | if (top) {
98 | translate(v = [0, 0, railSideHeight-railBaseThickness])
99 | cube(size = [sideRailBaseWidth, railLength, railBaseThickness]);
100 | }
101 | }
102 | if (sideVent) {
103 | union() {
104 | distanceFromSeparator = 3;
105 | r = 4;
106 |
107 | ventDy1 = frontMountPad+mountBlockDepth+distanceFromSeparator;
108 | ventY1 = min(supportedY-(ventDy1+distanceFromSeparator), sideRailScrewMountDist-(2*distanceFromSeparator+mountBlockDepth));
109 |
110 | ventDy2 = max(ventDy1, supportedY+railBackThickness+distanceFromSeparator);
111 | ventY2 = max(0, railLength - (ventDy2 + distanceFromSeparator + mountBlockDepth));
112 |
113 | ventDz = railBottomThickness+distanceFromSeparator+r;
114 | ventZ = railSideHeight-(ventDz+distanceFromSeparator+r+railBaseThickness);
115 |
116 | if (ventY1 > 2*r) {
117 | translate(v = [0, ventDy1+r, ventDz])
118 | minkowski() {
119 | cube(size = [inf, ventY1-2*r, ventZ]);
120 | sphere(r = r);
121 | }
122 | }
123 |
124 | if (ventY2 > 2*r) {
125 | translate(v = [0, ventDy2+r, ventDz])
126 | minkowski() {
127 | cube(size = [inf, ventY2-2*r, ventZ]);
128 | sphere(r = r);
129 | }
130 | }
131 |
132 | frontCutTrans = recess ? translate(v=[0,frontMountPad,0]): translate(v=[0,xySlack,0]);
133 | multmatrix(frontCutTrans) {
134 | cylindricalFiletNegative(p0=[sideRailBaseWidth,0,0],p1=[sideRailBaseWidth,0,inf], n=[1,-1,0],r=r);
135 | halfspace(vpos=[0,-1,0], p=[0,0,0]);
136 | }
137 |
138 | }
139 | }
140 | }
141 | }
142 |
143 | }
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/rack-mount/patch-panel/README.md:
--------------------------------------------------------------------------------
1 | # Patch Panel
2 |
3 |
4 | 
5 |
6 | Please see [entry.scad](./entry.scad) for config and building. Make sure the correct rack profile is configured in [rackFrame.scad](../../config/rackFrame.scad).
7 |
8 | - Mount RJ-45 keystone jacks with this part.
9 | - Single part. Can be printed without supports.
10 |
11 | ### BOM:
12 |
13 | | Item | Name | Quantity | Comment |
14 | |---------------------------------------------------------------|---------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------|
15 | |
| M4x12 FHCS | 4 | Extras are useful and inexpensive. If you plan on eventually stacking multiple racks together, don't hesitate to get a lot more. |
16 | |
| M4 hex nut | 4 | ☝️ |
--------------------------------------------------------------------------------
/rack-mount/patch-panel/animate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/rack-mount/patch-panel/animate.gif
--------------------------------------------------------------------------------
/rack-mount/patch-panel/animate.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 | use <./entry.scad>
3 |
4 | $vpt = [110,-42,36];
5 | $vpr = [77,0,23];
6 | $vpd = 445;
7 | $vpf = 22.50;
8 |
9 | animatePatchPanel(at=$t);
10 |
11 | module animatePatchPanel(at=$t) {
12 |
13 | plateThickness = 3;
14 | keystoneSpacing = 19;
15 | allSlots = [2, 2, 2, 2, 2, 2, 2, 5, 2];
16 | numSlots = max(1,ceil(at*8));
17 | slots = [each [for (i=[1:numSlots]) allSlots[i]]];
18 |
19 | rotate(a=[90,0,0])
20 | render()
21 | patchPanelSystem(slots = slots, plateThickness=plateThickness, keystoneSpacing=keystoneSpacing);
22 |
23 | }
--------------------------------------------------------------------------------
/rack-mount/patch-panel/entry.scad:
--------------------------------------------------------------------------------
1 | use <./patchPanel.scad>
2 |
3 | /*
4 | Parametric patch panel for rj45 keystones
5 |
6 | Please also make sure that the correct rack frame preset is set in rackFrame.scad.
7 |
8 | TODO add support for 2d arrays
9 | */
10 |
11 | module patchPanelSystem (
12 |
13 | // begin config ////////////////////////////////////////////////////////////////////////////////////////////////////////
14 |
15 | // 1 for the original keystone mount design, 2 for a visually cleaner keystone mount
16 | // but where the keystone is a bit harder to remove
17 | // 3 for a cube with the height of plateThickness,
18 | // 4 and 5 for cubes with the same height as keystone1 and 2
19 | slots = [2, 2, 2, 2, 2, 2, 2, 5, 2],
20 | plateThickness = 3,
21 | keystoneSpacing = 19,
22 | center = false
23 |
24 | // end config //////////////////////////////////////////////////////////////////////////////////////////////////////////
25 |
26 | ) {
27 | mirror(v = [0, 0, 1])
28 | patchPanel(slots = slots, plateThickness = 3, keystoneSpacing = 19, center=center);
29 | }
30 |
31 | patchPanelSystem();
32 |
--------------------------------------------------------------------------------
/rack-mount/patch-panel/patchPanel.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 | use <../plateBase.scad>
3 |
4 | /*
5 | Parametric patch panel -
6 | Please see ./entry.scad for configuring/printing
7 |
8 | Please also make sure that the correct rack frame preset is set in rackFrame.scad.
9 | */
10 |
11 | module patchPanel(slots, plateThickness = 3, screwToXEdge = 4.5, screwToYEdge = 4.5, keystoneSpacing = 19, center = false) {
12 | slotsWidth = len(slots) * keystoneSpacing;
13 | slotsMinPadding = railScrewHoleToInnerEdge+4;
14 | plateLength = rackMountScrewWidth + 2 * screwToXEdge;
15 | plateHeight = 2 * uDiff + 2 * screwToXEdge;
16 | leftRailScrewToSlots = center
17 | ? (plateLength-(slotsWidth+slotsMinPadding))/2
18 | : slotsMinPadding;
19 |
20 | difference() {
21 | plateBase(U = 2, plateThickness = plateThickness, screwType = mainRailScrewType, screwToXEdge = screwToXEdge, screwToYEdge = screwToYEdge, filletR = 2);
22 | translate([leftRailScrewToSlots, -screwToYEdge - 10 * eps, -plateThickness - 10 * eps])
23 | cube([slotsWidth, plateHeight + 2 * 10 * eps, plateThickness + 2 * 10 * eps]);
24 | }
25 |
26 | for(i = [0 : len(slots) - 1]) {
27 | translate([leftRailScrewToSlots + keystoneSpacing / 2 + i * keystoneSpacing, uDiff, -plateThickness])
28 | let (slot = slots[i])
29 | if (slot == 1) keystone1(outerWidth = keystoneSpacing, outerHeight = plateHeight);
30 | else if (slot == 2) keystone2(outerWidth = keystoneSpacing, outerHeight = plateHeight);
31 | else if (slot == 3) plate(outerWidth = keystoneSpacing, outerHeight = plateHeight, thickness = plateThickness);
32 | else if (slot == 4) plate(outerWidth = keystoneSpacing, outerHeight = plateHeight, thickness = 5.9);
33 | else if (slot == 5) plate(outerWidth = keystoneSpacing, outerHeight = plateHeight, thickness = 9.9);
34 | else assert(false);
35 | }
36 | }
37 |
38 | module plate(outerWidth, outerHeight, thickness) {
39 | translate([0, 0, thickness / 2])
40 | cube([outerWidth, outerHeight, thickness], center = true);
41 | }
42 |
--------------------------------------------------------------------------------
/rack-mount/plateBase.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 |
3 |
4 | *plateBase(U=2, plateThickness=3, screwType="m4", filletR=2);
5 |
6 | module plateBase(U, plateThickness, screwType, screwToXEdge=4.5, screwToYEdge=4.5, filletR=2) {
7 |
8 | assert(floor(U) == U && U > 0)
9 | assert(plateThickness > 0);
10 |
11 | screwDx = rackMountScrewWidth;
12 | screwDy = uDiff * U;
13 |
14 | plateLength = screwDx + 2*screwToXEdge;
15 | plateHeight = screwDy + 2*screwToYEdge;
16 |
17 | translate(v=[-screwToXEdge,-screwToYEdge,-plateThickness]) // easier to work with
18 | difference() {
19 | base();
20 |
21 | mirror4XY(p=[screwToXEdge, screwToYEdge], dx=screwDx, dy=screwDy)
22 | translate(v=[0,0,plateThickness])
23 | cylinder(r=screwRadiusSlacked(screwType), h=inf, center=true);
24 | }
25 |
26 | module base() {
27 | minkowski() {
28 | translate(v=[filletR, filletR, 0])
29 | cube(size = [plateLength-2*filletR, plateHeight-2*filletR, plateThickness]);
30 | cylinder(r=filletR, h=eps);
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/rack-mount/rackEars.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 |
3 | // Rack ear modules.
4 | // To be used either by itself if the item supports it, or within another module
5 |
6 | rackEarModule(u=4, frontThickness=3, sideThickness=3, frontWidth=20, sideDepth=50, backPlaneHeight, support=true);
7 |
8 | module rackEarModule(
9 | u,
10 | frontThickness,
11 | sideThickness,
12 | frontWidth,
13 | sideDepth,
14 | backPlaneHeight,
15 | support=true
16 | ) {
17 |
18 | // check frontWidth is wide enough
19 | assert(frontWidth-sideThickness >= rackMountScrewXDist+railScrewHoleToInnerEdge);
20 |
21 | earHeight = u*uDiff + 2*rackMountScrewZDist;
22 |
23 | difference() {
24 | translate(v = [-rackMountScrewXDist, 0, -rackMountScrewZDist]) {
25 | // front
26 | cube(size = [frontWidth, frontThickness, earHeight]);
27 |
28 | // side
29 | hull() {
30 | translate(v = [frontWidth-sideThickness, 0, 0])
31 | cube(size = [sideThickness, frontThickness, earHeight]);
32 |
33 | backSegmentPlane();
34 | }
35 |
36 | if (support) {
37 | defaultExtraSpacing = 1;
38 | extraSpacing = frontWidth-(rackMountScrewXDist+railScrewHoleToInnerEdge+sideThickness) > defaultExtraSpacing
39 | ? defaultExtraSpacing
40 | : 0; // don't include extra spacing for support, if tray itself is too large
41 |
42 | hull() {
43 | translate(v= [rackMountScrewXDist+railScrewHoleToInnerEdge+extraSpacing,frontThickness,0])
44 | cube(size = [sideThickness, eps, earHeight]);
45 |
46 | backSegmentPlane();
47 | }
48 | }
49 | }
50 |
51 | rackMountHoles();
52 | }
53 |
54 | module backSegmentPlane() {
55 | translate(v = [frontWidth-sideThickness, sideDepth, 0])
56 | cube(size = [sideThickness, eps, backPlaneHeight]);
57 | }
58 |
59 | module rackMountHoles() {
60 | rotate(a=[90,0,0])
61 | cylinder(r=screwRadiusSlacked(mainRailScrewType), h=inf, center=true);
62 |
63 | translate(v=[0,0,u*uDiff])
64 | rotate(a=[90,0,0])
65 | cylinder(r=screwRadiusSlacked(mainRailScrewType), h=inf, center=true);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/rack-mount/tray/README.md:
--------------------------------------------------------------------------------
1 | # Tray Mounting System
2 |
3 | 
4 |
5 | Please see [entry.scad](./entry.scad) for config and building. Make sure the correct rack profile is configured in [rackFrame.scad](../../config/rackFrame.scad).
6 |
7 | - Mount on front rails.
8 | - Single part. Can be printed without supports.
9 | - Includes support for custom bottom screws (see `mountPoints` in config). This is useful for SBCs and mini PCs with bottom screws.
10 |
11 | ### BOM:
12 |
13 | | Item | Name | Quantity | Comment |
14 | |---------------------------------------------------------------|---------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------|
15 | |
| M4x12 FHCS | 4 | Extras are useful and inexpensive. If you plan on eventually stacking multiple racks together, don't hesitate to get a lot more. |
16 | |
| M4 hex nut | 4 | ☝️ |
--------------------------------------------------------------------------------
/rack-mount/tray/animate.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/rack-mount/tray/animate.gif
--------------------------------------------------------------------------------
/rack-mount/tray/animate.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 | use <./entry.scad>
3 |
4 | $vpt = [100,-42,36];
5 | $vpr = [70,0,27];
6 | $vpd = 445;
7 | $vpf = 22.50;
8 |
9 | animateTraySystem(at=$t);
10 |
11 | module animateTraySystem(at=$t) {
12 |
13 | trayU = max(1, ceil(at*3));
14 | x=100;
15 | y=100;
16 | dx = abs(lerp(a=-40, b=40, t=at));
17 | dy = abs(lerp(a=-30, b=30, t=at));
18 |
19 | traySystem(trayU=trayU, baseWidth=x+dx, baseDepth=y+dy, mountPoints=[], backLipHeight=8);
20 | }
--------------------------------------------------------------------------------
/rack-mount/tray/entry.scad:
--------------------------------------------------------------------------------
1 | use <./tray.scad>
2 |
3 | /*
4 | Parametric rack-mount tray:
5 | Dimensions can be adjusted using the variables below. You can also add mounting holes to fasten things that have
6 | screw holes at the bottom.
7 |
8 | !!! Please also make sure that the correct rack frame preset is set in rackFrame.scad !!!
9 | */
10 |
11 | module traySystem (
12 |
13 | // begin config ////////////////////////////////////////////////////////////////////////////////////////////////////////
14 |
15 | trayU = 2,
16 |
17 | // these dimensions are the total base width including padding not usable space.
18 | // e.g. 145 baseWidth and 3 sideThickness = 145-(3*2) = 139mm useable space.
19 | baseWidth = 145,
20 | baseDepth = 100,
21 |
22 | baseThickness = 3, // tray bottom thickness
23 | frontThickness = 3, // front plate thickness
24 | sideThickness = 3,
25 |
26 | backLipHeight = 2,
27 | frontLipHeight = 2,
28 |
29 | sideSupport = true,
30 | trayLeftPadding = 10, // extra space between the left rail and tray. configure this to move the tray left/right.
31 |
32 | mountPointType = "m3",
33 | mountPointElevation = 1, // basically standoff height
34 |
35 | // add/config standoff coordinates here. Format is [[x,y]]
36 | mountPoints = [
37 | [30,10],
38 | [30+75,10],
39 | [30,10+75],
40 | [30+75,10+75],
41 | ]
42 |
43 | // end config //////////////////////////////////////////////////////////////////////////////////////////////////////////
44 |
45 | ) {
46 |
47 | bottomScrewTray (
48 | u = trayU,
49 | trayWidth = baseWidth,
50 | trayDepth = baseDepth,
51 | trayThickness = baseThickness,
52 | frontLipHeight = frontLipHeight,
53 | backLipHeight = backLipHeight,
54 | mountPoints = mountPoints,
55 | frontThickness = frontThickness,
56 | sideThickness = sideThickness,
57 | mountPointElevation = mountPointElevation,
58 | mountPointType = mountPointType,
59 | sideSupport = sideSupport,
60 | trayLeftPadding = trayLeftPadding
61 | );
62 | }
63 |
64 | traySystem();
65 |
--------------------------------------------------------------------------------
/rack-mount/tray/tray.scad:
--------------------------------------------------------------------------------
1 | include <../common.scad>
2 | use <../rackEars.scad>
3 |
4 | /*
5 | Parametric rack-mount tray -
6 | Please see ./entry.scad for configuring/printing
7 |
8 | Please also make sure that the correct rack frame preset is set in rackFrame.scad.
9 | */
10 |
11 | module bottomScrewTray(u, trayWidth, trayDepth, trayThickness, mountPoints, mountPointElevation, mountPointType, frontThickness, sideThickness, frontLipHeight, backLipHeight, trayLeftPadding, sideSupport=true) {
12 |
13 | lipThickness = sideThickness;
14 |
15 | screwDx = rackMountScrewWidth; // x dist between the mount holes
16 | screwDz = uDiff * u;
17 |
18 | plateLength = screwDx + 2*rackMountScrewXDist;
19 | plateHeight = screwDz + 2*rackMountScrewZDist;
20 |
21 | minScrewToTraySpacing = railScrewHoleToInnerEdge;
22 |
23 | leftScrewDistToTray = minScrewToTraySpacing + trayLeftPadding;
24 |
25 | leftScrewGlobalX = -leftScrewDistToTray;
26 | rightScrewGlobalX = screwDx + leftScrewGlobalX;
27 |
28 | // check (tray width)+(configured extra space) fits within the rack
29 | assert(trayWidth <= screwDx-(2*minScrewToTraySpacing + trayLeftPadding));
30 |
31 | difference() {
32 | applyMountHoles()
33 | translate(v = [-sideThickness, -frontThickness, -trayThickness])
34 | body();
35 | }
36 |
37 | module body() {
38 |
39 | // base
40 | cube(size = [trayWidth, trayDepth, trayThickness]);
41 |
42 | // front lip
43 | translate(v = [0, 0, trayThickness])
44 | cube(size = [trayWidth, lipThickness, frontLipHeight]);
45 |
46 | // back lip
47 | translate(v = [0, trayDepth-lipThickness, trayThickness])
48 | cube(size = [trayWidth, lipThickness, backLipHeight]);
49 |
50 | translate(v = [leftScrewGlobalX, 0, rackMountScrewZDist])
51 | rackEarModule(frontThickness = frontThickness, sideThickness = sideThickness, frontWidth =
52 | leftScrewDistToTray+rackMountScrewXDist+sideThickness, sideDepth = trayDepth-lipThickness, u = u, backPlaneHeight=trayThickness+backLipHeight, support=sideSupport);
53 |
54 | translate(v = [rightScrewGlobalX, 0, rackMountScrewZDist])
55 | mirror(v = [1, 0, 0])
56 | rackEarModule(frontThickness = frontThickness, sideThickness = sideThickness, frontWidth =
57 | rightScrewGlobalX-trayWidth+rackMountScrewXDist+sideThickness, sideDepth = trayDepth-lipThickness, u = u, backPlaneHeight=trayThickness+backLipHeight, support=sideSupport);
58 | }
59 |
60 |
61 | module applyMountHoles() {
62 |
63 | mountPointPosThickness = 2;
64 |
65 | if (len(mountPoints) > 0) {
66 | apply_pn() {
67 | for (i = [0:len(mountPoints)-1]) {
68 | x = mountPoints[i][0];
69 | y = mountPoints[i][1];
70 |
71 | translate(v = [x, y, 0])
72 | cylinder(r = screwRadiusSlacked(mountPointType)+mountPointPosThickness, h = mountPointElevation);
73 | }
74 |
75 | for (i = [0:len(mountPoints)-1]) {
76 | x = mountPoints[i][0];
77 | y = mountPoints[i][1];
78 |
79 | translate(v = [x, y, -trayThickness])
80 | mirror(v = [0, 0, 1])
81 | counterSunkHead_N(mountPointType, inf, inf);
82 | }
83 |
84 | children(0);
85 | }
86 | } else {
87 | children(0);
88 | }
89 |
90 | }
91 |
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/rack/assembly/addMagnetsToMagnetModules.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./slideHexNutsIntoYBar.scad>
3 |
4 | $vpt = [21,-15,20];
5 | $vpr = [65,0,40];
6 | $vpd = 50;
7 | $vpf = 22.50;
8 |
9 | addMagnetsToMagnetModules(at=$t);
10 |
11 | module addMagnetsToMagnetModules(at=0) {
12 | t = lerp(a=6,b=0,t=at);
13 |
14 |
15 | if (!plasticMask) {
16 |
17 | if (fixedSideModules) {
18 | multmatrix(yBarToMagnetModuleTrans)
19 | slideHexNutsIntoYBar(at=1);
20 | }
21 | else {
22 | magnetModule();
23 | }
24 | }
25 |
26 | function insertMagnetTrans(t=0) =
27 | translate(v=[sideWallConnW-(magnetFaceToSideWallConnOuterYEdge+magnetHSlacked) + t,
28 | magnetModuleMagnetMountDy,
29 | magnetModuleMagnetMountDz]) *
30 | rotate(a=[0,90,0]);
31 |
32 |
33 |
34 | multmatrix(insertMagnetTrans(t=t))
35 | magnet();
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/rack/assembly/addMagnetsToSideWall.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 |
3 | $vpt = [23,105,70];
4 | $vpr = [84,0,133];
5 | $vpd = 370;
6 | $vpf = 22.50;
7 |
8 | addMagnetsToSideWall(at=$t);
9 |
10 | module addMagnetsToSideWall(at=0) {
11 | t = lerp(a=8,b=0,t=at);
12 |
13 | if (!plasticMask) {
14 | sideWallLeft();
15 | }
16 |
17 | function insertMagnetTrans(t=0) =
18 | translate(v=[sideWallThickness+t, magnetMountToYBarFront, magnetMountToYBarTop-sideWallZHingeTotalClearance]) *
19 | rotate(a=[0,90,0]);
20 |
21 | multmatrix(insertMagnetTrans(t=t))
22 | magnet();
23 |
24 | multmatrix(translate(v=[0,0,sideWallZ - 2*(magnetMountToYBarTop- sideWallZHingeTotalClearance)]) * insertMagnetTrans(t=t))
25 | magnet();
26 | }
--------------------------------------------------------------------------------
/rack/assembly/attachSideConnectorModulesToYBars.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./screwXBarAndYBar.scad>
3 | use <./addMagnetsToMagnetModules.scad>
4 |
5 |
6 | /*
7 | NOTE You only need to do this step if the `fixedSideModules` option is set to false.
8 | */
9 |
10 | $vpt = [116,90,18];
11 | $vpr = [56,0,42];
12 | $vpd = 550;
13 | $vpf = 22.50;
14 |
15 | attachSideConnectorModulesToYBars(at=$t);
16 |
17 | module attachSideConnectorModulesToYBars(at=0) {
18 | elevation = lerp(a=8, b=0, t=at);
19 |
20 | // side module to front corner ybar
21 | function sideModuleTrans(t=0) =
22 | translate(v=[sideWallConnW,0,t-sideWallConnLugDepression])
23 | * yBarSideModuleConnectorTrans
24 | * mirror(v=[1,0,0]); // mirror for magnetModule
25 |
26 | screwXBarAndYBar(at=1);
27 |
28 | if (!fixedSideModules) {
29 | multmatrix(sideModuleTrans(elevation))
30 | union() {
31 |
32 |
33 | addMagnetsToMagnetModules(at=1);
34 |
35 |
36 | translate(v=[yBarScrewHoleToOuterYEdge,yBarScrewHoleToFrontXEdge,sideWallConnLugDepression + 2*elevation])
37 | caseScrewShort();
38 | }
39 |
40 | multmatrix(xBarSpaceToYBarSpace * xBarMirrorOtherCornerTrans * yBarSpaceToXBarSpace * sideModuleTrans(elevation))
41 | union() {
42 |
43 | addMagnetsToMagnetModules(at=1);
44 |
45 |
46 | translate(v=[yBarScrewHoleToOuterYEdge,yBarScrewHoleToFrontXEdge,sideWallConnLugDepression + 2*elevation])
47 | caseScrewShort();
48 | }
49 |
50 | multmatrix(yBarMirrorOtherCornerTrans * sideModuleTrans(elevation))
51 | union() {
52 |
53 | if (!plasticMask) {
54 | hingeModule();
55 | }
56 |
57 | translate(v=[yBarScrewHoleToOuterYEdge,yBarScrewHoleToFrontXEdge,sideWallConnLugDepression + 2*elevation])
58 | caseScrewShort();
59 | }
60 |
61 | multmatrix(xBarSpaceToYBarSpace * xBarMirrorOtherCornerTrans * yBarSpaceToXBarSpace * yBarMirrorOtherCornerTrans * sideModuleTrans(elevation))
62 | union() {
63 | if (!plasticMask) {
64 | hingeModule();
65 | }
66 |
67 | translate(v=[yBarScrewHoleToOuterYEdge,yBarScrewHoleToFrontXEdge,sideWallConnLugDepression + 2*elevation])
68 | caseScrewShort();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/rack/assembly/attachXBarWithYBar.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./slideHexNutsIntoYBar.scad>
3 | use <./addMagnetsToMagnetModules.scad>
4 |
5 | $vpt = [116,90,18];
6 | $vpr = [56,0,42];
7 | $vpd = 550;
8 | $vpf = 22.50;
9 |
10 | attachXBarWithYBar(at=$t);
11 |
12 | module attachXBarWithYBar(at=0) {
13 |
14 | t = lerp(a=20, b=0, t=at);
15 |
16 | // assemble x-y bar trays
17 | multmatrix(translate(v = [0, 0, t]))
18 |
19 | if (fixedSideModules) {
20 | multmatrix(inv4x4(yBarToMagnetModuleTrans))
21 | addMagnetsToMagnetModules(at=1); // same as slideHexNutsIntoYBar, but the magnet has already been inserted
22 | } else {
23 | slideHexNutsIntoYBar(at=1);
24 | }
25 |
26 |
27 | multmatrix(translate(v = [0, 0, t])*xBarSpaceToYBarSpace*xBarMirrorOtherCornerTrans*yBarSpaceToXBarSpace)
28 | if (fixedSideModules) {
29 | multmatrix(inv4x4(yBarToMagnetModuleTrans))
30 | addMagnetsToMagnetModules(at=1);
31 | } else {
32 | slideHexNutsIntoYBar(at=1);
33 | }
34 |
35 | if (!plasticMask) {
36 | multmatrix(xBarSpaceToYBarSpace)
37 | xBar();
38 |
39 | multmatrix(yBarMirrorOtherCornerTrans*xBarSpaceToYBarSpace)
40 | xBar();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/rack/assembly/attachXYPlates.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./slideHexNutsIntoYBarXYPlate.scad>
3 |
4 | $vpt = [96,110,70];
5 | $vpr = [68,0,36];
6 | $vpd = 700;
7 | $vpf = 22.50;
8 |
9 | attachXYPlates(at=$t);
10 |
11 | module attachXYPlates(at=0,r=0) {
12 |
13 | t = lerp(a=10,b=0,t=at);
14 |
15 | // TODO fix xyPlate transformations
16 | function xyPlateToYBarTrans() = translate(v=[6,6,0]) * yBarBasePlateConnectorTrans;
17 |
18 | slideHexNutsIntoYBarXYPlate(at=1);
19 |
20 | multmatrix(xyPlateToYBarTrans())
21 | xyPlateWithScrews(t=t);
22 |
23 | multmatrix(upperXYTrayTrans * xyPlateToYBarTrans())
24 | xyPlateWithScrews(t=t);
25 |
26 | module xyPlateWithScrews(t=0) {
27 |
28 | module screw(t=0) {
29 | translate(v=[0,0,-t])
30 | mirror(v=[0,0,1])
31 | caseScrewMedium();
32 | }
33 |
34 | if (!plasticMask) {
35 | translate(v = [0, 0, -t])
36 | xyPlate();
37 | }
38 |
39 | screw(t=2*t);
40 |
41 | translate(v=[xyPlateConnDx, 0,0])
42 | screw(t=2*t);
43 |
44 | translate(v=[0, xyPlateConnDy,0])
45 | screw(t=2*t);
46 |
47 | translate(v=[xyPlateConnDx, xyPlateConnDy,0])
48 | screw(t=2*t);
49 | }
50 | }
--------------------------------------------------------------------------------
/rack/assembly/attachXYTrays.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./attachSideConnectorModulesToYBars.scad>
3 | use <./propUpBottomXYTraywithSideWalls.scad>
4 |
5 | $vpt = [115,58,113];
6 | $vpr = [98,0,17];
7 | $vpd = 620;
8 | $vpf = 22.50;
9 |
10 | attachXYTrays(at=$t);
11 |
12 | module attachXYTrays(at=0,r=0) {
13 |
14 | t1 = lerp(a=12, b=0, t=min(1, 2*at));
15 | t2 = lerp(a=16, b=0, t=max(0, 2*at - 1));
16 |
17 | module singleScrew() {
18 | translate(v = [mainRailSlideHexOnYBarDx, mainRailSlideHexOnYBarDy, -5])
19 | rotate(a=[-45,0,0])
20 | translate(v=[0,0,14 + t2]) // length of caseScrewLong
21 | caseScrewMedium();
22 | }
23 |
24 | translate(v=[0,0,t1])
25 | multmatrix(upperXYTrayTrans) {
26 | attachSideConnectorModulesToYBars(at=1);
27 |
28 | if (at >= 1/2) {
29 | mirrorAllTrayCornersFromYBarSpace()
30 | multmatrix(yBarMainRailConnectorTrans)
31 | singleScrew();
32 | }
33 | }
34 |
35 | propUpBottomXYTraywithSideWalls(at=1,r=r);
36 | }
37 |
--------------------------------------------------------------------------------
/rack/assembly/common.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 | include <../side/sideWallVariables.scad>
5 | include <../connector/connectors.scad>
6 | use <../mainRail.scad>
7 | use <../yBar.scad>
8 | use <../xBar.scad>
9 | use <../side/magnetModule.scad>
10 | use <../side/hingeModule.scad>
11 | use <../side/sideWallRight.scad>
12 | use <../side/sideWallLeft.scad>
13 | use <../stackEnds.scad>
14 | use <../xyPlate.scad>
15 |
16 | screwMask = false;
17 | plasticMask = false;
18 | sideSupportRailMask = true;
19 |
20 | xBarSpaceToYBarSpace =
21 | yBarXBarConnectorTrans *
22 | xBarConnectorToYBarConnectorTrans *
23 | inv4x4(xBarYBarConnectorTrans);
24 |
25 | yBarSpaceToXBarSpace =
26 | xBarYBarConnectorTrans *
27 | yBarConnectorToXBarConnectorTrans *
28 | inv4x4(yBarXBarConnectorTrans);
29 |
30 | upperXYTrayTrans =
31 | yBarMainRailConnectorTrans *
32 | mirrorMainRailOtherSideTrans *
33 | inv4x4(yBarMainRailConnectorTrans);
34 |
35 | function feetToYBarTrans(t=0) =
36 | translate(v=[connectorRectWidth/2,connectorRectDepth/2,-t]) *
37 | yBarStackConnectorTrans *
38 | mirror(v=[0,1,0]);
39 |
40 | function stackConnectorTrans(t=0) =
41 | upperXYTrayTrans *
42 | yBarStackConnectorTrans;
43 |
44 | module mirrorAllTrayCornersFromYBarSpace() {
45 | children(0);
46 |
47 | multmatrix(yBarMirrorOtherCornerTrans)
48 | children(0);
49 |
50 | multmatrix(xBarSpaceToYBarSpace * xBarMirrorOtherCornerTrans * yBarSpaceToXBarSpace * yBarMirrorOtherCornerTrans)
51 | children(0);
52 |
53 | multmatrix(xBarSpaceToYBarSpace * xBarMirrorOtherCornerTrans * yBarSpaceToXBarSpace * yBarMirrorOtherCornerTrans * yBarMirrorOtherCornerTrans)
54 | children(0);
55 | }
56 |
57 | secondStackTrans = upperXYTrayTrans * mirror(v=[0,0,1]);
58 |
59 |
60 |
61 | yBarToMagnetModuleTrans =
62 | translate(v=[13,0,sideWallConnLugDepression]) *
63 | inv4x4(yBarSideModuleConnectorTrans) *
64 | mirror(v=[1,0,0]);
65 |
66 |
67 | module caseScrewShort() {
68 | if (!screwMask) {
69 | color([1, 1, 1]) {
70 | difference() {
71 | scale(v = [0.9, 0.9, 0.9])
72 | counterSunkHead_N(rackFrameScrewType, screwExtension = 8, headExtension = 0.5);
73 |
74 | cylinder($fn = 6, r = 1.5);
75 | }
76 | }
77 | }
78 | }
79 |
80 | module caseScrewMedium() {
81 | if (!screwMask) {
82 | color([1, 1, 1]) {
83 | difference() {
84 | scale(v = [0.9, 0.9, 0.9])
85 | counterSunkHead_N(rackFrameScrewType, screwExtension = 12, headExtension = 0.5);
86 |
87 | cylinder($fn = 6, r = 1.5);
88 | }
89 | }
90 | }
91 | }
92 |
93 | module caseScrewLong() {
94 | if (!screwMask) {
95 | color([1, 1, 1]) {
96 | difference() {
97 | scale(v = [0.9, 0.9, 0.9])
98 | counterSunkHead_N(rackFrameScrewType, screwExtension = 16, headExtension = 0.5);
99 |
100 | cylinder($fn = 6, r = 1.5);
101 | }
102 | }
103 | }
104 | }
105 |
106 | module hingeDowel() {
107 | if (!screwMask) {
108 | color([0, 1, 1])
109 | cylinder(h = dowelPinH, r = dowelPinR);
110 | }
111 | }
112 |
113 |
114 | module magnet() {
115 | if (!screwMask) {
116 | color([1, 1, 1])
117 | cylinder(r = magnetR, h = magnetH);
118 | }
119 | }
120 |
121 | module arrow(length) {
122 | color([1,0,1]) {
123 | translate(v = [0, 0, length-2])
124 | cylinder(r1 = 2, r2 = 0.2, h = 2);
125 |
126 | cylinder(r = 1, h = length-2);
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/rack/assembly/connectXYTrayWithMainRails.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./attachSideConnectorModulesToYBars.scad>
3 |
4 | $vpt = [96,110,70];
5 | $vpr = [68,0,36];
6 | $vpd = 700;
7 | $vpf = 22.50;
8 |
9 | connectXYTrayWithMainRails(at=$t);
10 |
11 | module connectXYTrayWithMainRails(at=0) {
12 |
13 | attachSideConnectorModulesToYBars(at=1);
14 |
15 | function mainRailTrans() =
16 | yBarMainRailConnectorTrans;
17 |
18 | module railAndScrew(at) {
19 | t1 = lerp(a=12, b=0, t=min(1, 2*at));
20 | t2 = lerp(a=16, b=0, t=max(0, 2*at - 1));
21 |
22 | if (!plasticMask) {
23 | translate(v=[0,0,t1])
24 | mainRail();
25 | }
26 |
27 | if (at >= 1/2) {
28 | multmatrix(
29 | translate(v = [mainRailSlideHexOnYBarDx, mainRailSlideHexOnYBarDy, -5])*
30 | rotate(a = [-45, 0, 0]))
31 | translate(v = [0, 0, 14 + t2]) // length of caseScrewLong
32 | caseScrewLong();
33 | }
34 | }
35 |
36 | multmatrix(mainRailTrans())
37 | railAndScrew(at=at);
38 |
39 | multmatrix(yBarMirrorOtherCornerTrans * mainRailTrans())
40 | railAndScrew(at=at);
41 |
42 | multmatrix(xBarSpaceToYBarSpace * xBarMirrorOtherCornerTrans * yBarSpaceToXBarSpace * mainRailTrans())
43 | railAndScrew(at=at);
44 |
45 | multmatrix(xBarSpaceToYBarSpace * xBarMirrorOtherCornerTrans * yBarSpaceToXBarSpace * yBarMirrorOtherCornerTrans * mainRailTrans())
46 | railAndScrew(at=at);
47 | }
--------------------------------------------------------------------------------
/rack/assembly/finalBuilds.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | include <./screwFeet.scad>
3 |
4 | // TODO fix this
5 | module finalBuilds () {
6 |
7 | // Final builds:
8 | // render()
9 | // finalSingle();
10 | // finalDouble();
11 |
12 | // Features:
13 | // render()
14 | // slideInNuts(at=$t);
15 | // stackable(at=$t);
16 | // sideSwivel(at=$t);
17 |
18 | module finalSingle(r=0) {
19 | screwFeet(at=1,r=r);
20 |
21 | for (i = [1, 5, 9, 13, 17]) {
22 | translate(v = [2, frontScrewSpacing+railFrontThickness+railSlotToXZ, i*10])
23 | multmatrix(yBarMainRailConnectorTrans)
24 | union() {
25 | if (!sideSupportRailMask) {
26 | sideSupportRailBase("lBracket");
27 | }
28 |
29 | rotate(a = [0, -90, 0])
30 | caseScrewMedium();
31 |
32 | translate(v = [0, sideRailScrewMountDist, 0])
33 | rotate(a = [0, -90, 0])
34 | caseScrewMedium();
35 | }
36 | }
37 |
38 | multmatrix(xBarSpaceToYBarSpace*xBarMirrorOtherCornerTrans*yBarSpaceToXBarSpace)
39 | for (i = [1, 5, 9, 13, 17]) {
40 | translate(v = [2, frontScrewSpacing+railFrontThickness+railSlotToXZ, i*10])
41 | multmatrix(yBarMainRailConnectorTrans)
42 | union() {
43 | if (!sideSupportRailMask) {
44 | sideSupportRailBase("lBracket");
45 | }
46 | rotate(a=[0,-90,0])
47 | caseScrewMedium();
48 |
49 | translate(v=[0,sideRailScrewMountDist,0])
50 | rotate(a=[0,-90,0])
51 | caseScrewMedium();
52 | }
53 | }
54 | }
55 |
56 |
57 | module finalDouble(r=0) {
58 | stackable(at=1,r=r);
59 | }
60 |
61 | module slideInNuts(at=0) {
62 |
63 | t = lerp(a=15,b=0,t=at);
64 |
65 | screwFeet(at=1);
66 |
67 | slideInScrew(t=t, i=1);
68 | slideInScrew(t=t, i=4);
69 |
70 | module slideInScrew(t=0, i=1) {
71 | translate(v = [railScrewHoleToOuterEdge + t, railFrontThickness/2, railFootThickness+(10*i)])
72 | multmatrix(yBarMainRailConnectorTrans)
73 | rotate(a = [90, 0, 0])
74 | hexNut(mainRailScrewType);
75 | }
76 | }
77 |
78 | module slideInStackConnectorNut(at=0) {
79 |
80 | t = lerp(a=10,b=0,t=at);
81 |
82 | module slidingNut(t=0) {
83 | translate(v=[connectorRectWidth/2,connectorRectDepth/2 - t,connectorBottomToScrew+stackConnectorDualSpacing/2])
84 | rotate(a=[90,0,0])
85 | rotate(a=[0,90,0])
86 | hexNut(rackFrameScrewType);
87 | }
88 |
89 | slidingNut(t=t);
90 |
91 | mirror(v=[0,0,1])
92 | slidingNut(t=t);
93 |
94 | translate(v=[0,connectorRectDepth,0])
95 | mirror(v=[0,1,0])
96 | stackConnectorDual();
97 | }
98 |
99 | module stackable(at=0,r=0) {
100 |
101 | t1 = lerp(a=0, b=1, t=min(3*at, 1));
102 | t2 = lerp(a=30, b=0, t=min(max(3*at-1,0),1));
103 | t3 = lerp(a=15, b=0, t=max(3*at-2, 0));
104 |
105 | module stackConnectors() {
106 | mirrorAllTrayCornersFromYBarSpace()
107 | multmatrix(stackConnectorTrans(t=0))
108 | slideInStackConnectorNut(t1);
109 | }
110 |
111 | module singleTrayScrews() {
112 | screwTrans = feetToYBarTrans(t=0) * translate(v=[-t3 - 9,0,connectorBottomToScrew]) * rotate(a=[0,-90,0]);
113 |
114 | mirrorAllTrayCornersFromYBarSpace()
115 | multmatrix(screwTrans)
116 | caseScrewLong();
117 | }
118 |
119 | if (!plasticMask) {
120 | translate(v = [0, 0, t2/2])
121 | stackConnectors();
122 | }
123 |
124 | if (at >= 2/3) {
125 | multmatrix(secondStackTrans)
126 | singleTrayScrews();
127 |
128 | multmatrix(upperXYTrayTrans)
129 | singleTrayScrews();
130 | }
131 |
132 | translate(v=[0,0,t2])
133 | multmatrix(secondStackTrans)
134 | attachXYPlates(at=1,r=r);
135 |
136 | screwFeet(at=1,r=20);
137 |
138 | }
139 |
140 | module sideSwivel(at=0) {
141 | r = abs(lerp(a=-110,b=110,t=at));
142 |
143 | finalSingle(r=r);
144 | }
145 |
146 |
147 | }
--------------------------------------------------------------------------------
/rack/assembly/insertDowelsIntoSideWall.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./addMagnetsToSideWall.scad>
3 |
4 | $vpt = [65,120,96];
5 | $vpr = [66,0,112];
6 | $vpd = 500;
7 | $vpf = 22.50;
8 |
9 | insertDowelsIntoSideWall(at=$t);
10 |
11 | module insertDowelsIntoSideWall(at=0) {
12 |
13 | t = lerp(a=10, b=0, t=at);
14 |
15 | hingeHoleH = hingePoleH-sideWallConnLugDepression;
16 |
17 | addMagnetsToSideWall(at=1);
18 |
19 | translate(v=[hingePoleDx,hingePoleDy, (sideWallZ-hingeHoleH) + t])
20 | hingeDowel();
21 |
22 | translate(v=[hingePoleDx,hingePoleDy, (hingeHoleH-hingePoleH)-t])
23 | hingeDowel();
24 |
25 | }
--------------------------------------------------------------------------------
/rack/assembly/insertFeet.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./slideHexNutToFeet.scad>
3 | use <./attachXYPlates.scad>
4 |
5 | $vpt = [95,90,10];
6 | $vpr = [105,0,38];
7 | $vpd = 650;
8 | $vpf = 22.50;
9 |
10 | insertFeet(at=$t);
11 |
12 | module insertFeet(at=0,r=0) {
13 |
14 | t = lerp(a=10,b=0,t=at);
15 |
16 | attachXYPlates(at=1,r=r);
17 |
18 | multmatrix(feetToYBarTrans(t=t))
19 | slideHexNutToFeet(at=1);
20 |
21 | multmatrix(yBarMirrorOtherCornerTrans * feetToYBarTrans(t=t))
22 | slideHexNutToFeet(at=1);
23 | }
24 |
25 | module screwFeet(at=0,r=0) {
26 |
27 | t = lerp(a=20, b=0, t=at);
28 |
29 | function screwTrans(t=0) = translate(v=[-t - 9,0,connectorBottomToScrew]) * rotate(a=[0,-90,0]);
30 | mirrorOtherFeetStackConnectorTrans = translate(v=[stackConnectorDx,0,0]) * mirror(v=[1,0,0]);
31 |
32 |
33 | module screwToFeetModule() {
34 | multmatrix(feetToYBarTrans(t = 0)*screwTrans(t = t))
35 | caseScrewLong(); // we might want a longer screw?
36 |
37 | multmatrix(feetToYBarTrans(t = 0)*mirrorOtherFeetStackConnectorTrans*screwTrans(t = t))
38 | caseScrewLong();
39 | }
40 |
41 | screwToFeetModule();
42 |
43 | multmatrix(yBarMirrorOtherCornerTrans)
44 | screwToFeetModule();
45 |
46 | insertFeet(at=1,r=r);
47 | }
48 |
--------------------------------------------------------------------------------
/rack/assembly/propUpBottomXYTraywithSideWalls.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./insertDowelsIntoSideWall.scad>
3 | use <./connectXYTrayWithMainRails.scad>
4 |
5 | $vpt = [96,110,70];
6 | $vpr = [68,0,36];
7 | $vpd = 700;
8 | $vpf = 22.50;
9 |
10 | propUpBottomXYTraywithSideWalls(at=$t, r=0);
11 |
12 | module propUpBottomXYTraywithSideWalls(at=0, r=0) {
13 |
14 | t = lerp(a=10,b=0,t=at);
15 |
16 | function sideWallToYBarTrans(t=0,r=0) =
17 | yBarMirrorOtherCornerTrans *
18 | yBarSideModuleConnectorTrans * // bring to y bar space
19 | mirror(v=[0,1,0]) *
20 | translate(v=[0,0,t]) *
21 | translate(v=[sideWallConnW/2.0, -hingePoleR, sideWallZHingeTotalClearance]) * // bring to side module space
22 | rotate(a=[0,0,-r]) *
23 | translate(v=[-hingePoleDx, -hingePoleDy, 0]);
24 |
25 | connectXYTrayWithMainRails(at=1);
26 |
27 | multmatrix(sideWallToYBarTrans(t=t, r=r))
28 | insertDowelsIntoSideWall(at=1);
29 |
30 | multmatrix(xBarSpaceToYBarSpace * xBarMirrorOtherCornerTrans * yBarSpaceToXBarSpace * sideWallToYBarTrans(t=t,r=r))
31 | insertDowelsIntoSideWall(at=1);
32 | }
--------------------------------------------------------------------------------
/rack/assembly/screwFeet.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./insertFeet.scad>
3 |
4 | $vpt = [95,90,10];
5 | $vpr = [105,0,38];
6 | $vpd = 650;
7 | $vpf = 22.50;
8 |
9 | screwFeet(at=$t);
10 |
11 | module screwFeet(at=0,r=0) {
12 |
13 | t = lerp(a=20, b=0, t=at);
14 |
15 | function screwTrans(t=0) = translate(v=[-t - 9,0,connectorBottomToScrew]) * rotate(a=[0,-90,0]);
16 | mirrorOtherFeetStackConnectorTrans = translate(v=[stackConnectorDx,0,0]) * mirror(v=[1,0,0]);
17 |
18 |
19 | module screwToFeetModule() {
20 | multmatrix(feetToYBarTrans(t = 0)*screwTrans(t = t))
21 | caseScrewMedium();
22 |
23 | multmatrix(feetToYBarTrans(t = 0)*mirrorOtherFeetStackConnectorTrans*screwTrans(t = t))
24 | caseScrewMedium();
25 | }
26 |
27 | screwToFeetModule();
28 |
29 | multmatrix(yBarMirrorOtherCornerTrans)
30 | screwToFeetModule();
31 |
32 | insertFeet(at=1,r=r);
33 | }
34 |
--------------------------------------------------------------------------------
/rack/assembly/screwXBarAndYBar.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./attachXBarWithYBar.scad>
3 |
4 | $vpt = [103,90,20];
5 | $vpr = [68,0,36];
6 | $vpd = 500;
7 | $vpf = 22.50;
8 |
9 | screwXBarAndYBar(at=$t);
10 |
11 | module screwXBarAndYBar(at=0) {
12 | screwExtension = lerp(a=16, b=0, t=at);
13 |
14 | // in x bar space
15 | function xBarYBarScrewTrans(extension) =
16 | translate(v=[27,xBarSideThickness + extension,8]) * rotate(a=[270,0,0]);
17 |
18 | attachXBarWithYBar(at=1);
19 |
20 | multmatrix(xBarSpaceToYBarSpace)
21 | union() {
22 |
23 | if (!plasticMask) { xBar(); }
24 |
25 | multmatrix(xBarYBarScrewTrans(screwExtension))
26 | caseScrewLong();
27 |
28 | multmatrix(xBarMirrorOtherCornerTrans * xBarYBarScrewTrans(screwExtension))
29 | caseScrewLong();
30 | }
31 |
32 | multmatrix(yBarMirrorOtherCornerTrans*xBarSpaceToYBarSpace)
33 | union() {
34 | if (!plasticMask) { xBar(); }
35 |
36 | multmatrix(xBarYBarScrewTrans(screwExtension))
37 | caseScrewLong();
38 |
39 | multmatrix(xBarMirrorOtherCornerTrans * xBarYBarScrewTrans(screwExtension))
40 | caseScrewLong();
41 | }
42 | }
--------------------------------------------------------------------------------
/rack/assembly/slideHexNutToFeet.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 |
3 | $vpt = [75,-10,-14];
4 | $vpr = [74,0,120];
5 | $vpd = 300;
6 | $vpf = 22.50;
7 |
8 | slideHexNutToFeet(at=$t);
9 |
10 | module slideHexNutToFeet(at=0) {
11 |
12 | t = lerp(a=8, b=0, t=at);
13 |
14 | module slideNut() {
15 | if (!screwMask) {
16 | rotate(a = [0, 0, 90])
17 | rotate(a = [90, 0, 0])
18 | hexNut(rackFrameScrewType);
19 | }
20 | }
21 |
22 | translate(v=[0,t,connectorBottomToScrew + 0.5]) // where does this come from again? slack?
23 | slideNut();
24 |
25 | translate(v=[stackConnectorDx,t,connectorBottomToScrew + 0.5]) // where does this come from again? slack?
26 | slideNut();
27 |
28 | if (!plasticMask) {
29 | rackFeet();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/rack/assembly/slideHexNutsIntoYBar.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 |
3 | $vpt = [43,66,41];
4 | $vpr = [44,0,47];
5 | $vpd = 350;
6 | $vpf = 22.50;
7 |
8 | slideHexNutsIntoYBar(at=$t);
9 |
10 | module slideHexNutsIntoYBar(at=0)
11 | {
12 |
13 | t = lerp(a=20,b=0,t=at);
14 |
15 | if (!plasticMask) {
16 | yBar();
17 | }
18 |
19 | function sideModuleTrans(t=0) =
20 | yBarSideModuleConnectorTrans *
21 | translate(v = [yBarScrewHoleToOuterYEdge, yBarScrewHoleToFrontXEdge+t, -(4+sideWallConnLugDepression)]) *
22 | rotate(a=[0,0,90]);
23 |
24 | function mainRailTrans(t=0) =
25 | yBarMainRailConnectorTrans *
26 | translate(v = [mainRailSlideHexOnYBarDx+t, mainRailSlideHexOnYBarDy, -5]) *
27 | rotate(a=[-45,0,0]);
28 |
29 | function xBarTrans(t=0) =
30 | translate(v = [-5, 27, 8+t]) *
31 | yBarXBarConnectorTrans *
32 | rotate(a=[0,90,0]);
33 |
34 | module slideHexNutsOneCorner(t=0) {
35 |
36 | if (!fixedSideModules) {
37 | multmatrix(sideModuleTrans(t = t))
38 | hexNut(rackFrameScrewType);
39 | }
40 |
41 | multmatrix(mainRailTrans(t = t))
42 | hexNut(rackFrameScrewType);
43 |
44 | multmatrix(xBarTrans(t = t))
45 | hexNut(rackFrameScrewType);
46 | }
47 |
48 | if (!screwMask) {
49 | slideHexNutsOneCorner(t = t);
50 |
51 | multmatrix(yBarMirrorOtherCornerTrans)
52 | slideHexNutsOneCorner(t = t);
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/rack/assembly/slideHexNutsIntoYBarXYPlate.scad:
--------------------------------------------------------------------------------
1 | include <./common.scad>
2 | use <./attachXYTrays.scad>
3 |
4 | $vpt = [71,123,88];
5 | $vpr = [44,0,47];
6 | $vpd = 450;
7 | $vpf = 22.50;
8 |
9 | slideHexNutsIntoYBarXYPlate(at=$t);
10 |
11 | module slideHexNutsIntoYBarXYPlate(at=0) {
12 |
13 | t = lerp(a=12,b=0,t=at);
14 |
15 | attachXYTrays(at=1,r=0);
16 |
17 | slideHexNuts(t=t);
18 |
19 | multmatrix(upperXYTrayTrans)
20 | slideHexNuts(t=t);
21 |
22 | module plateHexNut(t) {
23 | multmatrix(yBarBasePlateConnectorTrans)
24 | translate(v=[basePlateYBarSlideNutDx+t, basePlateYBarSlideNutDy, 4 + plateBlockBaseConnRecession]) // TODO gotta rename these
25 | hexNut(rackFrameScrewType);
26 | }
27 |
28 | module slideHexNuts(t=0) {
29 |
30 | plateHexNut(t=t);
31 |
32 | translate(v=[xyPlateConnDx, 0,0])
33 | plateHexNut(t=-t);
34 |
35 | translate(v=[0, xyPlateConnDy,0])
36 | plateHexNut(t=t);
37 |
38 | translate(v=[xyPlateConnDx, xyPlateConnDy,0])
39 | plateHexNut(t=-t);
40 | }
41 | }
--------------------------------------------------------------------------------
/rack/connector/basePlateYBarConnectors.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 |
5 | connectorTopThickness = screwRadiusSlacked(rackFrameScrewType)+0.5;
6 |
7 | module onYBarBasePlateConnectorPositive() {
8 | translate(v=[0,0,yBarWallThickness])
9 | intersection() {
10 | cube(size = [yBarXYPlateBlockX, yBarXYPlateBlockY, yBarXYPlateBlockZ]);
11 | halfspace(vpos=[0, -1, -1], p=[0, yBarXYPlateBlockY-1, yBarXYPlateBlockZ-1]);
12 | }
13 | }
14 |
15 | module onYBarBasePlateConnectorNegative() {
16 |
17 | translate(v=[basePlateYBarSlideNutDx, basePlateYBarSlideNutDy, 4 + plateBlockBaseConnRecession])
18 | mirror(v=[0,0,1])
19 | hexNutPocket_N("m3", openSide=false, backSpace=5, bridgeBack=true);
20 |
21 | hull() {
22 | // This has always been a pretty annoying to fit part. Increasing slack to 2*radiusXYSlack to compensate. TODO fix
23 | translate(v = [basePlateYBarSlideNutDx, basePlateYBarSlideNutDy, plateBlockBaseConnRecession+overhangSlack])
24 | roundCutSlice(radius = connectorTopThickness+2*radiusXYSlack);
25 |
26 | translate(v = [basePlateYBarSlideNutDx, basePlateYBarSlideNutDy, 0])
27 | roundCutSlice(radius = plateBlockBaseConnY/2 + 2*radiusXYSlack);
28 | }
29 |
30 | }
31 |
32 | module onBasePlateToYBarConnectorPositive() {
33 |
34 | union() {
35 | translate(v=[basePlateConnPosX, basePlateConnPosY, 0])
36 | yBarConnector();
37 |
38 | translate(v=[basePlateConnPosX, basePlateConnPosY+xyPlateConnDy, 0])
39 | yBarConnector();
40 |
41 | translate(v=[basePlateConnPosX+xyPlateConnDx, basePlateConnPosY, 0])
42 | rotate(a=[0,0,180])
43 | yBarConnector();
44 |
45 | translate(v=[basePlateConnPosX+xyPlateConnDx, basePlateConnPosY+xyPlateConnDy, 0])
46 | rotate(a=[0,0,180])
47 | yBarConnector();
48 |
49 | }
50 |
51 | module yBarConnector() {
52 | difference() {
53 | hull() {
54 | translate(v=[0,0,plateBlockBaseConnRecession])
55 | roundCutSlice(radius = connectorTopThickness, length=5);
56 |
57 | roundCutSlice(radius = plateBlockBaseConnY/2, length=15);
58 | }
59 | mirror(v=[0,0,1])
60 | counterSunkHead_N(rackFrameScrewType, headExtension = eps, screwExtension = inf10);
61 |
62 | }
63 | }
64 | }
65 |
66 | module roundCutSlice(radius, length=inf50) {
67 |
68 | hull() {
69 | cylinder(r = radius, h = eps);
70 |
71 | translate(v = [length, -radius, 0])
72 | cube(size = [eps, radius*2, eps]);
73 | }
74 | }
--------------------------------------------------------------------------------
/rack/connector/connectors.scad:
--------------------------------------------------------------------------------
1 | // Connector Aggregator and utils
2 |
3 | include <../../helper/common.scad>
4 | include <../../config/common.scad>
5 | include <./xBarYBarConnectors.scad>
6 | include <./mainRailYBarConnectors.scad>
7 | include <./sideModuleYBarConnectors.scad>
8 | include <./stackYBarConnectors.scad>
9 | include <./basePlateYBarConnectors.scad>
10 | include <./transformations.scad>
11 |
12 | // Default is to apply the positive first
13 | module applyConnector(on, to, trans) {
14 |
15 | apply_pn() {
16 | multmatrix(trans)
17 | connectorPositive(on=on, to=to);
18 |
19 | multmatrix(trans)
20 | connectorNegative(on=on, to=to);
21 |
22 | children(0);
23 | }
24 | }
25 |
26 | module connectorDebug(on, to, trans) {
27 |
28 | color([0,1,0])
29 | multmatrix(trans)
30 | connectorPositive(on=on, to=to);
31 |
32 | color([1,0,0])
33 | multmatrix(trans)
34 | connectorNegative(on=on, to=to);
35 | }
36 |
37 | module applyConnectorDebug(on,to,trans) {
38 |
39 | echo("on: ", on, "-- to:", to);
40 |
41 | apply_p() {
42 | multmatrix(trans)
43 | connectorDebug(on=on,to=to,trans=trans);
44 |
45 | children(0);
46 | }
47 | }
48 |
49 | module connectorPositive(on, to) {
50 |
51 | if (on == "yBar" && to == "xBar") {
52 | onYBarToXBarPositive();
53 | } else if (on == "yBar" && to == "basePlate") {
54 | onYBarBasePlateConnectorPositive();
55 | } else if (on == "yBar" && to == "magnetModule") {
56 | onYBarMagnetModulePositive();
57 | } else if (on == "yBar" && to == "hingeModule") {
58 | onYBarHingeModulePositive();
59 | } else if (on == "basePlate" && to == "yBar") {
60 | onBasePlateToYBarConnectorPositive();
61 | } else if (on == "xBar" && to == "yBar") {
62 | onXBarToYBarPositive();
63 | } else if (on == "mainRail" && to == "yBar") {
64 | onMainRailYBarConnectorPositive();
65 | }
66 | }
67 |
68 | module connectorNegative(on, to) {
69 |
70 | if (on == "yBar" && to == "xBar") {
71 | onYBarToXBarNegative();
72 | } else if (on == "xBar" && to == "yBar") {
73 | onXBarToYBarNegative();
74 | } else if (on == "yBar" && to == "sideModule") {
75 | onYBarSideModuleNegative();
76 | } else if (on == "yBar" && to == "hingeModule") {
77 | onYBarHingeModuleNegative();
78 | } else if (on == "yBar" && to == "mainRail") {
79 | onYBarToMainRailNegative();
80 | } else if (on == "yBar" && to == "stackConnector") {
81 | onYBarStackConnectorNegative();
82 | } else if (on == "yBar" && to == "basePlate") {
83 | onYBarBasePlateConnectorNegative();
84 | } else if (on == "mainRail" && to == "yBar") {
85 | onMainRailYBarConnectorNegative();
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/rack/connector/mainRailYBarConnectors.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 |
5 | mainRailSlideHexOnYBarDx = railSideMountThickness + 5;
6 | mainRailSlideHexOnYBarDy = railFrontThickness + 2;
7 |
8 | module onYBarToMainRailNegative() {
9 |
10 | slotSlack = xySlack;
11 | slotZSlack = zSlack;
12 |
13 | union() {
14 | translate(v=[-slotZSlack/2, -slotSlack/2,0])
15 | cube(size = [railTotalWidth+slotZSlack, railTotalDepth + slotSlack, railFootThickness]);
16 |
17 | translate(v = [mainRailSlideHexOnYBarDx, mainRailSlideHexOnYBarDy, -5])
18 | rotate(a=[-45,0,0])
19 | hexNutPocket_N("m3", openSide=false, backSpace=5);
20 | }
21 | }
22 |
23 | module onMainRailYBarConnectorPositive() {
24 | cube(size = [frontFaceWidth, sideSupportDepth+railFrontThickness, railFootThickness]);
25 |
26 | // TODO magic numbers
27 | hull() {
28 | cube(size = [frontFaceWidth, railFrontThickness+8, railFootThickness+4]);
29 | translate(v = [0, railFrontThickness+14, 0])
30 | cube(size = [frontFaceWidth, 1, railFootThickness]);
31 | }
32 | }
33 |
34 |
35 | module onMainRailYBarConnectorNegative() {
36 |
37 | screwOffset = 9;
38 |
39 | translate(v = [mainRailSlideHexOnYBarDx, mainRailSlideHexOnYBarDy + screwOffset, -5 + screwOffset])
40 | rotate(a=[-45,0,0])
41 | counterSunkHead_N(rackFrameScrewType, screwExtension=inf50, headExtension=inf50);
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/rack/connector/sideModuleYBarConnectors.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 | include <../side/sideWallVariables.scad>
5 | include <../side/magnetModule.scad>
6 | include <../side/hingeModule.scad>
7 |
8 |
9 | module onYBarSideModuleNegative(fixed=false) {
10 |
11 | translate(v = [-xySlack/2, -xySlack/2, -sideWallConnLugDepression])
12 | cube(size = [sideWallConnW+xySlack, sideWallConnD+xySlack, sideWallConnLugDepression]);
13 |
14 |
15 | if (!fixed) {
16 | translate(v = [yBarScrewHoleToOuterYEdge, yBarScrewHoleToFrontXEdge, -(4+sideWallConnLugDepression)])
17 | rotate(a=[0,0,90])
18 | hexNutPocket_N("m3", openSide=false, backSpace=5, bridgeFront=true);
19 | }
20 | }
21 |
22 |
23 | module onYBarMagnetModulePositive() {
24 |
25 |
26 | translate(v=[sideWallConnW,0,-sideWallConnLugDepression])
27 | mirror(v=[1,0,0])
28 | magnetModule(fixed=true);
29 |
30 |
31 | }
32 |
33 | module onYBarHingeModulePositive() {
34 |
35 | translate(v=[sideWallConnW,0,-sideWallConnLugDepression])
36 | mirror(v=[1,0,0])
37 | hingeModule(fixed=false);
38 | }
39 |
40 | module onYBarHingeModuleNegative() {
41 |
42 | translate(v=[sideWallConnW,0,-sideWallConnLugDepression])
43 | mirror(v=[1,0,0])
44 | difference() {
45 | cube(size=[sideWallConnW,sideWallConnD,sideWallConnLugDepression]);
46 | hingeModule(fixed=true);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/rack/connector/stackYBarConnectors.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 |
5 |
6 | module stackConnectorBase(rectSlack, topSlack=0.0) {
7 |
8 | wSlacked = connectorRectWidth + rectSlack;
9 | dSlacked = connectorRectDepth + rectSlack;
10 | topRSlacked = connectorTopR + rectSlack/2;
11 |
12 | module connRect() {
13 | linear_extrude(height=eps)
14 | square(size = [wSlacked, dSlacked]);
15 | }
16 |
17 | module connTop() {
18 | linear_extrude(height=eps)
19 | circle(r=topRSlacked);
20 | }
21 |
22 | hull() {
23 | connRect();
24 |
25 | translate(v=[0,0,connectorTaperStartHeight])
26 | connRect();
27 | }
28 |
29 | hull() {
30 | translate(v = [0, 0, connectorTaperStartHeight])
31 | connRect();
32 |
33 | translate(v=[wSlacked/2, dSlacked/2, connectorTotalHeight+topSlack])
34 | connTop();
35 | }
36 | }
37 |
38 |
39 | module onYBarStackConnectorNegative() {
40 |
41 | wSlacked = connectorRectWidth + connectorRectSocketSlack;
42 | dSlacked = connectorRectDepth + connectorRectSocketSlack;
43 |
44 | bevelSlack = 0.6;
45 | bevelR = wSlacked + bevelSlack;
46 | bevelW = dSlacked + bevelSlack;
47 | bevelH = 0.6;
48 |
49 | screwExtension = 4;
50 |
51 |
52 | union() {
53 | stackConnectorBase(connectorRectSocketSlack, topSlack=0.4);
54 |
55 | translate(v = [-screwExtension, connectorRectDepth/2, connectorBottomToScrew])
56 | rotate(a = [0, -90, 0])
57 | counterSunkHead_N(rackFrameScrewType, screwExtension = 5, headExtension = 10);
58 |
59 | // bevel at the lip of the socket to guide the plug, as well as mitigate elephant foot during 3d printing
60 | hull() {
61 | translate(v = [0, 0, bevelH])
62 | linear_extrude(height = eps)
63 | square(size = [wSlacked, dSlacked]);
64 |
65 | translate(v = [-bevelSlack/2, -bevelSlack/2, 0])
66 | linear_extrude(height = eps)
67 | square(size = [bevelR, bevelW]);
68 | }
69 | }
70 | }
71 |
72 |
73 | module stackConnectorPlug() {
74 |
75 | difference() {
76 | stackConnectorBase(connectorRectPlugSlack);
77 |
78 | translate(v=[connectorRectWidth/2,connectorRectDepth/2,connectorBottomToScrew])
79 | rotate(a=[0,0,90])
80 | rotate(a=[90,0,0])
81 | hexNutPocket_N(rackFrameScrewType, openSide=false);
82 | }
83 | }
84 |
85 | module stackConnectorBottom() {
86 |
87 | height = 2; // space between bottom and floor
88 |
89 | stackConnectorPlug();
90 | translate(v=[0,0,-height])
91 | cube(size=[connectorRectWidth+connectorRectPlugSlack, connectorRectDepth+connectorRectPlugSlack, height]);
92 | }
93 |
--------------------------------------------------------------------------------
/rack/connector/transformations.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 |
5 | // Y-bar
6 | yBarMirrorOtherCornerTrans = translate(v = [0, yBarDepth, 0]) * mirror(v = [0, 1, 0]);
7 |
8 | yBarBasePlateConnectorTrans = translate(v = [yBarWidth-yBarBasePlateConnectorWidth, joinCornerDepth, 0]);
9 |
10 | yBarStackConnectorTrans = translate(v = [connectorXEdgeToYBarXEdge, connectorYEdgeToYBarYEdge, 0]);
11 |
12 | yBarSideModuleConnectorTrans = translate(v = [
13 | yBarWidth-(railTotalWidth+railSlotToInnerYEdge+railSlotToSideWallSlot+sideWallConnectorSlotWidth),
14 | sideWallSlotToXZ,
15 | yBarHeight
16 | ]);
17 |
18 | yBarMainRailConnectorTrans = translate(v = [
19 | yBarWidth-(railTotalWidth+railSlotToInnerYEdge),
20 | railSlotToXZ,
21 | yBarHeight-railFootThickness
22 | ]);
23 |
24 | yBarXBarConnectorTrans = translate(v = [yBarWidth+eps, 0, 0]);
25 |
26 |
27 | // X-bar
28 | xBarYBarConnectorTrans = rotate(a=[0,0,-90]);
29 | xBarMirrorOtherCornerTrans = translate(v = [0, xBarX, 0]) * mirror(v = [0, 1, 0]);
30 |
31 |
32 | // Main rail
33 | mirrorMainRailOtherSideTrans = translate(v = [0, 0, railTotalHeight]) * mirror(v=[0,0,1]);
34 |
35 |
--------------------------------------------------------------------------------
/rack/connector/xBarYBarConnectors.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 |
5 | // On xBar
6 | module onXBarToYBarNegative() {
7 | y = 27;
8 | z = 8;
9 | slack = xBarYBarDovetailSlack;
10 |
11 | translate(v=[-1,14,0])
12 | mirror(v=[1,0,0])
13 | rotate(a=[0,0,-90])
14 | dovetail(
15 | topWidth = 15+slack,
16 | bottomWidth = 12+slack,
17 | height = 2,
18 | length = yBarHeight,
19 | headExtension = 1+slack,
20 | baseExtension = 2,
21 | frontFaceLength = 0.5, // elephant foot compensation
22 | frontFaceScale = 1.05,
23 | backFaceLength = 5,
24 | backFaceScale = 1.2
25 | );
26 |
27 | // TODO clean this up
28 | translate(v = [-xBarSideThickness, y, z])
29 | rotate(a = [0, -90, 0])
30 | counterSunkHead_N(rackFrameScrewType, screwExtension=inf10, headExtension=inf10);
31 |
32 | // lugs for snap fit and hold in place
33 | translate(v=[-0.1,26,13.5])
34 | lug();
35 | }
36 |
37 | module onXBarToYBarPositive() {
38 | // lugs for snap fit and hold in place
39 | translate(v=[-0.1,26,2])
40 | lug();
41 | }
42 |
43 |
44 | // On yBar
45 | module onYBarToXBarNegative() {
46 | y = 27;
47 | z = 8;
48 | translate(v = [-5, y, z])
49 | rotate(a = [180, 0, 0])
50 | rotate(a = [0, 90, 0])
51 | hexNutPocket_N("m3", openSide=false, backSpace=5);
52 |
53 | // lugs for snap fit and hold in place
54 | translate(v=[-0.1,26,2])
55 | lug();
56 | }
57 |
58 | module onYBarToXBarPositive() {
59 |
60 | translate(v=[1, 14,0]) // TODO: variable for the 14
61 | rotate(a=[0,0,-90])
62 | dovetail(
63 | topWidth = 15-xySlack, // figure out why we need this
64 | bottomWidth = 12,
65 | height = 2,
66 | length = yBarHeight,
67 | headExtension = 1,
68 | baseExtension = 2,
69 | frontFaceLength = 2,
70 | frontFaceScale = 0.95, // elephant foot compensation
71 | backFaceLength = 5,
72 | backFaceScale = 1.2
73 | );
74 |
75 | // lugs for snap fit and hold in place
76 | translate(v=[-0.1,26,13.5])
77 | lug();
78 | }
79 |
80 |
81 | xBarConnectorToYBarConnectorTrans = mirror(v=[1,0,0]);
82 | yBarConnectorToXBarConnectorTrans = mirror(v=[-1,0,0]);
83 |
84 |
85 | module lug() {
86 | hull() {
87 | sphere(r=0.5);
88 |
89 | translate(v=[0,2,0])
90 | sphere(r=0.5);
91 | }
92 | }
--------------------------------------------------------------------------------
/rack/mainRail.scad:
--------------------------------------------------------------------------------
1 | include <../helper/common.scad>
2 | include <../config/common.scad>
3 | include <./sharedVariables.scad>
4 | include <./connector/connectors.scad>
5 |
6 | mainRail();
7 |
8 | module mainRail() {
9 |
10 | applyBevels()
11 | applyConnector(on="mainRail", to="yBar", trans=yBarConnectorTrans)
12 | applyConnector(on="mainRail", to="yBar", trans=mirrorMainRailOtherSideTrans * yBarConnectorTrans)
13 | mainRailBase();
14 |
15 | module mainRailBase() {
16 |
17 | difference() {
18 | union() {
19 | frontRailSegment();
20 |
21 | translate(v = [railSideMountThickness, railFrontThickness, 0])
22 | rotate(a = [0, 0, 90])
23 | sideSupportSegment();
24 | }
25 | }
26 |
27 | module frontRailSegment() {
28 | difference() {
29 | cube(size = [frontFaceWidth, railFrontThickness, railTotalHeight]);
30 |
31 | for (i = [1:numRailScrews]) {
32 | translate(v = [railScrewHoleToOuterEdge, railFrontThickness/2, i*screwDiff+railFootThickness])
33 | rotate(a = [90, 0, 0])
34 | hexNutPocket_N(mainRailScrewType);
35 | }
36 | }
37 | }
38 |
39 | module sideSupportSegment() {
40 | difference() {
41 | cube(size = [sideSupportDepth, railSideMountThickness, railTotalHeight]);
42 |
43 | for (i = [1:numRailScrews]) {
44 | translate(v = [frontScrewSpacing, railFrontThickness/2, i*screwDiff+railFootThickness])
45 | rotate(a = [90, 0, 0])
46 | cylinder(r = screwRadiusSlacked(mainRailSideMountScrewType), h = inf10, $fn = 32);
47 | }
48 | }
49 | }
50 |
51 | }
52 |
53 | yBarConnectorTrans = identity;
54 |
55 | module applyBevels() {
56 | b = 0.5; // bevel value
57 | apply_n() {
58 | union() {
59 | halfspace(vpos = [-1, -1, 0], p = [b, b, 0]);
60 | halfspace(vpos = [-1, 0, -1], p = [b, 0, b]);
61 | halfspace(vpos = [-1, 0, 1], p = [b, 0, railTotalHeight-b]);
62 |
63 | cylindricalFiletNegative(p0=[frontFaceWidth, 0, 0], p1=[frontFaceWidth, 0, railTotalHeight], n=[1,-1,0], r=1);
64 | cylindricalFiletNegative(p0=[frontFaceWidth, railFrontThickness, railFootThickness+4], p1=[frontFaceWidth, railFrontThickness, railTotalHeight-(railFootThickness+4)], n=[1,1,0], r=1);
65 | }
66 |
67 | children(0);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/rack/print/eval_P.scad:
--------------------------------------------------------------------------------
1 | include <../sharedVariables.scad>
2 | use <../xBar.scad>
3 | use <../yBar.scad>
4 | use <../mainRail.scad>
5 |
6 | // Evaluation print for slack config, please see rackstack/config/print.scad to configure tolerances
7 | // Too tight -> increase slacks values. Too loose -> decrease values
8 |
9 | intersection() {
10 | yBar();
11 | halfspace(vpos=[0,-1,0], p=[0,joinCornerDepth,0]);
12 | }
13 |
14 | translate(v=[35,0,0])
15 | intersection() {
16 | translate(v=[0,-xBarX + xBarSideThickness + 5,0])
17 | xBar();
18 | halfspace(vpos=[0,1,0], p=[0,0,0]);
19 | }
20 |
21 | translate(v=[35,18,0])
22 | rotate(a=[0,0,90])
23 | intersection() {
24 | mirror(v=[0,1,0])
25 | multmatrix(mainRailPrintOrientation)
26 | mainRail();
27 | halfspace(vpos=[-1,0,0], p=[19,0,0]);
28 |
29 | mainRailPrintOrientation = [
30 | [cos(-90), 0, sin(-90), railTotalHeight],
31 | [0, 1, 0, 0],
32 | [-sin(-90), 0, cos(-90), 0],
33 | [0, 0, 0, 1]
34 | ];
35 | }
--------------------------------------------------------------------------------
/rack/print/hingeModule.scad:
--------------------------------------------------------------------------------
1 | use <../side/hingeModule.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports generally not required (? need to print to test)
5 | hingeModule();
--------------------------------------------------------------------------------
/rack/print/magnetModuleLeft_P.scad:
--------------------------------------------------------------------------------
1 | use <../side/magnetModule.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports generally not required (? need to print to test)
5 | mirror(v=[1,0,0])
6 | magnetModule();
--------------------------------------------------------------------------------
/rack/print/magnetModuleRight_P.scad:
--------------------------------------------------------------------------------
1 | use <../side/magnetModule.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports generally not required (? need to print to test)
5 | magnetModule();
--------------------------------------------------------------------------------
/rack/print/mainRail_P.scad:
--------------------------------------------------------------------------------
1 | include <../sharedVariables.scad>
2 |
3 | use <../mainRail.scad>
4 |
5 | // Oriented for 3d printing.
6 | // Supports not required.
7 | multmatrix(mainRailPrintOrientation)
8 | mainRail();
9 |
10 | mainRailPrintOrientation = [
11 | [cos(-90), 0, sin(-90), railTotalHeight],
12 | [0, 1, 0, 0 ],
13 | [-sin(-90), 0, cos(-90), 0 ],
14 | [0, 0, 0, 1 ]
15 | ];
--------------------------------------------------------------------------------
/rack/print/rackFeet_P.scad:
--------------------------------------------------------------------------------
1 | include <../sharedVariables.scad>
2 | use <../stackEnds.scad>
3 |
4 |
5 | // Oriented for 3d printing. No supports required.
6 | rotate(a=[90-feetProtrusionAngle,0,0])
7 | rackFeet();
--------------------------------------------------------------------------------
/rack/print/rackJoiner_P.scad:
--------------------------------------------------------------------------------
1 | use <../stackEnds.scad>
2 |
3 | // Oriented for 3d printing. No supports required, but it's recommended to print this with a brim.
4 | rackJoiner();
--------------------------------------------------------------------------------
/rack/print/sideWallLeft_P.scad:
--------------------------------------------------------------------------------
1 | use <../side/sideWallLeft.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports generally not required (? need to print to test), but a brim is recommended
5 | // Depending on the type of filament you use, you could also print this with the outer wall side facing down.
6 | sideWallLeft();
--------------------------------------------------------------------------------
/rack/print/sideWallRight_P.scad:
--------------------------------------------------------------------------------
1 | use <../side/sideWallRight.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports generally not required (? need to print to test), but a brim is recommended
5 | // Depending on the type of filament you use, you could also print this with the outer wall side facing down.
6 | sideWallRight();
--------------------------------------------------------------------------------
/rack/print/stackConnectorBottom_P.scad:
--------------------------------------------------------------------------------
1 | use <../stackEnds.scad>
2 |
3 | // Oriented for 3d printing. No supports required.
4 | stackConnectorBottom();
--------------------------------------------------------------------------------
/rack/print/xBar_P.scad:
--------------------------------------------------------------------------------
1 | use <../xBar.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports generally not required: depending on roundness.
5 | xBar();
--------------------------------------------------------------------------------
/rack/print/xyPlate_P.scad:
--------------------------------------------------------------------------------
1 | use <../xyPlate.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports generally not required.
5 | xyPlate();
--------------------------------------------------------------------------------
/rack/print/yBarLeft_P.scad:
--------------------------------------------------------------------------------
1 | use <../yBar.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports required at XY wall connections, and depending on roundness
5 | yBar();
6 |
--------------------------------------------------------------------------------
/rack/print/yBarRight_P.scad:
--------------------------------------------------------------------------------
1 | use <../yBar.scad>
2 |
3 | // Oriented for 3d printing.
4 | // Supports required at XY wall connections, and depending on roundness
5 |
6 | mirror(v=[1,0,0])
7 | yBar();
8 |
--------------------------------------------------------------------------------
/rack/sharedVariables.scad:
--------------------------------------------------------------------------------
1 | include <../config/common.scad>
2 |
3 | // TODO: This rather unweildy config file is the result of multiple lazy and forgetful refactors. Clean it up.
4 |
5 | // Main rail variables:
6 |
7 | /* Small horizontal planes at the top and bottom of the main rails. Used so we can fasten the rail to the frame
8 | Note that this value is also used for a depression at the bottom/top of the frame for aligning the rail */
9 | railFootThickness = 3;
10 |
11 | railTotalHeight = screwDiff * (numRailScrews + 1) + 2 * railFootThickness;
12 |
13 | railFrontThickness = 8; // Make sure that the nuts for the chosen screw type can slot within the front face
14 | railSideMountThickness = 2.5;
15 |
16 | // Distance between the middle of a screw mount and the rail's vertical edges
17 | railScrewHoleToInnerEdge = 5;
18 | railScrewHoleToOuterEdge = 7;
19 |
20 | // Distance between the midpoint of the rail screw holes.
21 | rackMountScrewWidth = maxUnitWidth + 2 * railScrewHoleToInnerEdge;
22 |
23 | // Extra spacing for screws.
24 | frontScrewSpacing = 15;
25 |
26 | sideSupportScrewHoleToBackEdge = 4;
27 | sideSupportDepth = sideSupportScrewHoleToBackEdge + frontScrewSpacing;
28 |
29 | frontFaceWidth = railScrewHoleToInnerEdge + railScrewHoleToOuterEdge;
30 |
31 | railTotalWidth = frontFaceWidth;
32 | railTotalDepth = railFrontThickness+sideSupportDepth;
33 |
34 | // Side Wall variables, cannot put in sideWallVariables due to dependency by ybar
35 | sideWallThickness = 2.5;
36 |
37 | sideWallSlotToOuterYEdge = 3;
38 | sideWallSlotToOuterXEdge = 3; // TODO rename to variables found in ybar
39 | sideWallConnectorSlotWidth = 7;
40 |
41 | // Y Bar variables:
42 | railSlotToXZ = 3;
43 | sideWallSlotToXZ = 3;
44 |
45 | railSlotToInnerYEdge = 2;
46 | railSlotToSideWallSlot = 2;
47 |
48 | yBarWidth = railSlotToInnerYEdge + railTotalWidth+ railSlotToSideWallSlot
49 | + sideWallSlotToOuterYEdge + sideWallConnectorSlotWidth;
50 | yBarDepth = maxUnitDepth + 2*railSlotToInnerYEdge;
51 | yBarHeight = 15;
52 | yBarWallThickness = 3;
53 | yBarRoundness = baseRoundness;
54 |
55 | joinCornerDepth = 32;
56 |
57 | // It's actually the railSlotToInnerYEdge of the yBar, it'll be nice to be able to refer to it like yBar.railSlotToInnerYEdge
58 | xBarX = maxUnitWidth - 2*railSlotToInnerYEdge;
59 | xBarY = 32;
60 | xBarHeight = 15;
61 |
62 | xBarWallThickness = 3;
63 | xBarSideThickness = 8;
64 | xBarRoundness = baseRoundness;
65 |
66 | rackTotalWidth = 2*yBarWidth + xBarX;
67 | rackTotalDepth = yBarDepth;
68 |
69 |
70 | // Dimensions for the connector block, applied to y-bar
71 | yBarXYPlateBlockX = 12;
72 | yBarXYPlateBlockY = 14;
73 | yBarXYPlateBlockZ = 10;
74 |
75 | // Needed for y bar to align this connector to its inner Y edge
76 | yBarBasePlateConnectorWidth = yBarXYPlateBlockX;
77 |
78 | // x and y faces of the yBarBasePlateMount_P block
79 | plateBlockInnerXFaceToScrew = 6;
80 | plateBlockInnerYFaceToScrew = 8;
81 | plateBlockBaseConnRecession = 3;
82 | plateBlockBaseConnY = 8;
83 |
84 | basePlateYBarSlideNutDx = yBarXYPlateBlockX - plateBlockInnerXFaceToScrew;
85 | basePlateYBarSlideNutDy = yBarXYPlateBlockY - plateBlockInnerYFaceToScrew;
86 |
87 | basePlateScrewMountToYBarXZFace = basePlateYBarSlideNutDy + joinCornerDepth; // Distance to the nearest YBar XZ face
88 | basePlateScrewMountToYBarYZFace = (yBarWidth+basePlateYBarSlideNutDx) - yBarBasePlateConnectorWidth;
89 |
90 | basePlateConnYBarCornerDx = yBarWidth; // distance from a plate body corner and the nearest yBar corner
91 | basePlateConnYBarCornerDy = xBarY; // distance from a plate body corner and the nearest yBar corner
92 |
93 | basePlateConnPosX = basePlateScrewMountToYBarYZFace - basePlateConnYBarCornerDx; // distance between plateBody corner at (0,0,0) and the related corner
94 | basePlateConnPosY = basePlateScrewMountToYBarXZFace - basePlateConnYBarCornerDy;
95 |
96 | xyPlateConnDx = xBarX + 2*basePlateYBarSlideNutDx; // X distance between connectors
97 | xyPlateConnDy = yBarDepth - 2*basePlateScrewMountToYBarXZFace; // Y distance between connectors
98 | plateGap = 1; // distance between edge of xy plate and other parts
99 | assert(plateGap >= xySlack);
100 |
101 |
102 | connectorYEdgeToYBarYEdge = 5;
103 | connectorXEdgeToYBarXEdge = 5;
104 |
105 | connectorRectWidth = 10;
106 | connectorRectDepth = 10;
107 | connectorTotalHeight = 10;
108 |
109 | connectorSocketMagnetExtrudeHeight = 1;
110 | connectorTaperStartHeight = 3;
111 | connectorTopR = 3;
112 | connectorRectPlugSlack = -0.2;
113 | connectorRectSocketSlack = 0.2;
114 | connectorBottomToScrew = 6;
115 | // Distance from midpoint of stack connectors to each other
116 | stackConnectorDx = rackTotalWidth - 2*(connectorXEdgeToYBarXEdge + connectorRectWidth/2);
117 | stackConnectorDy = rackTotalDepth - 2*(connectorYEdgeToYBarYEdge + connectorRectDepth/2);
118 | stackConnectorDualSpacing = 0.5;
119 |
120 | feetProtrusionAngle = 40;
--------------------------------------------------------------------------------
/rack/side/hingeModule.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 | include <./sideWallVariables.scad>
5 |
6 |
7 | module hingeModule(fixed=false) {
8 |
9 | applyHingePole()
10 | applyYBarScrewMount(fixed)
11 | base();
12 |
13 | module base() {
14 |
15 | connW = sideWallConnW;
16 | connD = sideWallConnD;
17 |
18 | intersection() {
19 |
20 | union() {
21 | cube(size = [connW, connD, sideWallConnLugDepression]);
22 |
23 | // Riser to enforce side wall hinge clearance
24 | translate(v = [0, 0, sideWallConnLugDepression])
25 | cube(size = [connW, connD - 12, sideWallZGapClearance]);
26 | }
27 |
28 | union() {
29 | // don't bevel the part around the dowel pin hole
30 | *cube(size = [connW, 2*(hingePoleR+radiusXYSlack) , sideWallConnLugDepression + sideWallZGapClearance]);
31 |
32 | // TODO: pattern for this? beef up mirror4XY?
33 | intersection() {
34 | cVal = 0.25;
35 | halfspace(p = [0, cVal, 0], vpos = [0, 1, 1]);
36 | halfspace(p = [cVal, 0, 0], vpos = [1, 0, 1]);
37 | halfspace(p = [connW-cVal, 0, 0], vpos = [-1, 0, 1]);
38 | halfspace(p = [0, connD-cVal, 0], vpos = [0, -1, 1]);
39 | }
40 | }
41 | }
42 | }
43 |
44 | module applyHingePole() {
45 | apply_n() {
46 |
47 | union() {
48 | translate(v = [sideWallConnW/2.0, hingePoleR + radiusXYSlack, 0])
49 | cylinder(r = hingePoleR + radiusXYSlack, h = inf50, $fn=64);
50 |
51 | translate(v = [sideWallConnW/2.0, 0 , 0])
52 | cube(size=[2, 5, inf50], center=true);
53 | }
54 |
55 | children(0);
56 | }
57 | }
58 |
59 |
60 | module applyYBarScrewMount(fixed=false) {
61 | apply_n() {
62 |
63 | if (!fixed) {
64 | translate(v = [yBarScrewHoleToOuterYEdge, yBarScrewHoleToFrontXEdge, sideWallConnLugDepression])
65 | counterSunkHead_N(rackFrameScrewType, headExtension = eps, screwExtension = inf10);
66 | }
67 |
68 | children(0);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/rack/side/magnetModule.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 | include <./sideWallVariables.scad>
5 |
6 |
7 | module magnetModule(fixed=false) {
8 |
9 | applyYBarScrewMount(fixed)
10 | applyMagnetMount()
11 | base();
12 |
13 | module base() {
14 |
15 | connW = sideWallConnW;
16 | connD = sideWallConnD;
17 |
18 | intersection() {
19 |
20 | cube(size = [connW, connD, sideWallConnLugDepression]);
21 |
22 | // TODO: pattern for this? beef up mirror4XY?
23 | cVal = 0.25;
24 | halfspace(p=[0,cVal,0], vpos=[0,1,1]);
25 | halfspace(p=[cVal,0,0], vpos=[1,0,1]);
26 | halfspace(p=[connW-cVal,0,0], vpos=[-1,0,1]);
27 | halfspace(p=[0,connD-cVal,0], vpos=[0,-1,1]);
28 | }
29 | }
30 |
31 | module applyYBarScrewMount(fixed=false) {
32 |
33 | apply_n() {
34 |
35 | if (!fixed) {
36 | translate(v = [yBarScrewHoleToOuterYEdge, yBarScrewHoleToFrontXEdge, sideWallConnLugDepression])
37 | counterSunkHead_N(rackFrameScrewType, headExtension = eps, screwExtension = inf10);
38 | }
39 |
40 | children(0);
41 | }
42 | }
43 |
44 | module applyMagnetMount() {
45 | apply_pn() {
46 | magnetMountShell();
47 | magnetMountHole();
48 | children(0);
49 | }
50 |
51 | module magnetMountShell() {
52 | hull() {
53 | translate(v = [0, magnetModuleMagnetMountDy, magnetModuleMagnetMountDz])
54 | rotate(a = [0, 90, 0])
55 | cylinder(r = magnetMountShellRadius, h = sideWallConnW-magnetFaceToSideWallConnOuterYEdge);
56 |
57 | translate(v = [0, 2, sideWallConnH])
58 | cube(size = [sideWallConnW-magnetFaceToSideWallConnOuterYEdge, 2*magnetMountShellRadius, eps]);
59 | }
60 | }
61 |
62 | module magnetMountHole() {
63 | translate(v = [sideWallConnW-(magnetFaceToSideWallConnOuterYEdge+magnetHSlacked),
64 | magnetModuleMagnetMountDy,
65 | magnetModuleMagnetMountDz])
66 | rotate(a = [0, 90, 0])
67 | cylinder(r = magnetRSlacked, h = magnetHSlacked);
68 | }
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/rack/side/sideWallBase.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 | include <./sideWallMagnetMount.scad>
5 | include <./sideWallVariables.scad>
6 | use <./magnetModule.scad>
7 | use <./hingeModule.scad>
8 |
9 | //translate(v = [hingePoleDx ,hingePoleDy, 10])
10 | //rotate(a=[0,0,-120])
11 | //translate(v = [-hingePoleDx ,-hingePoleDy, 0])
12 | *sideWallBase();
13 |
14 | module sideWallBase() {
15 |
16 | applyHingeConnector()
17 | applySideWallBracing(numVerticalRibs=2)
18 | applyMagnetConnector()
19 | applyHandle()
20 | sideWallBase();
21 |
22 | module sideWallBase() {
23 |
24 | module sideWallShellHelper(x, y, z, r) {
25 | translate(v = [r, r, 0])
26 | minkowski() {
27 | cube(size = [x-r, y-2*r, z]);
28 |
29 | if (r > 0) {
30 | sphere(r = r);
31 | }
32 | }
33 | }
34 |
35 | intersection() {
36 | difference() {
37 | sideWallShellHelper(sideWallX, sideWallY, sideWallZ, baseRoundness);
38 | translate(v = [sideWallThickness, sideWallThickness, 0])
39 | sideWallShellHelper(sideWallX, sideWallY-2*sideWallThickness, sideWallZ, max(0,baseRoundness-sideWallThickness));
40 | }
41 | halfspace(vpos = [-1, 0, 0], p = [sideWallX, 0, 0]);
42 | halfspace(vpos = [0, 0, -1], p = [0, 0, sideWallZ]);
43 | halfspace(vpos = [0, 0, 1], p = [0, 0, 0]);
44 | halfspace(vpos = [1, 0, 0], p = [0, 0, 0]);
45 | }
46 | }
47 |
48 | module applyHingeConnector() {
49 |
50 | hingeHoleShellR = hingePoleR+1;
51 |
52 | hingeHoleH = hingePoleH-sideWallConnLugDepression;
53 | assert(hingeHoleH > 1);
54 |
55 | apply_pn() {
56 | hull() {
57 | hingeShell();
58 | hingeSideProjectionPlane();
59 | }
60 |
61 | union() {
62 | hingeHole(extraZ=1);
63 |
64 | translate(v=[0,0,sideWallZ])
65 | mirror(v=[0,0,1])
66 | hingeHole(extraZ=1);
67 |
68 | // Trim parts of the wall for rotational clearance
69 | halfspace(p=[0, sideWallY-2.5, 0], vpos=[-0.5,1,0]); // flat area to limit rotation against the main rail
70 | halfspace(p=[sideWallX-10, sideWallY, 0], vpos=[1,2.5,0]);
71 | }
72 |
73 | children(0);
74 | }
75 |
76 | module hingeShell() {
77 | translate(v = [hingePoleDx, hingePoleDy, 0])
78 | cylinder(r = hingeHoleShellR, h = sideWallZ);
79 | }
80 |
81 | // XZ plane in line with the back of the case. Project the hinge pole shell onto this to fill any weird
82 | // geometries from the curves of the side wall
83 | module hingeSideProjectionPlane() {
84 | translate(v=[sideWallThickness, hingePoleDy - hingeHoleShellR, 0])
85 | cube(size=[eps, 2*hingeHoleShellR, sideWallZ]);
86 | }
87 |
88 | module hingeHole(extraZ) {
89 | translate(v = [hingePoleDx, hingePoleDy, 0])
90 | cylinder(r = hingePoleR+radiusXYSlack, h = hingeHoleH+extraZ);
91 | }
92 | }
93 |
94 | // TODO: add correct magnet translations, also remove random variables
95 | module applyMagnetConnector() {
96 | apply_p() {
97 | union() {
98 | translate(v = [sideWallThickness, magnetMountToYBarFront, magnetMountToYBarTop - sideWallZHingeTotalClearance])
99 | sideWallMagnetMountRotated();
100 |
101 | translate(v = [sideWallThickness, magnetMountToYBarFront, sideWallZ - (magnetMountToYBarTop- sideWallZHingeTotalClearance)])
102 | sideWallMagnetMountRotated();
103 | }
104 |
105 | children(0);
106 | }
107 |
108 | module sideWallMagnetMountRotated() {
109 | rotate(a=[0,90,0])
110 | sideWallMagnetMount();
111 | }
112 | }
113 |
114 | module applyHandle() {
115 |
116 | handleWidth = 8;
117 | handleLength = 60;
118 | handleRoundness = 7;
119 | widthOffset = 3;
120 |
121 | apply_n() {
122 |
123 | minkowski() {
124 | sphere(r=handleRoundness);
125 |
126 | translate(v = [sideWallX -(handleWidth-handleRoundness) + widthOffset, 0, (sideWallZ-handleLength)/2])
127 | cube(size = [handleWidth-handleRoundness, sideWallThickness, handleLength-handleRoundness]);
128 | }
129 |
130 | children(0);
131 | }
132 | }
133 | }
134 |
135 | module applySideWallDefaultVentilation(numVents) {
136 |
137 | r = 2; // vent roundness
138 | ventLength = sideWallY - 2*sideWallDefaultVentilationToZEdge;
139 | ventZDiff = numVents == 1
140 | ? 0 // TODO kinda ugly
141 | : (sideWallZ - 2*sideWallDefaultVentilationToYEdge)/(numVents-1);
142 |
143 | apply_n() {
144 | if (numVents > 0) {
145 | for (i = [0:numVents-1]) {
146 | translate(v = [0, sideWallDefaultVentilationToZEdge, i*ventZDiff+sideWallDefaultVentilationToYEdge])
147 | vent();
148 | }
149 | }
150 |
151 | children(0);
152 | }
153 |
154 | module vent() {
155 | translate(v=[-inf/2,r,-sideWallDefaultVentilationWidth/2])
156 | minkowski() {
157 | rotate(a=[0,90,0])
158 | cylinder(r=r,h=inf);
159 | cube(size = [inf, max(eps, ventLength-2*r), max(eps,sideWallDefaultVentilationWidth-2*r)]);
160 | }
161 | }
162 | }
163 |
164 | module applySideWallBracing(numVerticalRibs) {
165 |
166 | apply_p() {
167 | // TODO add horizontal bracing
168 | union() {
169 | sideWallVerticalBracing(numRibs = numVerticalRibs);
170 | sideWallHorizontalBracing();
171 | }
172 | children(0);
173 | }
174 |
175 | module sideWallVerticalBracing(numRibs) {
176 |
177 | ribYDiff = sideWallY - 2*sideWallDefaultVerticalBracingToZEdge;
178 |
179 | translate(v=[0,sideWallDefaultVerticalBracingToZEdge,0])
180 | intersection() {
181 | for (i = [0:numRibs-1]) {
182 | translate(v = [0, i*ribYDiff, 0])
183 | verticalRib();
184 | }
185 |
186 | halfspace(vpos=[1,0,0], p=[0,0,0]);
187 | }
188 |
189 | module verticalRib(height=4, thickness=3, rampLength=0) {
190 |
191 | translate(v=[sideWallThickness-eps,-thickness/2,0])
192 | hull() {
193 | cube(size = [eps, thickness, eps]);
194 |
195 | translate(v = [0, 0, rampLength])
196 | cube(size = [height, thickness, sideWallZ-2*rampLength]);
197 |
198 | translate(v = [0, 0, sideWallZ])
199 | cube(size = [eps, thickness, eps]);
200 | }
201 | }
202 | }
203 |
204 | module sideWallHorizontalBracing() {
205 |
206 | ribThickness = 2.5;
207 |
208 | horizontalRib(thickness=ribThickness);
209 |
210 | translate(v=[0,0,sideWallZ-ribThickness])
211 | horizontalRib(thickness=ribThickness);
212 |
213 | module horizontalRib(height=4, thickness=3, rampLength=5) {
214 |
215 | ribLength = sideWallY + rampLength - sideWallDefaultHorizontalBracingToZEdge;
216 |
217 | translate(v = [sideWallThickness-eps, sideWallY-ribLength, 0])
218 | hull() {
219 | cube(size = [height, ribLength, thickness]);
220 |
221 | translate(v=[0,-rampLength,0])
222 | cube(size=[eps, eps, thickness]);
223 | }
224 | }
225 | }
226 | }
227 |
228 |
--------------------------------------------------------------------------------
/rack/side/sideWallLeft.scad:
--------------------------------------------------------------------------------
1 | include <./sideWallBase.scad>
2 |
3 | sideWallLeft();
4 |
5 | module sideWallLeft() {
6 |
7 | numVentsCustom = sideWallVentilation? ceil((sideWallZ - 2*sideWallDefaultVentilationToYEdge)/10): 0;
8 |
9 | applySideWallDefaultVentilation(numVents=numVentsCustom)
10 | sideWallBase();
11 | }
12 |
--------------------------------------------------------------------------------
/rack/side/sideWallMagnetMount.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 | include <../sharedVariables.scad>
4 | include <./sideWallVariables.scad>
5 |
6 | module sideWallMagnetMount() {
7 | // oriented so that the xy face is the side wall's inner face
8 | difference() {
9 | cylinder(r1 = magnetMountShellRadius+1, r2 = magnetMountShellRadius, h = innerSideWallToYBarMagnetConn);
10 |
11 | translate(v=[0, 0, innerSideWallToYBarMagnetConn-magnetHSlacked])
12 | cylinder(r = magnetRSlacked, h = magnetHSlacked);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/rack/side/sideWallRight.scad:
--------------------------------------------------------------------------------
1 | include <./sideWallBase.scad>
2 |
3 | sideWallRight();
4 |
5 | module sideWallRight() {
6 |
7 | numVentsCustom = sideWallVentilation? ceil((sideWallZ - 2*sideWallDefaultVentilationToYEdge)/10): 0;
8 |
9 | mirror(v=[1,0,0])
10 | applySideWallDefaultVentilation(numVents=numVentsCustom)
11 | sideWallBase();
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/rack/side/sideWallVariables.scad:
--------------------------------------------------------------------------------
1 | include <../../helper/common.scad>
2 | include <../../config/common.scad>
3 |
4 |
5 | sideWallConnW = 7;
6 | sideWallConnD = 20;
7 | sideWallConnH = 3;
8 | sideWallConnLugDepression = sideWallConnH;
9 |
10 | yBarScrewHoleToOuterYEdge = 3.5;
11 | yBarScrewHoleToFrontXEdge = 16;
12 |
13 | magnetFaceToSideWallConnOuterYEdge = 2;
14 | magnetMountShellRadius = magnetRSlacked + 1;
15 |
16 | innerSideWallToYBarMagnetConn = magnetFaceToSideWallConnOuterYEdge + sideWallSlotToOuterYEdge - sideWallThickness;
17 |
18 | hingePoleR = dowelPinR;
19 | hingePoleH = dowelPinH;
20 |
21 | sideWallZHingeSlack = 0.3;
22 | sideWallZGapClearance = 0.5;
23 | sideWallZHingeTotalClearance = sideWallZHingeSlack + sideWallZGapClearance; // only for one edge
24 | sideWallZ = (railTotalHeight - 2*railFootThickness) - 2*sideWallZHingeTotalClearance;
25 | sideWallY = yBarDepth;
26 |
27 | magnetMountToYBarTop = magnetMountShellRadius + sideWallZHingeTotalClearance + 1;
28 | magnetMountToYBarFront = magnetMountShellRadius + sideWallSlotToXZ + 2;
29 |
30 | sideWallXGapClearance = 0.2;
31 | sideWallX = (yBarWidth-(railTotalWidth+railSlotToInnerYEdge)) - sideWallXGapClearance;
32 |
33 | hingePoleDx = sideWallSlotToOuterYEdge + sideWallConnW/2.0;
34 | hingePoleDy = sideWallY - (sideWallSlotToOuterXEdge + (hingePoleR+radiusXYSlack));
35 |
36 | sideWallDefaultVerticalBracingToZEdge = 30;
37 | sideWallDefaultHorizontalBracingToZEdge = sideWallDefaultVerticalBracingToZEdge;
38 | sideWallDefaultVentilationToZEdge = 40;
39 | sideWallDefaultVentilationToYEdge = 25;
40 | sideWallDefaultVentilationWidth = 6;
41 |
42 | magnetModuleMagnetMountDy = magnetMountToYBarFront - sideWallSlotToXZ;
43 | magnetModuleMagnetMountDz = magnetMountToYBarTop + sideWallConnLugDepression;
44 |
--------------------------------------------------------------------------------
/rack/stackEnds.scad:
--------------------------------------------------------------------------------
1 | include <../helper/common.scad>
2 | include <./sharedVariables.scad>
3 | include <./connector/connectors.scad>
4 |
5 | module rackJoiner() {
6 | translate(v=[0,0,stackConnectorDualSpacing/2])
7 | stackConnectorPlug();
8 |
9 | mirror(v=[0,0,1])
10 | translate(v=[0,0,stackConnectorDualSpacing/2])
11 | stackConnectorPlug();
12 |
13 | translate(v=[0,0,-stackConnectorDualSpacing/2])
14 | cube(size=[connectorRectWidth+connectorRectPlugSlack, connectorRectDepth+connectorRectPlugSlack, stackConnectorDualSpacing]);
15 | }
16 |
17 | module rackFeet() {
18 |
19 | bandThickness = 2;
20 | height = 18;
21 |
22 | translate(v = [stackConnectorDx/2, 0, 2])
23 | mirror(v=[0,0,1]) {
24 | // stack connectors along rack x axis
25 | translate(v = [-(stackConnectorDx+connectorRectWidth)/2, -connectorRectDepth/2, 2-overhangSlack])
26 | mirror(v = [0, 0, 1]) {
27 | translate(v = [stackConnectorDx, 0, 0])
28 | stackConnectorBottom();
29 |
30 | stackConnectorBottom();
31 | }
32 | band();
33 | }
34 |
35 | module band() {
36 | intersection() {
37 | translate(v=[0,0,2])
38 | difference() {
39 | roundedCube(rackTotalWidth, inf50, height, 5, center = true);
40 |
41 | translate(v=[0,0,3])
42 | roundedCube(rackTotalWidth-6, inf50, height-6, 3, center = true);
43 | }
44 |
45 | halfspace(vpos=[0,1,-tan(feetProtrusionAngle)],p=[0,-8,2]);
46 | halfspace(vpos=[0,-1, tan(feetProtrusionAngle)],p=[0,6,2]);
47 |
48 | // TODO make these edge deburrings more parametric
49 | halfspace(vpos=[0,-1,0],p=[0,16,2]);
50 | halfspace(vpos=[0,1,0],p=[0,-5,2]);
51 | }
52 |
53 | }
54 |
55 | module roundedCube(x,y,z,r, center=false) {
56 | translate(v=[0,0,z/2])
57 | minkowski() {
58 | cube(size=[x-2*r,y,z-2*r], center=center);
59 |
60 | rotate(a=[90,0,0])
61 | cylinder(r=r, h=eps);
62 | }
63 | }
64 | }
65 |
66 | rackTopHandle();
67 |
68 | module rackTopHandle() {
69 |
70 |
71 | handleWidth = 20;
72 | handleHeight = 50;
73 |
74 | handleTopThickness = 10;
75 | handleBottomThickness = 10;
76 | handleSideThickness = 10;
77 |
78 | handleR = baseRoundness;
79 |
80 | handleRing();
81 |
82 | module handleRing() {
83 |
84 | w = handleWidth - 2*handleR;
85 | st = max(eps,handleSideThickness - 2*handleR);
86 | bt = max(eps,handleBottomThickness - 2*handleR);
87 | tt = max(eps,handleTopThickness - 2*handleR);
88 |
89 | y =100;
90 |
91 | minkowski() {
92 |
93 | sphere(r=handleR);
94 |
95 | ringFourHull() {
96 | cube(size = [w, st, bt]);
97 |
98 | translate(v = [0, y-handleSideThickness, 0])
99 | cube(size = [w, st, bt]);
100 |
101 | translate(v = [0, y-handleSideThickness, handleHeight-handleTopThickness])
102 | cube(size = [w, st, tt]);
103 |
104 | translate(v = [0, 0, handleHeight-handleTopThickness])
105 | cube(size = [w, st, tt]);
106 | }
107 | }
108 |
109 | }
110 |
111 |
112 | module ringFourHull() {
113 | union() {
114 | hull() {children(0); children(1);}
115 | hull() {children(1); children(2);}
116 | hull() {children(2); children(3);}
117 | hull() {children(3); children(0);}
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/rack/xBar.scad:
--------------------------------------------------------------------------------
1 | include <../helper/common.scad>
2 | include <../config/common.scad>
3 | include <./sharedVariables.scad>
4 | include <./connector/connectors.scad>
5 |
6 | xBar();
7 |
8 | module xBar() {
9 |
10 | applyConnector(on="xBar", to="yBar", trans=xBarMirrorOtherCornerTrans * xBarYBarConnectorTrans)
11 | applyConnector(on="xBar", to="yBar", trans=xBarYBarConnectorTrans)
12 | xBarBase();
13 |
14 | module xBarBase() {
15 | intersection() {
16 |
17 | difference() {
18 | cylindricalFiletEdge(xBarY, xBarX, xBarHeight, xBarRoundness);
19 |
20 | union() {
21 | translate(v = [xBarWallThickness, xBarSideThickness, xBarWallThickness])
22 | cylindricalFiletEdge(xBarY, xBarX-2*xBarSideThickness, xBarHeight, xBarRoundness-xBarWallThickness);
23 |
24 | connectorWallFiletNegative();
25 |
26 | multmatrix(xBarMirrorOtherCornerTrans)
27 | connectorWallFiletNegative();
28 | }
29 | }
30 |
31 | // Shave off bottom corners to reduce elephant's foot at where xBar and YBar join
32 | halfspace(vpos = [0, 1, 1], p = [0, 0.75, 0]);
33 | halfspace(vpos = [0, -1, 1], p = [0, xBarX-0.75, 0]);
34 | }
35 |
36 |
37 | module connectorWallFiletNegative() {
38 | cylindricalFiletNegative(
39 | p0=[xBarWallThickness, xBarSideThickness, xBarHeight],
40 | p1=[xBarY, xBarSideThickness, xBarHeight],
41 | n=[0, 1, 1], r=2
42 | );
43 | }
44 |
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/rack/xyPlate.scad:
--------------------------------------------------------------------------------
1 | include <../helper/common.scad>
2 | include <./connector/connectors.scad>
3 |
4 | xyPlate();
5 |
6 | module xyPlate() {
7 |
8 | translate(v=-[basePlateConnPosX,basePlateConnPosY,0]) // center around one of the YBarConnector holes
9 | applyVentilation()
10 | applyConnector(on="basePlate", to="yBar")
11 | plateBody();
12 |
13 | module plateBody() {
14 | plateBodyX = xBarX - 2*plateGap;
15 | plateBodyY = (yBarDepth - 2*xBarY) - 2*plateGap;
16 | plateBodyH = xBarWallThickness;
17 |
18 | translate(v=[plateGap, plateGap, 0]) {
19 | cube(size = [plateBodyX, plateBodyY, plateBodyH]);
20 |
21 | // bracing
22 | braceThickness = 3;
23 | braceHeight = 2;
24 | translate(v = [0, 0, plateBodyH])
25 | difference() {
26 | cube(size = [plateBodyX, plateBodyY, braceHeight]);
27 | translate(v=[braceThickness, braceThickness,0])
28 | cube(size=[plateBodyX-2*braceThickness, plateBodyY-2*braceThickness, braceHeight]);
29 | }
30 |
31 | }
32 | }
33 |
34 | module applyVentilation() {
35 |
36 | apply_n() {
37 | numSlits = 5;
38 | edgePadding = 30;
39 | diff = (xBarX-2*edgePadding)/(numSlits-1);
40 | slitWidth = 4;
41 | slitLength = (yBarDepth - 2*xBarY)-2*edgePadding;
42 |
43 | for(i=[0:numSlits-1]) {
44 | translate(v=[edgePadding+diff*i-slitWidth/2, edgePadding,0])
45 | minkowski() {
46 | cylinder(h=1,r=2);
47 | cube(size=[slitWidth,slitLength,inf]);
48 | }
49 | }
50 | children(0);
51 | }
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/rack/yBar.scad:
--------------------------------------------------------------------------------
1 | include <../helper/common.scad>
2 | include <../config/common.scad>
3 | include <./connector/connectors.scad>
4 | include <./sharedVariables.scad>
5 |
6 | yBar();
7 |
8 | module yBar() {
9 |
10 | applyOnYBarBothCorners(to="basePlate", trans=yBarBasePlateConnectorTrans)
11 | applyOnYBarBothCorners(to="stackConnector", trans=yBarStackConnectorTrans)
12 | applySideModules()
13 | applyOnYBarBothCorners(to="mainRail", trans=yBarMainRailConnectorTrans)
14 | applyOnYBarBothCorners(to="xBar", trans=yBarXBarConnectorTrans)
15 | yBarBase();
16 |
17 | module yBarBase() {
18 | intersection() {
19 | difference() {
20 | sphericalFiletEdge(yBarWidth, yBarDepth, yBarHeight, yBarRoundness);
21 |
22 | translate(v = [yBarWallThickness, joinCornerDepth, yBarWallThickness])
23 | cylindricalFiletEdge(yBarWidth, yBarDepth-2*joinCornerDepth, yBarHeight, yBarRoundness-yBarWallThickness);
24 | }
25 |
26 | halfspace(vpos=[-1, 0, 1], p=[yBarWidth-1, 0,0]);
27 | }
28 | }
29 |
30 | // Helper module to apply connectors to both corners
31 | module applyOnYBarBothCorners(to, trans) {
32 | applyConnector(on="yBar", to=to, trans=trans)
33 | applyConnector(on="yBar", to=to, trans=yBarMirrorOtherCornerTrans * trans)
34 | children(0);
35 | }
36 |
37 |
38 | module applySideModules() {
39 |
40 | if (!fixedSideModules) {
41 | applyOnYBarBothCorners(to="sideModule", trans=yBarSideModuleConnectorTrans)
42 | children(0);
43 |
44 | } else {
45 |
46 | applyConnector(on="yBar", to="magnetModule", trans=yBarSideModuleConnectorTrans)
47 | applyConnector(on="yBar", to="hingeModule", trans=yBarMirrorOtherCornerTrans * yBarSideModuleConnectorTrans)
48 | children(0);
49 | }
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/stl/micro/rack/eval_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/eval_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/hingeModule.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/hingeModule.stl
--------------------------------------------------------------------------------
/stl/micro/rack/magnetModuleLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/magnetModuleLeft_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/magnetModuleRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/magnetModuleRight_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/mainRail_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/mainRail_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/rackFeet_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/rackFeet_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/rackJoiner_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/rackJoiner_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/sideWallLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/sideWallLeft_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/sideWallRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/sideWallRight_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/stackConnectorBottom_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/stackConnectorBottom_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/xBar_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/xBar_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/xyPlate_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/xyPlate_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/yBarLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/yBarLeft_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/yBarRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/yBarRight_P.stl
--------------------------------------------------------------------------------
/stl/micro/rack/yBar_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/micro/rack/yBar_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/eval_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/eval_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/hingeModule.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/hingeModule.stl
--------------------------------------------------------------------------------
/stl/mini/rack/magnetModuleLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/magnetModuleLeft_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/magnetModuleRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/magnetModuleRight_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/mainRail_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/mainRail_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/rackFeet_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/rackFeet_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/rackJoiner_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/rackJoiner_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/sideWallLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/sideWallLeft_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/sideWallRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/sideWallRight_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/stackConnectorBottom_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/stackConnectorBottom_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/xBar_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/xBar_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/xyPlate_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/xyPlate_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/yBarLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/yBarLeft_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/yBarRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/yBarRight_P.stl
--------------------------------------------------------------------------------
/stl/mini/rack/yBar_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/mini/rack/yBar_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/eval_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/eval_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/hingeModule.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/hingeModule.stl
--------------------------------------------------------------------------------
/stl/nano/rack/magnetModuleLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/magnetModuleLeft_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/magnetModuleRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/magnetModuleRight_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/mainRail_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/mainRail_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/rackFeet_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/rackFeet_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/rackJoiner_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/rackJoiner_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/sideWallLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/sideWallLeft_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/sideWallRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/sideWallRight_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/stackConnectorBottom_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/stackConnectorBottom_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/xBar_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/xBar_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/xyPlate_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/xyPlate_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/yBarLeft_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/yBarLeft_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/yBarRight_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/yBarRight_P.stl
--------------------------------------------------------------------------------
/stl/nano/rack/yBar_P.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jazwa/rackstack/5bfb76a4ed850f7d02c33f651f40bd123d1f5208/stl/nano/rack/yBar_P.stl
--------------------------------------------------------------------------------