115 Commits
v3.0.0 ... main

Author SHA1 Message Date
1a94eabd39 delete panel_clamp 2025-07-30 12:59:27 +09:00
480afbf2db remove gap 2025-07-30 10:14:15 +09:00
Edward Kisiel
760e0e6bdd updated sbcmf with new terminal class components 2025-06-22 21:17:31 -04:00
Edward Kisiel
d7e70658f3 updated readme.md and sbcmf library 2025-06-07 14:05:57 -04:00
Edward Kisiel
4f42b9a3db added washer to accessory tool, added holes to bottom of rack case for feet, updated readme.md 2025-06-01 17:40:00 -04:00
Edward Kisiel
60ca7f47bb changed rack stand foot and arc thickness, readme.md corrections. 2025-05-30 10:04:33 -04:00
Edward Kisiel
054dbb9edc added sbccb_accessory_tool.scad for user access to the accessory library, fixed rack tab hole spacing, added library parts rack_rail and rack_stand for 1u-4u cases 2025-05-29 16:50:35 -04:00
Edward Kisiel
12c99bee77 corrected interior wall height relative to floor thickness changes. 2025-05-28 18:24:07 -04:00
Edward Kisiel
3aa7e5837a adjusted removable bay clearances, added example rack case and other cleanup 2025-05-27 21:04:24 -04:00
Edward Kisiel
9a037db8a4 grommet tolerance adjustment, fixed wrong part count and other minor changes 2025-05-26 16:06:52 -04:00
Edward Kisiel
5a15316530 rack case design branch merge and sbcmf update 2025-05-25 12:32:18 -04:00
Edward Kisiel
d5d63e54a2 adjusted n2, n2+ openings and sbc placement for rack case 2025-05-25 12:02:04 -04:00
Edward Kisiel
f5dd71ec29 repositioned top and bottom cover patterns, alignment adjustments for removable bay and other changes 2025-05-23 19:37:51 -04:00
Edward Kisiel
d502252d2e add grommet() and panel_clamp() to accessory library, readme.md updated, work on removable bay sbc positioning. 2025-05-22 22:20:27 -04:00
Edward Kisiel
13ccfc6357 fixed bottom heatsink standoff mounting for relavent sbc 2025-05-21 21:41:41 -04:00
Edward Kisiel
d254f162c1 fixed rack bay external bottom heatsink standoff mounting support, raised case wall clamps, changed rack case to initial fixed depth of 100mm 2025-05-21 18:20:49 -04:00
Edward Kisiel
ed077d5039 rearranged standoff gui tabs and created h4 bottom mount panel_nas example case 2025-05-20 13:41:21 -04:00
Edward Kisiel
71034dee85 set interior walls to fixed width of 2mm 2025-05-18 10:13:35 -04:00
Edward Kisiel
b221fabed5 fixed manifold issue with lower panel clamps and other minor changes 2025-05-16 19:48:00 -04:00
Edward Kisiel
728b8398f9 added individual standoff control for rack case, fixed, open and removable bays 2025-05-16 11:56:58 -04:00
Edward Kisiel
1c64305276 added case top for rack cases 2025-05-15 15:49:59 -04:00
Edward Kisiel
1b8a47361b expanded rear conduit-grommet selection and tweaked removal bay trays 2025-05-14 21:34:24 -04:00
Edward Kisiel
8d2ebd4f94 final plumbing for rack removable bays 2025-05-13 21:56:58 -04:00
Edward Kisiel
0d28ebbc88 more work for removable bays 2025-05-12 18:31:59 -04:00
Edward Kisiel
35825add61 removable bay tray initial work 2025-05-11 22:18:14 -04:00
Edward Kisiel
0aff56b70c individual bay open front or adjoining combinations based on disabled bay wall and empty adjoining bay 2025-05-09 21:57:13 -04:00
Edward Kisiel
c3ec2837ed setup screw mask for panel_clamp and used mask for rack case 2025-05-08 16:28:54 -04:00
Edward Kisiel
cd05ff7528 view accessory part added for rack cases 2025-05-08 15:52:28 -04:00
Edward Kisiel
93b4de0444 rack case added to individual part selection as left, bottom, right 2025-05-07 20:38:20 -04:00
Edward Kisiel
9f11e2884e support for 10 inch racks and changed rack tabs to standard width 2025-05-07 17:31:29 -04:00
Edward Kisiel
c09d444913 adjusted 2mm panel_clamps, implemented bottom cover and front vents 2025-05-07 15:36:18 -04:00
Edward Kisiel
5b03cd94fc more rack bay work, fixes and code cleanup 2025-05-06 17:11:43 -04:00
Edward Kisiel
63ea4bae0b plumbed wall, fan and conduit for 6 rack bays 2025-05-05 20:43:15 -04:00
Edward Kisiel
b6554114ec additional rack sizes 1u+, 1u++ and gui additions for wall, fan and conduit 2025-05-04 19:23:45 -04:00
Edward Kisiel
6bc4920bea added middle floor clamp, expanded support to 6 devices, initial wall dividers 2025-05-03 21:44:01 -04:00
Edward Kisiel
ca26347358 rack case piece fastening geometry, added panel_clamp to library 2025-05-03 17:44:48 -04:00
Edward Kisiel
859192bd6b multi sbc support with individual location and rotation for rack case 2025-05-01 17:43:39 -04:00
Edward Kisiel
b48bb23e53 changed height of panel_nas front and back panel. 2025-05-01 13:55:39 -04:00
Edward Kisiel
5aebb0d549 initial work for rack_1u case, rack.scad with mounting tabs 2025-04-29 14:45:29 -04:00
Edward Kisiel
415d5532a1 gui work for rack case design 2025-04-27 19:52:44 -04:00
Edward Kisiel
a9e51e25dd added tol adjustment to panel_nas panel openings for right and left side for a better fit 2025-04-26 15:34:51 -04:00
Edward Kisiel
d7f043e6ed increased side slot mask depth for panel_nas 2025-04-25 22:18:51 -04:00
Edward Kisiel
2979144e28 minor gui format change, lib/vent.scad replaced 2025-04-25 22:00:34 -04:00
Edward Kisiel
43f7e0f476 added section part under view tab for panel case part 2d sections 2025-04-24 19:59:56 -04:00
Edward Kisiel
a6dd0dcb1d panel_nas right side placement and related panel size fixed 2025-04-24 18:16:50 -04:00
Edward Kisiel
3281835ac8 panel_nas case design and SBCMF update 2025-04-23 17:50:45 -04:00
Edward Kisiel
2f318b1cce cable_holder improvement, more front, top and bottom vent cover adjustments, other code cleanup and example cases 2025-04-23 15:07:23 -04:00
Edward Kisiel
86eb912784 fixed spacer and right side placment issue, updated readme.md, code cleanup and example case accessories 2025-04-21 17:30:50 -04:00
Edward Kisiel
1c2cf8e00f platter and part view plumbed and indent adjusted 2025-04-18 21:12:11 -04:00
Edward Kisiel
b369665049 added fan models for rear panel in model view 2025-04-18 18:08:03 -04:00
Edward Kisiel
db43558f9c front, top and bottom cover vent adjustments 2025-04-18 16:29:32 -04:00
Edward Kisiel
5a56f3d4fc additional tab support for 4+ hd bays 2025-04-18 11:55:11 -04:00
Edward Kisiel
5d0242ff1c for sbc wider then 100mm, added option to center hd positions on x axis using dual spacers 2025-04-17 21:40:52 -04:00
Edward Kisiel
2eea918f4f implemented hd_holes() hole or slot openings for 2.5 and 3.5 drives 2025-04-17 17:16:48 -04:00
Edward Kisiel
f5793ea453 variable length spacer placement and hd reverse, 180 z rotation, implemented 2025-04-17 15:53:56 -04:00
Edward Kisiel
53b242440f hd cableholder_spacer work, top cover adjustments, other changes 2025-04-14 20:49:57 -04:00
Edward Kisiel
c151a9047b wide format sbc support and other changes 2025-04-12 21:56:28 -04:00
Edward Kisiel
3ce75a345b more case panel fastening work 2025-04-12 15:08:07 -04:00
Edward Kisiel
3fee9e59ce added rpi5_bottom_m2hat_shell as a saved case 2025-04-11 14:47:40 -04:00
Edward Kisiel
a999585197 added panel tabs and cutouts for case assembly 2025-04-10 21:59:03 -04:00
Edward Kisiel
2e797dd1fb added top or bottom sbc mount with indents for panel_nas, other misc additions and changes 2025-04-08 17:18:01 -04:00
Edward Kisiel
a032839b3b work on parametrics for drive(s), fan and case size, other gui and misc work 2025-04-07 17:33:32 -04:00
Edward Kisiel
6f26ab2f04 more wip for panel_nas case 2025-04-06 19:06:29 -04:00
Edward Kisiel
cd2e77acc9 new case panel_nas initial work 2025-04-06 12:40:01 -04:00
Edward Kisiel
1d97917d46 saved case m2_eyespi_eink1.54 and m2_eyespi_lcd2.8 added 2025-04-05 20:06:37 -04:00
Edward Kisiel
f393da7372 fixed top standoff opening problem due to typo 2025-04-05 15:21:45 -04:00
Edward Kisiel
d6d6fb6d41 fixed top standoff z placement and height for tray_side cases 2025-04-01 17:02:45 -04:00
Edward Kisiel
c678853a6d fixed top standoff z placement and height for fitted and snap cases 2025-04-01 16:40:53 -04:00
Edward Kisiel
bb3a1d6f80 updated SBC Model Framework and added opi5max sbc in gui 2025-03-30 18:38:24 -04:00
Edward Kisiel
5456ff54f1 added m2_eyespi_shell and adjusted button clip opening 2025-03-11 13:35:19 -04:00
Edward Kisiel
b19993d63c adjustments for rock4c+ and changed status to verified in SBC Model Framework, adjusted indent for audio jack 2025-02-04 15:12:13 -05:00
Edward Kisiel
7e809f2719 fixed standoff openings from interfering with case geometry 2025-01-30 11:20:34 -05:00
Edward Kisiel
7adbea7732 m2 shell for eyespi as wip 2025-01-30 10:10:33 -05:00
Edward Kisiel
3586afff2d lowered usbc single horizontal 180 indent. 2024-11-13 14:43:52 -05:00
Edward Kisiel
24a454a492 increased case gap by .5mm and lowered usbc mask for rock5b+. 2024-11-13 10:05:25 -05:00
Edward Kisiel
c7929e7f6b library models adafruit_2030_powerboost, adafruit_4755_solar_charger and changed the name of adafruit_lcd to adafruit_4311_lcd, updated sbcmf and documentation 2024-10-25 17:27:11 -04:00
Edward Kisiel
5bd72034e8 sbcmf update 2024-10-24 19:39:05 -04:00
Edward Kisiel
89b1bf1915 update sbc model framework that includes adafruit feather-m0_express and feather-m4_express 2024-10-24 18:00:27 -04:00
Edward Kisiel
1ef63e412d changed pillar Z location and changed rpi hat to use pillars in accessories.cfg. 2024-10-19 19:52:18 -04:00
Edward Kisiel
be91de94ff pillar model added and readme.md updated, xu4_shifter_shield case added 2024-10-19 17:08:46 -04:00
Edward Kisiel
ad087dbc77 updated sbc_model_framework for rock5b+ usbc adjustment 2024-09-05 10:31:43 -04:00
Edward Kisiel
8d7b211466 added odroid-m2 and test case m2_shell both verified green, added m2_shell_lowboy case, updated sbc_model_framework 2024-09-01 15:49:24 -04:00
Edward Kisiel
cfe140a048 adjusted rock5b+ hdmi-a input location 2024-08-24 09:19:25 -04:00
Edward Kisiel
9d1cfa396c added rock5b+ and initial test case, both currently unverified 2024-08-17 22:14:44 -04:00
Edward Kisiel
1918a7bbaa updated sbc model framework for nio12l corrections, created nio12l_shell test case to verify sbc 2024-08-17 11:10:49 -04:00
Edward Kisiel
183e3bee12 updated readme.md and added animation sbc_case_builder_gui.gif 2024-07-21 18:16:36 -04:00
Edward Kisiel
fba4fc3420 added soedge_a-baseboard and test case, updated sbc model framework and readme.md 2024-07-21 13:09:11 -04:00
Edward Kisiel
8b50011e35 added a64 and a64lts and test cases a64_shell and a64-lts_shell, initial work on soedge_a_baseboard_shell, updated sbc model framework 2024-07-14 21:42:29 -04:00
Edward Kisiel
aca4c96b1d updated quartz64b and passed test case quartz64b_shell, sbc model framework updated 2024-07-10 20:17:02 -04:00
Edward Kisiel
6527951336 rockpro64 adjustments, indent reposition for jack_3.5 and sbc model framework update 2024-07-04 10:12:44 -04:00
Edward Kisiel
a4aed16cbc modifications to star64, rock64 and indent.scad for jack_3.5, updated sbc model framework 2024-07-01 20:02:17 -04:00
Edward Kisiel
8815141155 added BPi-F3_shell, milk-V_duoS_shell cases and updated sbc model framework 2024-06-24 20:03:35 -04:00
Edward Kisiel
29192ea441 changed how the inner corner fillet is derived, added a note in the README.md file about updating the submodule sbc model framework as well as other readme.md corrections. 2024-06-09 17:18:19 -04:00
Edward Kisiel
6e49f76b4e bpif3 added and sbc model framework updated 2024-06-07 19:42:03 -04:00
Edward Kisiel
c952df6a28 expanded README.md, updated get_customizer_values and acccessory entries 2024-06-06 16:13:49 -04:00
Edward Kisiel
11b869daeb rework of extended case standoff placement based on standoff support size, cs-solar_energy_meter and avr_env_sensors case adjustments 2024-06-02 17:29:58 -04:00
Edward Kisiel
82fd693b04 increased top and bottom standoff adjustments range from 20mm to 30mm 2024-06-01 20:18:54 -04:00
Edward Kisiel
45c4f7e97f added cnano-avr128da48, adjustments to cs-solarmeter and updated sbc_model_framework 2024-05-31 16:36:27 -04:00
Edward Kisiel
9511f0263b initial standoff support for multiple secondary pcb assemblies 2024-05-30 20:57:40 -04:00
Edward Kisiel
a151de9575 restored rock5b accessory entries for standoff trim 2024-05-26 16:03:43 -04:00
Edward Kisiel
319bbe516e added multi-pcb indent support, new devices nodemcu-32s and cs-solarmeter 2024-05-26 15:57:06 -04:00
Edward Kisiel
f8684b715f added oem_rpi library and corrected parametric header 2024-05-15 20:54:29 -04:00
Edward Kisiel
d233f4c9c8 added rpi_m2hat model, example case rpi5_m2hat_shell and supporting plumbing 2024-05-15 20:47:35 -04:00
Edward Kisiel
9516fc4d03 increased star64 standoff support size 2024-05-11 08:48:56 -04:00
Edward Kisiel
a6e8e1d147 updated star64 pcb thickness and sdcard style 2024-05-11 08:43:35 -04:00
Edward Kisiel
62d6d15389 fixed fan_2 mask, created shared fan and heatsink mask code and readme.md updates and corrections 2024-05-10 21:57:12 -04:00
Edward Kisiel
ba9832a972 added 25mm fan model and mask opens, more sbc model framework changes 2024-05-10 20:27:11 -04:00
Edward Kisiel
0dcc224da2 updated sbc_model_framework for star64 changes 2024-05-10 16:39:44 -04:00
Edward Kisiel
c9ad238b9f corrected stl_model classes to model in readme.md 2024-05-10 16:36:34 -04:00
Edward Kisiel
1c33a21f3d Merge pull request #33 from yegct/patch-1
Update README.md
2024-04-30 17:06:54 +00:00
Chris Thompson
513712fcf9 Update README.md
it’s -> its, trivial grammar correction
2024-04-30 08:48:59 -06:00
Edward Kisiel
a88ac9457e lowered max bottom height for h4 series and changed heatsink stub location for nio12l 2024-04-29 22:23:55 -04:00
Edward Kisiel
1f2bb6613a added h4, h4+ and h4_ultra with updated sbc model framework 2024-04-29 18:29:39 -04:00
Edward Kisiel
a3f576edb9 changed adapter hole size to 4mm 2024-04-29 10:54:00 -04:00
Edward Kisiel
ddd7c0b4bd removed unneeded h3_port_extender.stl model and updated readme.md 2024-04-28 13:43:58 -04:00
31 changed files with 12858 additions and 2391 deletions

423
README.md
View File

@@ -19,7 +19,9 @@ License: GPLv3.
git submodule update
```
NOTE: The submodule *SBC Model Framework* needs to be updated anytime SBC Case Builder is updated.
## SBC Case Builder Features:
- Autonomous Multi-SBC, Multi-Case Parametric Generation
- Autonomous SBC and Accessory Model I/O Openings
@@ -32,7 +34,12 @@ License: GPLv3.
- SBC Associations
- SBC_X,Y - Case_Z Association
- Graphical User Interface
- SBC Model Framework Validation Tool
- SBC Meta Data Access
- Individual Standoff Parameter Control
- Dynamic Heatsink Fan Size, Vent and Mask Openings
- Top and Bottom Case Cover Patterns
- Parametric Bottom Access Panel
### Base Case Designs:
- Shell - complete
@@ -49,50 +56,130 @@ License: GPLv3.
- Paper, Folded - complete
- Standard MB SBC Adapters & io plates - completed
+ SSI-EEB, SSI-CEB, ATX, Micro-ATX, DTX, Flex-ATX, Mini-DTX, Mini-Itx, Mini-ITX Thin, Mini-STX, Mini-STX Thin
- Standard MB Cases - completed
- Standard MB Cases - complete
+ SSI-EEB, SSI-CEB, ATX, Micro-ATX, DTX, Flex-ATX, Mini-DTX, Mini-ITX, Mini-ITX Thin, Mini-STX, Mini-STX Thin, Nano-ITX, NUC, Pico-ITX
- Sheet Metal, Folded
- NAS - panel_nas complete
- Rack - 1U and 2U complete
- Stacked Levels
- Sliding
- Cylinder
- Free Form
- NAS
- Rack
- Sheet Metal, Folded
- CNC Cases
All case data is stored in the json file sbc_case_builder.json with the accessory data stored in a separate file structure in sbc_case_builder_accessories.cfg. An accessory group name for a given case is stored as part of the case data in the json file. This allows for the reuse or sharing of an accessory set by different cases and can be used to manage groups of accessories.
Variable height automated SBC standoffs, which can be individually adjusted, are also implemented to integrate add-on PCB, hats, heatsinks or other accessories that share SBC standoffs for mounting.
Multi-associative parametric positioning of accessories is implemented and allows each accessory to enable or disable parametric movement of the accessory for each axis. The XY and Z axis can be associated with the case offset (size), SBC positioning, multi-associated axises or absolute positioning. For instance, a SBC fan opening needs to follow the SBC in the X and Y axis but the case Z axis for the correct height.
```
p
a
r
r a s
o m e
t e s s s l t m
c l l l a t i i i e s
l t o o o f t r z z z d m n b t
a y c c c a i i e e e a a g a y
s p c o c t s t c l
s, e, x, y, z, e, n, s, x,y,z, a, k h k e
"sub","fan",10,10,24.5,"top",[0,0,0],["sbc-case_z",true,true,true],[40,0,6],[0],[true,10,2,"default"],
## Graphical User Interface
The GUI has multiple tabs that control what model and case is displayed, how it is presented, its adjustments, options and associated accessories. There are separate tabs in the GUI for *Folded Case Adjustments*, *Standard Motherboard Case Adjustments* and *3D Case Adjustments*. The first two have unique settings that only apply to the respective case designs. 3D case adjustments affect all others case designs and some entries can also affect Folded and Standard Motherboard cases as well. There are three groups of two tabs each associated with SBC, Extended Case and Multi-PCB standoffs.
![Image](SBC_Case_Builder_GUI.gif)
### View Tab
The View Tab allows the selection of various viewing modes and the selection of the device model for which a case is being generated. The *view* pickbox allows the respective case to be displayed as a 3D model, platter for 3D printing and as an individual case part, which can be selected using the *individual part* pickbox. The *section part* checkbox sections the selected part for dxf or other 2D export. The *sbc model* pickbox selects the device (SBC, MCU, Motherboard, etc). The *sbc off* and *sbc information* are self explanatory. The *sbc highlight* shows the subtractive openings that are being automatically created by SBC Model Framework while the *accessory highlight* shows the subtractive openings being generated by entries in the file sbc_case_builder_accessories.cfg. The later is useful when trying to visually place a subtractive accessory.
### Folded Case Adjustments Tab
This tab exclusively deals with folded cases. At this time the bend allowance equations are not complete and limits its use to paper and other thin materials with a low bend radius. Once folded metal cases are implemented the bend allowance equations will be complete and allow for any bendable material of any given bend radius. With that said, these adjustments are used for the paper_full-top and paper_split-top case designs and the *material thickness* and *bend Allowance* adjustments still need to be set appropriately for proper use. The *bottom clearance* adjustment allows additional bottom height adjustment for those wishing to use user provided standoffs on the bottom of the device for better stability. The *flat blank section* checkbox generates a flat blank based on the aforementioned settings. Once it has been generated the model must be rendered(F6) to produce a 2D blank that can then be exported as a DXF or SVG file for printing or fed to a CNC cutter.
### Standard Motherboard Case Adjustments Tab
Both standard motherboard adapters and cases can be generated with SBC Case Builder and this tab controls the specific settings. Since it is not possible to know the motherboard thickness it is set to 2mm and the *standard motherboard thickness* setting is used to add or subtract thickness for an accurate representation of the user provided PCB. The *rear io shield* setting is only used when generating full cases and is not needed when generating adapters and io shields. Most of the adjustments in the *3D Case Adjustments* tab also work for motherboard adapters which allows for the SBC or other device to be repositioned on the adapter while providing the full use of the accessory subsystem. Any accessory entries in the sbc_case_builder_accessories.cfg file should reference the bottom face. The *bottom cover pattern* in the *Fan and Vent Openings* tab and the *SBC Bottom Standoff* tabs also apply to motherboard adapters. There are predefined example cases and adapters available in the GUI for further reference.
### Rack Mount Case Adjustments Tab
Both 1U and 2U, 10" and 19", rack cases are configured in this tab. The first entry *rack width* selects if 10" or 19" rack cases are being created. The *rack size* sets whether 1U or 2U. There is a 2mm wall in front of every removable bay. *removable bay height* allows the tray height to be reduced to form an opening which allows for tray removal and venting when installed with other rack cases above. The remaining tab is divided into six groups of settings each representing a virtual bay. Each bay group specifies the SBC thru the pickbox *Rack Bay1* respectively. With *rack bay1 xyz loc* and *rack bay1 rotation determining the position and z-axis rotation. The type of bay is set in the *rack bay1 face* pickbox followed by two checkboxes for the internal dividing wall, rear fan and a bay conduit selection pickbox.
### 3D Case Adjustments Tab
The *3D Case Adjustments* tab makes up the bulk of the possible case adjustments for 3D printed cases. Most of the entries in this tab are self explanatory. The *pcb loc* adjustments allow the selected device model to be moved in the case design, the *case offset* adjustments increase the selected case design dimensions. The *wallthick*, *floorthick* and *sidethick* adjust their respective areas. Do note that the *floorthick* adjustment also determines the ceiling thickness for all case designs and the *sidethick* only affects the tray_sides, tray_vu5, tray_vu7 case designs. The *gap* entry is the distance between the device PCB and the sidewall of the case design. The *tol* adjustment, located at the bottom of the tab, is a tolerance fitment adjustment for the snap, fitted, round and hex case design tops. Adjust accordingly if the tops are too tight or loose.
### Fan and Vent Openings Tab
This tab handles the fan and cooling options for case designs. The *top cover pattern*, *bottom cover pattern* and *front cover pattern* contain several options for the creation of vent patterns that cover the complete panel, including a solid covering. The *cooling* pickbox selects fan and vent openings exclusively for the heatsink associated with the device in SBC Model Framework.
```
disable - turns off the heatsink model and mask
off - heatsink model is off, mask is on and default will be used
default - heatsink model is on and uses the mask setting in ./SBC_Model_Framework/sbc_models.cfg
none - heatsink model is on and mask is off.
fan and vent pattern selections - open, fan_open, fan_1, fan_2, fan_hex, vent, vent_hex_5mm, vent_hex_8mm
custom - uses the file ./SBC_Model_Framework/customfan.dxf
```
The *fan size* allows the selection of different fan size masks over the default size selected by 0. The rear fan entries are for the *panel_nas* case design and allow for the same types of fan adjustments as the heatsink. There is also the choice of one or two rear fans as well as additional adjustments for the position and spacing of them.
### Bottom Access Panel Tab
This tab allows the creation of a bottom access panel and its entries are self explanatory. Additional access panels can be implemented using the accessory subsystem.
### Options and Accessories
The entrys in this tab allow for the enablement and selection of different options and accessories. It includes case indents, GPIO, and UART openings based on their type identifier in SBC_Model_Framework. It also contains hard drive options for the panel_nas case.
#### GPIO Selections
```
disable - turns off the GPIO model and mask
off - GPIO model is off, mask is on and default will be used
default - GPIO model is on and uses the mask setting stored in ./SBC_Model_Framework/sbc_models.cfg
none - GPIO model is on and mask is off
mask opening selections - open, block, knockout, vent
```
An array holds a string and 3 Boolean that represent which association and axis are enabled for parametric movement. In the accessory example above, the 8th parameter `["sbc-case_z",true,true,true]` means all axises are enabled for multi-associative movement with the X and Y accessory axis following the SBC X and Y axis and the accessory Z axis following the case Z axis. The other currently supported associations are “sbc” and “case”. If other associations of objects are needed or are of value, they can be added in the future. All of the existing cases have been made parametric and can serve as further working examples.
#### UART Selections
```
default - UART model is on and uses the mask setting stored in ./SBC_Model_Framework/sbc_models.cfg
none - UART model is on and mask is off
mask opening selections - open, knockout
```
## Notes
The *indent* checkbox enables indents for a select group of components defined in SBC Model Framework. The currently support components are - video-hmdi_a, video-hdmi_micro, video-hdmi_mini, power-pwr5.5_7.5x11.5, power-pwr2.5_5x7.5, usb2-micro, usbc-single_horizontal, audio-jack_3.5. The *accessory name* pickbox uses the unique accessory group name to associate a given accessory set with a case design. Entries are stored in the file sbc_case_builder_accessories.cfg which is covered in detail with the Accessory Subsystem in this document. The remaining two entries select the color and proportional font used with the *sbc information* display when enabled in the *View* tab.
Due to the number of possibilities, no pre-compiled case stls are included.
#### NAS HD Options
The *nas sbc location* pickbox allows the positioning of the SBC at the top or bottom of a NAS case. *hd bays* sets the number of drive bays, *hd reverse* checkbox rotates the drives 180 degrees while *hd center* centers the drives in the x-axis. The next entry, *hd space* determines the spacing between drives and *hd y position* and *hd z position* sets the respective axis locations.
“tol”, located at the bottom of the Adjustments Tab, is a tolerance fitment adjustment for the snap, fitted, round and hex tops. Adjust accordingly if the tops are too tight or loose.
#### Accessory Group Name
The *accessory name* allows the selection of an accessory group to be associated with the current case. These groups are located in the file sbc_case_builder_accessories.cfg and provide a means to add or subtract geometry, models and add items to the print platter. See the *Accessory Subsystem* area below for further details and use.
## Case Designs and Styles
The case naming convention for standard cases in the configuration file follow the basic form of “sbc”_”design”_”style” e.g. c4_shell or c4_tray_vu5.
### Standoff Tabs
There are 3 types of standoffs available in the user interface, SBC Standoffs, Extended Case Standoffs and Multi-PCB Standoffs. The SBC standoffs control adjustments for the SBC or pcbid 0 as defined by the entry in SBC Model Framework file ./SBC_Model_Framework/sbc_models.cfg. The Extended Case Standoffs control case corner standoffs when the case exceeds the SBC size by the *SBC Standoff Support Size*. The Multi-PCB standoffs are used for additional PCB in multi-PCB configurations as defined in ./SBC_Model_Framework/sbc_models.cfg e.g. pcbid 1, pcbid 2, etc. All three standoff types have similar controls made up of a global tab and individual Settings tab in the GUI.
## Accessory Schema
The schema for case accessories is documented in the beginning of the file sbc_case_builder_accessories.cfg. There is one fixed entry that is the accessory set name followed by an unlimited number of accessory entries each containing 11 entries.
The main difference between the different standoff groups are that the SBC Standoffs are located by the SBC PCB holes, the Extended Case Standoffs are located in the four corners of a case design that exceeds dimensions of the intended device by the size of the *SBC Case Standoff Support Size* and the Multiple PCB Standoffs are located by the holes of the additional PCBs that makeup a given device. The entries for the standoffs are basically the same so only the top SBC standoffs will be specifically covered.
#### Standoff Global Settings
The tab *SBC Top Standoff Global Settings* affects all the respective standoffs and starts with three checkboxes. The first, *sbc top standoffs*, enables or disable all the top standoffs. The second, *top standoff reverse*, rotates the standoff 180 degrees and is used primarily for standoffs associated with the top face of all case designs. The last, *top sidewall support*, enables or disables the side wall support for all SBC top standoffs. The first pickbox in the tab is called *top standoff size* and determines the overall size of the SBC top standoffs. It is made up of named sizes that are predefined and a custom entry that is defined by the remaining entries in the tab. The predefined named top standoff sizes are further divided into entries where only the hole size is different e.g. m3, m3+, m3_tap. The m3 entry has a 3mm hole, the m3+ entry's hole is approximately 15% larger for clearance and the m3_tap entry's hole size is the tap drill size. When a named size is selected the *top standoff diameter* and *top standoff hole size* entries have no effect but the remaining entries do apply - it is the *custom* entry that allows full control of all parameters.
The *top standoff support size* and *top standoff support height* is what allows recessed *top standoff type* entries to work on thin wall
floors and ceilings by providing the extra size and depth for the given recess. This applies to the *top standoff type* selections countersunk, recessed and nutholder. The recessed entry also allows for deep recessed screws by recessing the standoff for the full height of the *standoff support height* less 2mm. This can be deployed for tall cases in order to use shorter fasteners and is the most practical way to handle this scenario. The *top standoff insert* checkbox enables the use of inserts of the size defined by *top standoff insert dia* and *top Standoff insert height* at the opposite end of the standoff. This allows case halves to be fastened together thru the bottom of the case and is another alternative to dealing with tall case designs.
#### Standoff Individual Settings
The *SBC Top Individual Settings* entries control variable on a per standoff basis. There are four entry groups each controlling a standoff's enablement, height adjustment and sidewall support location. This is useful when dealing with hats or other accessories that share SBC PCB holes for mounting. Likewise, being able to change the direction of the sidewall support allows for a wider choice to strengthen and tie the standoff to the case walls or completely disable them if SBC components interfere. The length of the sidewall support is equal to the respective *standoff support size* for SBC, Extended Case and Multi-PCB standoffs.
As indicated previously, The SBC Standoffs, Extended Case Standoffs and Multi-PCB Standoffs all work the same with the following exceptions. The *standoff support size* is also used to determine the corner proximity for the Extended Case standoffs. The Multiple PCB Standoffs present a unique challenge due to their nature. There will be situations with multiple PCB devices when not all the standoffs created by the PCB holes will be needed. Imagine two PCBs next to each other that would normally create eight standoffs. In many scenarios only outer standoffs are needed for both the top and bottom and the bottom inner standoffs for PCB support. In order to handle this and many other situations without creating a complex and burdensome GUI, an entry for the creation of the PCB hole can be used to disable the top, bottom or both standoffs. This is accomplished within the SBC Model Framework pcbhole class. The person creating the sbc_models.cfg entry can determine and override the creation of these standoffs in SBC Case Builder. See the SBC Model Framework pcbhole class for further details.
## Notes, Tips and Things to Check
SBC Case Builder by default makes the smallest symmetrical case possible for the SBC selected and default parameters. Most times this works well but some SBC need asymmetrical spacing, extra gap or additional standoff clearance and may require tweaking to obtain the best results. If there is a saved case for an SBC it is best to start your new case with it, or at least become familiar with any special changes made, since they might apply to a new case.
### Standoff Selection, Inserts and Clearance
Standoff selection and implementation is the most effected part of customizing a case. Some SBC can use a M3 screw and others only use a M2.5 or M2 screw. Finding the best fastening approach can be influenced too by the hardware one has on-hand or personal preference. If using inserts, a custom standoff size must be used since the standard standoff sizes are to small for their respective insert diameter. For tall cases, fastener length can be reduced by using a deep recessed standoff, the depth set by the *standoff support height* after selecting a *recessed* type under the appropriate global Tab . Watch for standoff clearance issues around PCB holes and neighboring components. Some SBC designs crowd the area and can interfere with standoff diameter sizes, especially when inserts are being used. This is one factor that may determine whether to fasten the case from the top or bottom.
### Component Overhang and Case Gap
As previously stated, symmetrical cases use the same gap spacing for all sides. This has worked well but more recently many SBC use significantly different component overhangs and could benefit from an asymmetrical case. By increasing the case size by the needed amount in an axis and possibly shifting the PCB the same amount or not, an asymmetrical case gap can be created to accommodate SBC with significantly differing overhangs. This is especially import if opposing sides of an SBC use component overhangs greater then 2mm which may also influence the assembly of the case.
### Geometry Placement, Alignment and Interference Checking
When using subtractive geometry accessories, turning on *accessory highlight* under the *View Tab* will help in placing and aligning objects.
Use case sections to view inside a closed case by setting to -1 the *move side* slider under the *View Tab*. Platter view can be useful to view changes and as a final check if everything is configured as required prior to STL export.
### Using Accessories Dynamically
Having SBC Case Builder running while editing the sbc_case_builder_accessories.cfg file using a separate text editor will aide in visual accessory manipulation and placement. OpenSCAD will automatically regenerate the model preview when the accessory configuration files is saved.
## Accessory Subsystem
Case accessories entries are kept in the file sbc_case_builder_accessories.cfg. Newly created accessory group names also need to be added to the variable accessory_name in sbc_models.scad on or around line #128 in order for them to appear in the GUI pickbox. Any new accessory group names must be added to the pickbox entry or they will not be present in the GUI. This can be done manually or the helper script get_customizer_values.scad can be used to generate a complete accessory names list for copy and paste from the console.
### Accessory Schema
Each accessory group consists of a unique name followed by an unlimited number of accessory entries each containing 11 variables.
```
schema:
@@ -122,36 +209,37 @@ e.g.
"sub","fan",10,10,24.5,"top",[0,0,0],["sbc-case_z",true,true,true],[40,0,6],[0],[true,10,2,"default"],
```
Every type, regardless of its class, uses a basic set of variables
Every type, regardless of its class, uses a basic set of variables
`(loc_x,loc_y,loc_z,”face”,rotation[],parametrics[])`
but each type doesnt necessarily use all available data fields
`(size[],data[])`
The parametric array specifies the axis to enable for associated parametric positoning. An accessory can be associated with the sbc position("sbc"), case offset("case"),multi-associated which use sbc xy postion and case z offset(sbc-case_z) or use absolute values if all axises are false.
Multi-associative parametric positioning of accessories is implemented and allows each accessory to enable or disable parametric movement of the accessory for each axis. The XY and Z axis can be associated with the case offset (size), SBC positioning, multi-associated axis's or absolute positioning. For instance, a SBC fan opening needs to follow the SBC in the X and Y axis but the case Z axis for the correct height. The parametric array specifies the axis to enable for associated parametric positioning. An accessory can be associated with the sbc position("sbc"), case offset("case"),multi-associated which use sbc xy position and case z offset("sbc-case_z") or use absolute values if all axis's are false. In the accessory example above, the 8th parameter `["sbc-case_z",true,true,true]` means all axis's are enabled for multi-associative movement with the X and Y accessory axis following the SBC X and Y axis and the accessory Z axis following the case Z axis.
### classes: add1, sub, suball, add2, model, platter
Class “add1” and “add2” are used to add geometry to the case. The difference is when the addition occurs. “add1” happens at the beginning when the core case geometry is created before any subtractions and add2 happens at the end after all subtractions have occurred. suball is used to affect all faces of a case, not just a single face. The “face” is the case piece that will be effected by the addition or subtraction. The "model" class is for placing supporting accessories in the model view. e.g. hard drives, fans. The "platter" class is for adding supporting accessories to the print platter.
Class *add1* and *add2* are used to add geometry to the case. The difference is when the addition occurs. *add1* happens at the beginning when the core case geometry is created before any subtractions and *add2* happens at the end after all subtractions have occurred. *suball* is used to affect all faces of a case, not just a single face. The “face” is the case piece that will be effected by the addition or subtraction. The *model* class is for placing supporting accessories in the model view. e.g. hard drives, fans. The *platter* class is for adding supporting accessories, that are not part of the core case geometry, to the print platter for printing e.g. a fan cover or access panel cover.
**additive type:**
circle, rectangle, slot, text, art, standoff, batt_holder, uart_holder, hd_holder, hd_holes, hd_vertright_holes, hc4_oled_holder, access_panel, button, pcb_holder, boom_grill, boom_speaker_holder
art, access_panel, batt_holder, button, button_assembly, fan_cover, feet, grommet, hd_holder, hk_boom_grill, hk_boom_speaker_holder, hk_boom_vring, hk_h3_port_extender_holder, hk_hc4_oled_holder, hk_uart_holder, hk_uart_strap, keyhole, nut_holder, panel_clamp, pcb_holder, rectangle, round, slot, sphere, standoff, text, vent_panel_hex, uart_holder, hc4_oled_holder, button, pcb_holder
**subtractive type:**
circle, rectangle, slot, text, art, punchout, vent, fan, hd_holes, hd_vertleft_holes, hd_vertright_holes, microusb, sphere
art, fan_mask, hd_holes, knockout, rectangle, round, slot, sphere, text, vent, vent_hex
**model type:**
uart_strap, fan_cover, hd25, hd35, hc4_oled, feet, access_cover, net_card, hk35_lcd, hk_boom, boom_speaker, boom_vring, hk_uart
access_cover, adafruit_lcd, dsub, fan, hd25, hd35, hk_boom, hk_boom_speaker, hk_h3_port_extender, hk_hc4_oled, hk35_lcd, hk_m1s_ups, hk_net_card, hk_pwr_button, hk_speaker, hk_uart, hk_vu7c, hk_vu8m, hk_vu8s, hk_wb2, hk_xu4_shifter_shield, pillar, rpi_m2hat, stl_model
**platter type:**
uart_strap, fan_cover, access_cover, button_assembly, boom_vring
access_cover, button_assembly, fan_cover, feet, grommet, hk_boom_vring, hk_h3_port_extender_holder, hk_uart_strap, vent_panel_hex
## Accessory Reference Manual
@@ -376,6 +464,35 @@ DESCRIPTION: creates case feet.
```
### grommet
```
CLASSES: add1, add2, platter
DESCRIPTION: creates different groumet styles.
MASK: yes
USAGE: "class", "grommet", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "add1", "add2", "platter"
type = "grommet"
loc_x = x location placement
loc_y = y location placement
loc_z = z location placement
face = "top", "bottom", "right", "left", "front", "rear"
rotation[] = object rotation
parametric[] = "case", "sbc", "sbc-case_z"
size[0] = od outside diameter of grommet body
size[1] = id inside hole diameter of grommet body
size[2] = wall thickness of installation
data[0] = "top","bottom","front","rear","left","right"
data[1] = "sleeve"
data[2] = assembled true, false
mask[0] = true enables component mask
mask[1] = mask length
mask[2] = mask setback
mask[3] = mstyle "default"
```
### hd_holder
```
@@ -679,7 +796,7 @@ DESCRIPTION: creates nut holder of various styles.
size[0] = top diameter or x size in mm
size[1] = bottom diameter or y size in mm
size[2] = holder height in mm
data[0] = "m2", "m2.5", "m3", "m4"
data[0] = "m2", "m2.5", "m3", "m4", "m3-insert"
data[1] = "default", "sloped", "trap"
mask[0] = true
mask[1] = length
@@ -688,6 +805,35 @@ DESCRIPTION: creates nut holder of various styles.
```
### panel_clamp
```
CLASSES: add1, add2
DESCRIPTION: creates clamps to join two panels.
MASK: yes
USAGE: "class", "panel_clamp", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "add1", "add2"
type = "panel_clamp"
loc_x = x location placement
loc_y = y location placement
loc_z = z location placement
face = "top", "bottom", "right", "left", "front", "rear"
rotation[] = object rotation
parametric[] = "case", "sbc", "sbc-case_z"
size[0] = top diameter or x size in mm
size[1] = bottom diameter or y size in mm
size[2] = clamp height in mm
data[0] = orientation "top","bottom","rear","front","left","right"
data[1] = "sloped"
data[2] = "m2", "m2.5", "m3", "m4"
mask[0] = false
mask[1] = length
mask[2] = set back
mask[3] = mstyle "default", "holes"
```
### pcb_holder
```
@@ -998,6 +1144,7 @@ DESCRIPTION: creates hard drive holes for 2.5 and 3.5 drives in various orientat
data[1] = "portrait", "landscape"
data[2] = "left", "right", "both", "bottom", "all"
data[3] = floor thickness
data[4] = "hole", "slot"
mask[0] = false, not used
mask[1] = length
mask[2] = set back
@@ -1232,16 +1379,66 @@ DESCRIPTION: creates horizontal or vertical hex vent openings.
## Model class “types”
### adafruit_lcd
### adafruit_2030_powerboost
```
CLASSES: model
DESCRIPTION: creates bottom access cover for access panels.
DESCRIPTION: creates Adafruit 2030 Powerboost 1000 basic.
MASK: yes
USAGE: "model", "adafruit_lcd", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
USAGE: "model", "adafruit_2030_powerboost", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "model"
type = "adafruit_lcd"
type = "adafruit_2030_powerboost"
loc_x = x location placement
loc_y = y location placement
loc_z = z location placement
face = "top", "bottom", "right", "left", "front", "rear"
rotation[] = object rotation
parametric[] = "case", "sbc", "sbc-case_z"
size[] = not used
data[] = not used
mask[0] = true
mask[1] = length
mask[2] = set back
mask[3] = mstyle "default"
```
### adafruit_4311_lcd
```
CLASSES: model
DESCRIPTION: creates Adafruit 4311 2.0" 320x240 Color IPS TFT Display with microSD Card Breakout - ST7789 EYESPI.
MASK: yes
USAGE: "model", "adafruit_4311_lcd", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "model"
type = "adafruit_4311_lcd"
loc_x = x location placement
loc_y = y location placement
loc_z = z location placement
face = "top", "bottom", "right", "left", "front", "rear"
rotation[] = object rotation
parametric[] = "case", "sbc", "sbc-case_z"
size[] = not used
data[] = not used
mask[0] = true
mask[1] = length
mask[2] = set back
mask[3] = mstyle "default"
```
### adafruit_4755_solar_charger
```
CLASSES: model
DESCRIPTION: creates Adafruit 4755 Universal USB/DC/Solar Lithium Ion/Polymer charger - bq24074.
MASK: yes
USAGE: "model", "adafruit_4755_solar_charger", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "model"
type = "adafruit_4755_solar_charger"
loc_x = x location placement
loc_y = y location placement
loc_z = z location placement
@@ -1287,7 +1484,7 @@ DESCRIPTION: creates db connectors.
```
CLASSES: model
DESCRIPTION: creates db connectors.
DESCRIPTION: creates fans.
MASK: yes
USAGE: "model", "fan", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
@@ -1300,7 +1497,7 @@ DESCRIPTION: creates db connectors.
rotation[] = object rotation
parametric[] = "case", "sbc", "sbc-case_z"
size[] = not used
data[0] = "box30x10","box40x10","box50x10","box60x10","box80x10","box80x25","box92x10","box92x25","box120x25","box140x25"
data[0] = "box25x10","box30x10","box40x10","box50x10","box60x10","box80x10","box80x25","box92x10","box92x25","box120x25","box140x25"
mask[0] = true
mask[1] = length
mask[2] = set back
@@ -1763,15 +1960,69 @@ DESCRIPTION: creates hk odroid-xu5 level shifter shield model.
```
### pillar
```
CLASSES: model
DESCRIPTION: creates pillars with female ends.
MASK: yes
USAGE: "model", "pillar", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "model"
type = "pillar"
loc_x = x location placement
loc_y = y location placement
loc_z = z location placement
face = "top", "bottom", "right", "left", "front", "rear"
rotation[] = object rotation
parametric[] = "case", "sbc", "sbc-case_z"
size[0] = outside diameter
size[1] = inside diameter
size[2] = height
data[0] = "hex", "round"
data[1] = "color"
data[2] = side "top" or "bottom"
mask[0] = false
mask[1] = length
mask[2] = set back
mask[3] = mstyle "default"
```
### rpi_m2hat
```
CLASSES: model
DESCRIPTION: adds Raspberry Pi M.2 HAT+ M Key model
MASK: yes
USAGE: "model", "rpi_m2hat", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "model"
type = "rpi_m2hat"
loc_x = x location placement
loc_y = y location placement
loc_z = z location placement
face = "top", "bottom", "right", "left", "front", "rear"
rotation[] = object rotation
parametric[] = "case", "sbc", "sbc-case_z"
size[] = not used
data[] = not used
mask[0] = true, false
mask[1] = length
mask[2] = set back
mask[3] = mstyle "default"
```
### stl_model
```
CLASSES: add1, add2
CLASSES: model
DESCRIPTION: adds stl models.
MASK: no
USAGE: "class", "stl_model", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
USAGE: "model", "stl_model", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "add1", "add2"
class = "model"
type = "stl_model"
loc_x = x location placement
loc_y = y location placement
@@ -1781,7 +2032,7 @@ DESCRIPTION: adds stl models.
parametric[] = "case", "sbc", "sbc-case_z"
size[] = not used
data[0] = scale
data[1] = "file"
data[1] = "file name"
mask[0] = false, not used
mask[1] = length
mask[2] = set back
@@ -1900,6 +2151,35 @@ DESCRIPTION: creates case feet.
```
### grommet
```
CLASSES: add1, add2, platter
DESCRIPTION: creates different groumet styles.
MASK: yes
USAGE: "class", "grommet", loc_x, loc_y, loc_z, face, rotation[], parametric[], size[], data[], mask[]
class = "add1", "add2", "platter"
type = "grommet"
loc_x = x location placement
loc_y = y location placement
loc_z = z location placement
face = "top", "bottom", "right", "left", "front", "rear"
rotation[] = object rotation
parametric[] = "case", "sbc", "sbc-case_z"
size[0] = od outside diameter of grommet body
size[1] = id inside hole diameter of grommet body
size[2] = wall thickness of installation
data[0] = "top","bottom","front","rear","left","right"
data[1] = "sleeve"
data[2] = assembled true, false
mask[0] = true enables component mask
mask[1] = mask length
mask[2] = mask setback
mask[3] = mstyle "default"
```
### hk_boom_speaker_holder
```
@@ -2032,21 +2312,62 @@ DESCRIPTION: creates hex pattern covers for vent openings.
```
## Accuracy
In the past there was been no way of validating whether a SBC Model Framework model and its components were dimensionaly accurate in their size and placement other then trial and error. Along with producing cases this project provides a much needed model validation tool to assure model accuracy thru the use of test cases. It works on the very simple premise that if the real SBC fits the test case then the virtual model is accurate or otherwise shows were corrections are needed. This will further increased the overall accuracy of models.
## Case Build Notes
This area covers specific build notes for specific cases. Hardware used or other relavent information is list by case design name.
Some SBC in SBC Model Framework have not been validated or may be missing component data and may produce one or more aspects of a case incorrectly. SBC status is noted in sbc.png, the README.md file and at the beginning of the SBC entry defined in sbc_models.cfg, all a part of SBC Model Framework. The color coded indicator of an SBCs verification and completion as indicated in sbc.png is as follows:
### panel_nas Case Design
The panel_nas design can be CNC cut or 3D printed. By changing the top and bottom standoff type to "none" in the *SBC Standoff Global Settings* tabs respectively, only a hole is generated for CNC cutting support. Panels can be exported in DXF or SVG by selecting the *part" view under the *view* tab, then the indivual part and select the *section part* checkbox. After the projection has been generated render it by pressing F7 or by selecting render from the user interface. Exported DXF and SVG file formats are available under the File->Export menu.
Normally the top and bottom height added together is the overall case height for other cases. But with hard drives involved there is additional height which is represented in its total by the height value. In the example, the top is 41mm tall from the outside of the case to the top of the PCB. In a bottom mounted case, 22.25mm measurement would be from the bottom of the case to the top of the PCB, which is sunk by its thickness so that the PCB top is even with the top edge of the bottom case piece normally. So the equations for the standoff lengths would be:
Top standoff length = top height floor thickness
38mm = 41mm 3mm
Bottom standoff height = bottom height floor thickness PCB thickness
17mm = 22.25mm 3mm 2.25mm
2.5” drives are supported using a 3.5” holder adapter. There is one in SBCCB that can be accessed using a new program, sbccb_accessory_tool.scad. The holder can also be wider then a 3.5” drive (101.6mm) for an exact case fit.
For internal mounted rear fans, room above the rear fans equal to the 10mm tab size is required to remove the rear piece.
### rack Case Design
This case is divided into 3 pieces for the 19" cases and 2 pieces for the 10" cases. They can be selected in the *part* view for STL export under the *view* tab by selecting the left, bottom or right individual part. The peices are held together using M2x8mm screws and nuts.
10” rack case Qty 5 - M2x8mm screws cap or countersunk with nuts.
19” rack case Qty 10 - M2x8mm screws cap or countersunk with nuts.
Appropriate fasteners for all SBC.
For a better fit, prep the edges of the case pieces prior to assembly. Use sand paper or a file to remove any imperfections and true the edge.
Using 2mm thickness for the floor and walls provides for an adequate case in most enclosed applications but a 3mm floor or better is recommended for removable and open front cases.
There are 3mm holes on the left, center and right, both front and rear, to use for feet when deployed as a single bench top case. If using the rack stands, the holes can be used to mount an external standoff to support the rear of a heavy case.
All case bodies can be printed without the use of support. Only the removable bay tray needs support for printing. SBC placement so as to bisect a SBC opening with a case divide, will require print supports.
Varies accessories (1u rack stand, grommets, fan covers, 2.5” drive holder, washers, etc) are available from sbccb_accessory_tool.scad. The table top rack stand is comprised of two interchangeable brackets that can hold 1U-4U rack cases.
## Accuracy
In the past there was been no way of validating whether a SBC Model Framework model and its components were dimensionaly accurate in their size and placement other then trial and error. Along with producing cases this project provides a much needed model validation tool to assure model accuracy thru the use of test cases. It works on the very simple premise that if the real SBC fits the test case then the virtual model is accurate or otherwise shows were corrections are needed. This will further increased the overall accuracy of models over time.
Some SBC in SBC Model Framework have not been validated or may be missing component data and may produce one or more aspects of a case incorrectly. SBC status is noted in sbc.png and sbc_models_viwer.scad, all a part of SBC Model Framework. The color coded indicator of a SBCs verification and completion is indicated in sbc.png as follows:
- GREEN = verified, complete and passes SBC Case Builder
- YELLOW = unverified, mostlikely usable and/or missing minor information
- ORANGE = unverified, may be usable but missing component data
- RED = unverified, not usable due to incomplete component data
The SBC that I do not own have been created using manufacturer supplied mechanical drawings. Some of the drawings are missing information or have errors that effect all or part of the drawings and subsequent SBC models. If you own an SBC that is not represented or verified in SBC Model Framework, please consider adding it or helping to correct errors in existing SBC data. An SBC can be verified to be accurate if a printed shell case from SBC Case Builder fits. Any misalignment is corrected in the SBC Model Framework model data(sbc_models.cfg).
The SBC that I do not own have been created using manufacturer supplied models, mechanical drawings or contributed by users. Some of the drawings are missing information or have errors that effect all or part of the subsequent SBC models. If you own an SBC that is not represented or verified in SBC Model Framework, please consider adding it or helping to correct any errors in the SBC data. An SBC can be verified to be accurate if a printed shell case from SBC Case Builder fits. Any misalignment is corrected in the SBC Model Framework model data(sbc_models.cfg).
## Future Development
There are a few more ideas for base cases to be worked on as well as a host of supporting accessory models that need to be created. It would also be nice to have all of the OEM accessories for each SBC in the library as well. Im still looking for a better way to create accessory entries and groups, and continue to expand and verify as many SBC as possible. With that and the obvious benefit of autonomously making SBC cases, this project has also been helping fulfill another personal goal.
There are a few more ideas for base cases to be worked on as well as a host of supporting accessory models that need to be created. It would also be nice to have all of the OEM accessories for each OEM in the library as well. Im still looking for a better way to create accessory entries and groups, and continue to expand and verify as many SBC as possible. With that and the obvious benefit of autonomously making SBC cases, this project has also been helping fulfill another personal goal.
Computer aided design(CAD) has been around along time but I have been interested in exploring approaches to the next step, computer autonomous design. Regardless of the current or future object creation method, whether it be manufactured or materialized, I believe a universal approach to autonomous design will be needed to advance the human condition. This application has helped me explore and think about practical approaches that might be possible right now in autonomous design and I hope to continue this work by developing new tools and techniques for the new CAD, Computer Autonomous Design.
Computer aided design(CAD) has been around a long time but I have been interested in exploring approaches to the next step, computer autonomous design. Regardless of the current or future object creation method, whether it be manufactured or materialized, I believe a universal approach to autonomous design will be needed to advance the human condition. This application has helped me explore and think about practical approaches that might be possible right now in autonomous design and I hope to continue this work by developing new tools and techniques for the new CAD, Computer Autonomous Design.
## Project Supporters
Thank You to the contributors for their contributions and also HardKernel and Pine64 for their support through the donation of SBC.

BIN
SBC_Case_Builder_GUI.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 MiB

View File

@@ -1,17 +1,19 @@
// Gets a list of SBCs from the SBC Model Framework and Accessory sets
// for use with SBC Case Builder.
// After running this script, copy the output from the first Echo command into the
// list of SBC boards in `sbc_case_builder.scad:32`
// Also copy the output from the second Echo command into the list of case acceessory
// sets in `sbc_case_builder.scad:196`
/* Gets a list of SBCs from the SBC Model Framework and Accessory sets
for use with SBC Case Builder.
After running this script, copy the output from the first Echo command into the
list of SBC boards in `sbc_case_builder.scad:32` and `sbc_case_builder.scad`
6 locations line 82,90,98,106,114,122 for the sbc selection for the rack case design.
Also copy the output from the second Echo command into the list of case acceessory
sets in `sbc_case_builder.scad:196`
*/
include <./SBC_Model_Framework/sbc_models.cfg>;
include <./sbc_case_builder_accessories.cfg>;
echo(" ");
boards = [for(i=[0:1:len(sbc_data)-1]) sbc_data[i][0]];
echo("Copy the following to `sbc_case_builder.scad` for the `sbc_model` variable");
echo(boards);
echo(" ");
accessory_sets = [for(i=[0:1:len(accessory_data)-1]) accessory_data[i][0]];
echo("Copy the following to `sbc_case_builder.scad` for the `accessory_name` variable");
echo(accessory_sets);
echo(" ");

View File

@@ -144,7 +144,7 @@ $fn = 90;
if(style == "recess") {
difference() {
cylinder(d=8.5, h=.8);
translate([-1.5,-1.75,-adj]) cube([2.75,3.5,1]);
translate([-1.5,-1.75,-adj]) cube([2.75,3.25,1]);
translate([-.75,-.75,-adj]) cube([5,1.25,1.25]);
}
}

View File

@@ -28,16 +28,20 @@
*/
module cableholder_spacer() {
module cableholder_spacer(length) {
size = [9.4,16,6];
adj = .01;
$fn = 90;
translate([0,size[2]/2,-5]) rotate([90,0,0])
difference() {
translate([size[0]/2,size[0]/2,0]) rotate([0,0,90]) slot(size[0],size[1],size[2]);
translate([-1,5,3]) rotate([0,90,0]) cylinder(d=3.2, h=12);
translate([-1,7.5,-1]) cube([2,20,9]);
translate([5,9.5,-1]) rotate([0,0,90]) slot(4.5,11,9);
union() {
translate([size[0]/2,size[0]/2,0]) rotate([0,0,90]) long_slot(size[0],size[1],size[2]);
translate([-length,5,3]) rotate([0,90,0]) cylinder(d=6, h=length+9.4);
}
translate([-length-adj,5,3]) rotate([0,90,0]) cylinder(d=3.2, h=length+size[0]+2*adj);
translate([-1,8,-1]) cube([2,20,9]);
translate([5,9.5,-1]) rotate([0,0,90]) long_slot(4.5,11,9);
translate([3,20,-1]) rotate([0,0,45]) cube([2,6,9]);
}
}

View File

@@ -50,7 +50,8 @@ module fans(style, mask) {
["box60x10", 60, 10, 50, 4.3, 30, "#353535"],
["box50x10", 60, 10, 40, 4.3, 20, "#353535"],
["box40x10", 40, 10, 32, 4.3, 18, "#353535"],
["box30x10", 30, 10, 24, 3.2, 12, "#353535"]
["box30x10", 30, 10, 24, 3.2, 12, "#353535"],
["box25x10", 25, 10, 20, 3, 12, "#353535"]
];
f = search([style],fan_data);
@@ -129,249 +130,3 @@ module fan_cover(size, thick, style) {
color("grey", 1) fan_mask(size, thick, style);
}
}
/*
DESCRIPTION: creates fan masks for openings
TODO:
USAGE: fan_mask(size, thick, style)
size = size of fan
thick = thickness of cover
style = "fan_open", "fan_1", "fan_2", "fan_hex"
*/
module fan_mask(size, thick, style) {
hole_pos = size == 30 ? 3 :
size == 40 ? 4 :
size == 50 || size == 60 || size == 70 ? 5 :
size >= 80 ? 3.75 : 3.75;
$fn = 90;
adj = .01;
if(style == "fan_open") {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-1);
// mount holes
translate([size-hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([size-hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
}
if(style == "fan_1" && size == 30) {
union() {
difference() {
union () {
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-2);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-8);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-11);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-17);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-20);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-25);
}
// mount holes
translate([size-hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([size-hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
}
translate([5, 4, -2]) rotate([0, 0, 45]) cube([size, 1.5, thick+4]);
translate([4, size-5, -2]) rotate([0, 0, -45]) cube([size, 1.5, thick+4]);
}
}
}
if(style == "fan_1" && size == 40) {
union() {
difference() {
union () {
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-2);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-8);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-11);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-17);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-20);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-25);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-28);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-35);
}
// mount holes
translate([size-hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([size-hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
}
translate([6.5, 5.5, -2]) rotate([0, 0, 45]) cube([size, 1.5, thick+4]);
translate([5, size-6, -2]) rotate([0, 0, -45]) cube([size, 1.5, thick+4]);
}
}
}
if(style == "fan_1" && (size == 50 || size == 60 || size == 70)) {
union() {
difference() {
union () {
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-2);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-14);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-18);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-30);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-34);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-46);
}
if(size > 50) {
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-50);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-59);
}
}
// mount holes
translate([size-hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([size-hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
}
translate([8.5, 7, -2]) rotate([0, 0, 45]) cube([size > 60 ? size+4 : size+1, 2, thick+4]);
translate([6.5, size-8, -2]) rotate([0, 0, -45]) cube([size > 60 ? size+4 : size+1, 2, thick+4]);
}
}
}
if(style == "fan_1" && size >= 80) {
union() {
difference() {
union () {
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-2);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-9);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-14);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-21);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-26);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-33);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-38);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-45);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-50);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-57);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-62);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-68);
}
if(size == 92) {
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-74);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-80);
}
difference() {
translate([size/2, size/2, -1]) cylinder(h=thick+2, d=size-85);
translate([size/2, size/2, -2]) cylinder(h=thick+4, d=size-91);
}
}
// mount holes
translate([size-hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([size-hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
}
translate([6.5, 4.25, -2]) rotate([0, 0, 45]) cube([size*1.2, 3, thick+4]);
translate([4.25, size-6.5, -2]) rotate([0, 0, -45]) cube([size*1.2, 3, thick+4]);
}
}
}
if(style == "fan_2") {
inner = size == 30 ? 24 :
size == 40 ? 32 :
size == 50 ? 40 :
size == 60 ? 50 :
size == 70 ? 61.9 :
size == 80 ? 71.5 :
size * 0.8; // Use 80% as default
rings = size <= 40 ? 4 : 6;
bar_size = size <= 40 ? 2 : 3;
screw_offset = inner / 2;
center_point = size * 0.5;
base_ring_size = size * 0.95;
rings_spacing = size / rings;
translate([size/2, size/2, -1])
union() {
translate([screw_offset, screw_offset, (thick+2)/2]) cylinder(d=3, h=thick+2, center=true);
translate([-screw_offset, screw_offset, (thick+2)/2]) cylinder(d=3, h=thick+2, center=true);
translate([screw_offset, -screw_offset, (thick+2)/2]) cylinder(d=3, h=thick+2, center=true);
translate([-screw_offset, -screw_offset, (thick+2)/2]) cylinder(d=3, h=thick+2, center=true);
difference() {
union() {
for(i=[inner:-rings_spacing:0]) {
difference() {
cylinder(d=base_ring_size - i, h=thick+2);
translate([0, 0, -1]) cylinder(d=base_ring_size - i - (rings_spacing/2), h=thick+4);
}
}
}
translate([0, 0, 11])
union() {
cylinder(d=bar_size*2+0.1, thick+2); // Add a circle to prevent any tiny holes around cross bar
rotate([0, 0, 45]) cube([size, bar_size, thick+4], center=true);
rotate([0, 0, 45]) cube([bar_size, size, thick+4], center=true);
}
}
}
}
if(style == "fan_hex") {
hex_pos = size == 30 ? [-11.75, -4.5, 0] :
size == 40 ? [-14, -11.25, 0] :
size == 50 ? [-16, -6.5, 0] :
size == 60 ? [-11, -1.5, 0] :
size == 70 ? [-13, -3.5, 0] :
size >= 80 ? [-8.25, -3.5, 0] : [-9, -4, 0];
union() {
difference () {
translate([1+(size-2)/2, 1+(size-2)/2, -1]) cylinder(h=thick+2, d=size-2);
union() {
difference() {
translate([1+(size-2)/2, 1+(size-2)/2, -1-adj]) cylinder(h=thick+3, d=size-2);
translate(hex_pos) vent_hex(15, 8, thick+4, 12, 2, "horizontal");
}
}
}
}
// mount holes
translate([size-hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([size-hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, size-hole_pos, -1]) cylinder(h=thick+2, d=3);
translate([hole_pos, hole_pos, -1]) cylinder(h=thick+2, d=3);
}
}

View File

@@ -21,20 +21,20 @@
/*
NAME: fan_cover
DESCRIPTION: creates fan covers for fan openings
NAME: m_insert
DESCRIPTION: creates brass inserts for models
TODO: none
USAGE: m_insert(type="M3", icolor = "#ebdc8b")
USAGE: m_insert(type="m3", icolor = "#ebdc8b")
type = "M3"
type = "m3"
icolor = color of insert
*/
module m_insert(type="M3", icolor = "#ebdc8b") { //#f4e6c3, #ebdc8b
module m_insert(type="m3", icolor = "#ebdc8b") { //#f4e6c3, #ebdc8b
odiam = type == "M3" ? 4.2 : 3.5;
idiam = type == "M3" ? 3 : 2.5;
odiam = type == "m3" ? 4.2 : 3.5;
idiam = type == "m3" ? 3 : 2.5;
iheight = 4;
difference() {
@@ -46,3 +46,36 @@ module m_insert(type="M3", icolor = "#ebdc8b") { //#f4e6c3, #ebdc8b
cube([.5, .5, 1.5]);
}
}
/*
NAME: washer
DESCRIPTION: creates washers
TODO: none
USAGE: washer(type="round", id=3, od=6, iheight=2, sheight=2, countersunk, icolor = "#ebdc8b")
type = "round", "shouldered"
id = inside diameter
od = outside diameter
iheight = washer thickness
sheight = shoulder height
countersunk = true
icolor = color of washer
*/
module washer(type="round", id=3, od=6, iheight=2, sheight=2, countersunk = false, icolor = "#ebdc8b") { //#f4e6c3, #ebdc8b
difference() {
union() {
color(icolor,.6) cylinder(d=od, h=iheight);
if(type == "shouldered") {
color(icolor,.6) cylinder(d=od+4, h=sheight);
}
}
color(icolor,.6) translate([0,0,-1]) cylinder(d=id, h=od+sheight+2);
if(type == "shouldered" && countersunk == true) {
color(icolor,.6) translate([0,0,-.01]) cylinder(d2=id, d1=6, h=sheight);
}
}
}

109
lib/grommet.scad Normal file
View File

@@ -0,0 +1,109 @@
/*
This file is part of SBC Case Builder https://github.com/hominoids/SBC_Case_Builder
Copyright 2022,2023,2024,2025 Edward A. Kisiel hominoid@cablemi.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
Code released under GPLv3: http://www.gnu.org/licenses/gpl.html
grommet(face, style, od, id, wall, assembly, mask)
grommet_clip(style, od, id, wall)
*/
/*
NAME: grommet
DESCRIPTION: creates different groumet styles
TODO: none
USAGE: grommet(face, style, od, id, wall, assembly, mask)
data[0] = "top","bottom","front","rear","left","right"
data[1] = "sleeve"
size[0] = od outside diameter of grommet body
size[1] = id inside hole diameter of grommet body
size[2] = wall thickness of installation
data[3] = assembled true, false
mask[0] = true enables component mask
mask[1] = mask length
mask[2] = mask setback
mask[3] = mstyle "default"
*/
module grommet(face = "bottom", style = "sleeve", od, id, wall, assembly, mask) {
height = 4.5+(2*wall);
enablemask = mask[0];
mlength = height+mask[1];
msetback = mask[2];
mstyle = mask[3];
cut = .25;
lip_od = od+4;
lip_thick = 2.5;
adj = .01;
$fn = 90;
rotx = face == "rear" ? 270 : face == "front" || face == "left" || face == "right" ? 90 : face == "top" ? 180 : 0;
roty = 0;
rotz = face == "left" ? 90 : face == "right" ? 270 : 0;
rx = face == "left" ? -lip_thick : face == "right" ? lip_thick : 0;
ry = face == "front" ? lip_thick : face == "rear" ? -lip_thick : 0;
rz = face == "bottom" ? -lip_thick : face == "top" ? lip_thick : 0;
translate([rx,ry,rz]) rotate([rotx,roty,rotz]) {
if(enablemask == true && mstyle == "default") {
if(style == "sleeve") {
translate([0, 0, -adj-msetback]) cylinder(d = od+.5, h = mlength);
}
}
if(enablemask == false) {
if(style == "sleeve") {
difference() {
union() {
cylinder(d=od, h=height);
cylinder(d=lip_od, h=2.5);
}
translate([0,0,-adj]) cylinder(d=id, h=height+(2*adj));
translate([-lip_od/2,-cut/2,-adj]) cube([lip_od+(2*adj),cut,height+(2*adj)]);
translate([0,0,2.75+wall]) grommet_clip(style,od,id,wall);
}
if(assembly == true) {
translate([0,0,2.5+wall]) grommet_clip(style,od,id,wall);
}
}
}
}
}
module grommet_clip(style,od,id,wall) {
height = 2.5+wall;
lip_od = od+4;
adj = .01;
$fn = 90;
if(style == "sleeve") {
difference() {
cylinder(d=lip_od, h=2.5);
difference() {
translate([0,0,-adj]) cylinder(d=od, h=wall+2.5);
translate([-lip_od/2,-od/2,-adj]) cube([lip_od+(2*adj),2,height-2]);
translate([-lip_od/2,-2+od/2,-adj]) cube([lip_od+(2*adj),2,height-2]);
}
translate([-lip_od,-(od-6)/2,-adj]) cube([lip_od+(2*adj),od-6,wall+2.5]);
}
}
}

View File

@@ -19,10 +19,10 @@
hd25_tab(side)
hd25_vtab(side)
hd35(orientation, mask)
hdd35_25holder(length)
hd35_25holder(length,width)
hd35_tab(side)
hd35_vtab(side)
hd_bottom_holes(hd, orientation, side, thick)
hd_bottom_holes(hd, orientation, side, thick, holetype)
hd_mount(hd, orientation, position, side)
*/
@@ -366,7 +366,7 @@ module hd35(orientation, mask) {
DESCRIPTION: 3.5" hdd to 2.5" hdd holder
TODO: none
USAGE: hdd35_25holder(length, width=101.6)
USAGE: hd35_25holder(length, width=101.6)
length = length of holder min. 145mm for 3.5" drive
*/
@@ -614,21 +614,25 @@ module hd35_vtab(side) {
DESCRIPTION: creates 2.5" and 3.5" hard drive hole mask for mounting
TODO: none
USAGE: hd_bottom_holes(hd, orientation, side, thick)
USAGE: hd_holes(hd, orientation, side, thick, holetype)
hd = 2.5, 3.5
orientation = "portrait", "landscape"
side = "left", "right", "both", "bottom", "all"
thick = floor thickness
holetype = "hole", "slot"
*/
module hd_holes(hd, orientation, side, thick) {
module hd_holes(hd=3.5, orientation="portrait", side="all", thick=2, holetype="slot") {
hd25_x = 100;
hd25_y = 69.85;
hd35_x = 147;
hd35_y = 101.6;
hd35_z = 26.1;
hole_size = 3.2;
hole_len = 3 * hole_size;
slot_size = [hole_size, hole_len, thick];
adj = .01;
$fn = 90;
@@ -636,35 +640,83 @@ module hd_holes(hd, orientation, side, thick) {
if(orientation == "portrait") {
translate([0,hd25_x,0]) rotate([0,0,270]) union() {
if(side == "left" || side == "both" || side == "all") {
translate([9.4,-thick,3]) rotate([270,0,0]) cylinder(d=3.6,h=thick);
translate([86,-thick,3]) rotate([270,0,0]) cylinder(d=3.6,h=thick);
if(holetype == "hole") {
translate([9.4,-thick,3]) rotate([270,0,0]) cylinder(d=hole_size,h=thick);
translate([86,-thick,3]) rotate([270,0,0]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([9.4-(1.5*hole_size),-thick,3]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
translate([86-(1.5*hole_size),-thick,3]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
}
}
if(side == "right" || side == "both" || side == "all") {
translate([9.4,hd25_y+thick,3]) rotate([90,0,0]) cylinder(d=3.6,h=thick);
translate([86,hd25_y+thick,3]) rotate([90,0,0]) cylinder(d=3.6,h=thick);
if(holetype == "hole") {
translate([9.4,hd25_y+thick,3]) rotate([90,0,0]) cylinder(d=hole_size,h=thick);
translate([86,hd25_y+thick,3]) rotate([90,0,0]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([9.4-(1.5*hole_size),hd25_y+thick,3]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
translate([86-(1.5*hole_size),hd25_y+thick,3]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
}
}
if(side == "bottom" || side == "all") {
translate([9.4,4.07,0]) cylinder(d=3.6,h=thick);
translate([86,4.07,0]) cylinder(d=3.6,h=thick);
translate([86,65.79,0]) cylinder(d=3.6,h=thick);
translate([9.4,65.79,0]) cylinder(d=3.6,h=thick);
if(holetype == "hole") {
translate([9.4,4.07,0]) cylinder(d=hole_size,h=thick);
translate([86,4.07,0]) cylinder(d=hole_size,h=thick);
translate([86,65.79,0]) cylinder(d=hole_size,h=thick);
translate([9.4,65.79,0]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([9.4-(1.5*hole_size),4.07,0]) slot(hole_size, hole_len, thick);
translate([86-(1.5*hole_size),4.07,0]) slot(hole_size, hole_len, thick);
translate([86-(1.5*hole_size),65.79,0]) slot(hole_size, hole_len, thick);
translate([9.4-(1.5*hole_size),65.79,0]) slot(hole_size, hole_len, thick);
}
}
}
}
if(orientation == "landscape") {
if(side == "left" || side == "both" || side == "all") {
translate([9.4,-thick,3]) rotate([270,0,0]) cylinder(d=3.6,h=thick);
translate([86,-thick,3]) rotate([270,0,0]) cylinder(d=3.6,h=thick);
if(holetype == "hole") {
translate([9.4,-thick,3]) rotate([270,0,0]) cylinder(d=hole_size,h=thick);
translate([86,-thick,3]) rotate([270,0,0]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([9.4-(1.5*hole_size),-thick,3]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
translate([86-(1.5*hole_size),-thick,3]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
}
}
if(side == "right" || side == "both" || side == "all") {
translate([9.4,hd25_y+thick,3]) rotate([90,0,0]) cylinder(d=3.6,h=thick);
translate([86,hd25_y+thick,3]) rotate([90,0,0]) cylinder(d=3.6,h=thick);
if(holetype == "hole") {
translate([9.4,hd25_y+thick,3]) rotate([90,0,0]) cylinder(d=hole_size,h=thick);
translate([86,hd25_y+thick,3]) rotate([90,0,0]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([9.4-(1.5*hole_size),hd25_y+thick,3]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
translate([86-(1.5*hole_size),hd25_y+thick,3]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
}
}
if(side == "bottom" || side == "all") {
translate([9.4,4.07,-thick]) cylinder(d=3.6,h=thick);
translate([86,4.07,-thick]) cylinder(d=3.6,h=thick);
translate([86,65.79,-thick]) cylinder(d=3.6,h=thick);
translate([9.4,65.79,-thick]) cylinder(d=3.6,h=thick);
if(holetype == "hole") {
translate([9.4,4.07,-thick]) cylinder(d=hole_size,h=thick);
translate([86,4.07,-thick]) cylinder(d=hole_size,h=thick);
translate([86,65.79,-thick]) cylinder(d=hole_size,h=thick);
translate([9.4,65.79,-thick]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([9.4-(1.5*hole_size),4.07,-thick]) slot(hole_size, hole_len, thick);
translate([86-(1.5*hole_size),4.07,-thick]) slot(hole_size, hole_len, thick);
translate([86-(1.5*hole_size),65.79,-thick]) slot(hole_size, hole_len, thick);
translate([9.4-(1.5*hole_size),65.79,-thick]) slot(hole_size, hole_len, thick);
}
}
}
}
@@ -672,45 +724,103 @@ module hd_holes(hd, orientation, side, thick) {
if(orientation == "portrait") {
translate([0,hd35_x,0]) rotate([0,0,270]) union() {
if(side == "left" || side == "both" || side == "all") {
translate([16.9,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
translate([76.6,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
translate([118.5,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
if(holetype == "hole") {
translate([16.9,-thick,6.35]) rotate([270,0,0]) cylinder(d=hole_size,h=thick);
translate([76.6,-thick,6.35]) rotate([270,0,0]) cylinder(d=hole_size,h=thick);
translate([118.5,-thick,6.35]) rotate([270,0,0]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([16.9-(1.5*hole_size),-thick,6.35]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
translate([76.6-(1.5*hole_size),-thick,6.35]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
translate([118.5-(1.5*hole_size),-thick,6.35]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
}
}
if(side == "right" || side == "both" || side == "all") {
translate([118.5,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
translate([76.6,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
translate([16.9,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
if(holetype == "hole") {
translate([118.5,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=hole_size,h=thick);
translate([76.6,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=hole_size,h=thick);
translate([16.9,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([118.5-(1.5*hole_size),hd35_y+thick,6.35]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
translate([76.6-(1.5*hole_size),hd35_y+thick,6.35]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
translate([16.9-(1.5*hole_size),hd35_y+thick,6.35]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
}
}
if(side == "bottom" || side == "all") {
// landscape 3.5" bottom screw holes
translate([29.52,3.18,0]) cylinder(d=3.6,h=thick);
translate([61.27,3.18,0]) cylinder(d=3.6,h=thick);
translate([105.72,3.18,0]) cylinder(d=3.6,h=thick);
translate([29.52,98.43,0]) cylinder(d=3.6,h=thick);
translate([61.27,98.43,0]) cylinder(d=3.6,h=thick);
translate([105.72,98.43,0]) cylinder(d=3.6,h=thick);
if(holetype == "hole") {
translate([29.52,3.18,0]) cylinder(d=hole_size,h=thick);
translate([61.27,3.18,0]) cylinder(d=hole_size,h=thick);
translate([105.72,3.18,0]) cylinder(d=hole_size,h=thick);
translate([29.52,98.43,0]) cylinder(d=hole_size,h=thick);
translate([61.27,98.43,0]) cylinder(d=hole_size,h=thick);
translate([105.72,98.43,0]) cylinder(d=hole_size,h=thick);
}
if(holetype == "slot") {
translate([29.52-(1.5*hole_size),3.18,0]) slot(hole_size, hole_len, thick);
translate([61.27-(1.5*hole_size),3.18,0]) slot(hole_size, hole_len, thick);
translate([105.72-(1.5*hole_size),3.18,0]) slot(hole_size, hole_len, thick);
translate([29.52-(1.5*hole_size),98.43,0]) slot(hole_size, hole_len, thick);
translate([61.27-(1.5*hole_size),98.43,0]) slot(hole_size, hole_len, thick);
translate([105.72-(1.5*hole_size),98.43,0]) slot(hole_size, hole_len, thick);
}
}
}
}
if(orientation == "landscape") {
if(side == "left" || side == "both" || side == "all") {
translate([16.9,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
translate([76.6,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
translate([118.5,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
if(holetype == "hole") {
translate([16.9,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
translate([76.6,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
translate([118.5,-thick,6.35]) rotate([270,0,0]) cylinder(d=3,h=thick);
}
if(holetype == "slot") {
translate([16.9-(1.5*hole_size),-thick,6.35]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
translate([76.6-(1.5*hole_size),-thick,6.35]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
translate([118.5-(1.5*hole_size),-thick,6.35]) rotate([270,0,0])
slot(hole_size, hole_len, thick);
}
}
if(side == "right" || side == "both" || side == "all") {
translate([118.5,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
translate([76.6,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
translate([16.9,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
if(holetype == "hole") {
translate([118.5,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
translate([76.6,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
translate([16.9,hd35_y+thick,6.35]) rotate([90,0,0]) cylinder(d=3,h=thick);
}
if(holetype == "slot") {
translate([118.5-(1.5*hole_size),hd35_y+thick,6.35]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
translate([76.6-(1.5*hole_size),hd35_y+thick,6.35]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
translate([16.9-(1.5*hole_size),hd35_y+thick,6.35]) rotate([90,0,0])
slot(hole_size, hole_len, thick);
}
}
if(side == "bottom" || side == "all") {
// landscape 3.5" bottom screw holes
translate([29.52,3.18,-thick]) cylinder(d=3.6,h=thick);
translate([61.27,3.18,-thick]) cylinder(d=3.6,h=thick);
translate([105.72,3.18,-thick]) cylinder(d=3.6,h=thick);
translate([29.52,98.43,-thick]) cylinder(d=3.6,h=thick);
translate([61.27,98.43,-thick]) cylinder(d=3.6,h=thick);
translate([105.72,98.43,-thick]) cylinder(d=3.6,h=thick);
if(holetype == "hole") {
translate([29.52,3.18,-thick]) cylinder(d=3.6,h=thick);
translate([61.27,3.18,-thick]) cylinder(d=3.6,h=thick);
translate([105.72,3.18,-thick]) cylinder(d=3.6,h=thick);
translate([29.52,98.43,-thick]) cylinder(d=3.6,h=thick);
translate([61.27,98.43,-thick]) cylinder(d=3.6,h=thick);
translate([105.72,98.43,-thick]) cylinder(d=3.6,h=thick);
}
if(holetype == "slot") {
translate([29.52-(1.5*hole_size),3.18,-thick]) slot(hole_size, hole_len, thick);
translate([61.27-(1.5*hole_size),3.18,-thick]) slot(hole_size, hole_len, thick);
translate([105.72-(1.5*hole_size),3.18,-thick]) slot(hole_size, hole_len, thick);
translate([29.52-(1.5*hole_size),98.43,-thick]) slot(hole_size, hole_len, thick);
translate([61.27-(1.5*hole_size),98.43,-thick]) slot(hole_size, hole_len, thick);
translate([105.72-(1.5*hole_size),98.43,-thick]) slot(hole_size, hole_len, thick);
}
}
}
}

View File

@@ -29,7 +29,7 @@
USAGE: nut_holder(nut, style, dia_x, dia_y, height, mask)
nut = "m2", "m2.5", "m3", "m4"
nut = "m2", "m2.5", "m3", "m4", "m3-insert"
style = "default", "sloped", "trap"
dia_x = top diameter or x size in mm
dia_y = bottom diameter or y size in mm
@@ -87,6 +87,10 @@ module nut_holder(nut, style, dia_x, dia_y, height, mask) {
translate([0, 0, -1]) cylinder(d=nuts[2][0]+.5, h=height+2);
translate([0, 0, 2]) cylinder(d=nuts[2][1]*2/sqrt(3), h=height, $fn=6);
}
if(nut == "m3-insert") {
translate([0, 0, -1]) cylinder(d=nuts[2][0]+.5, h=height+2);
translate([0, 0, 0]) cylinder(d=4.2, h=5.1);
}
if(nut == "m4") {
translate([0, 0, -1]) cylinder(d=nuts[3][0]+.5, h=height+2);
translate([0, 0, 2]) cylinder(d=nuts[3][1]*2/sqrt(3), h=height, $fn=6);
@@ -106,7 +110,11 @@ module nut_holder(nut, style, dia_x, dia_y, height, mask) {
}
if(nut == "m3") {
translate([0, 0, -1]) cylinder(d=nuts[2][0]+.5, h=height+2);
translate([0, 0, 2]) cylinder(d=nuts[2][1]*2/sqrt(3), h=height, $fn=6);
translate([0, 0, 0]) cylinder(d=nuts[2][1]*2/sqrt(3), h=height+5, $fn=6);
}
if(nut == "m3-insert") {
translate([0, 0, -1]) cylinder(d=nuts[2][0]+.5, h=height+2);
translate([0, 0, 0]) cylinder(d=4.2, h=5.1);
}
if(nut == "m4") {
translate([0, 0, -1]) cylinder(d=nuts[3][0]+.5, h=height+2);

View File

@@ -15,17 +15,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>
Code released under GPLv3: http://www.gnu.org/licenses/gpl.html
adafruit_lcd(mask)
adafruit_2030_powerboost(mask)
adafruit_4311_lcd(mask)
adafruit_4755_solar_charger(mask)
*/
/*
NAME: adafruit_lcd
DESCRIPTION: adafruit 4311 2in TFT IPS Display model
NAME: adafruit_2030_powerboost
DESCRIPTION: adafruit 2030 Powerboost 1000 Basic
TODO: none
USAGE: adafruit_lcd(mask[])
USAGE: adafruit_2030_powerboost(mask[])
mask[0] = true enables mask
mask[1] = mask length
@@ -34,7 +36,65 @@
*/
module adafruit_lcd(mask) {
module adafruit_2030_powerboost(mask) {
size_x = 29.21;
size_y = 22.86;
size_z = 1.6;
lcd_size = [34.75,48,2];
corner_radius = 2;
hole_size = 2.54;
enablemask = mask[0];
mlen = mask[1];
back = mask[2];
mstyle = mask[3];
adj = .01;
$fn = 90;
if(enablemask == true && mstyle == "default") {
jst("ph",0,8.5,0,"top",90,[2,0,0],["thruhole","side","white"], size_z, enablemask, [true,10,2,"default"]);
usb2("single_horizontal_a",23,4.5,0,"top",270,[0,13,0],[0], size_z, enablemask, [true,12,7,"default"]);
}
if(enablemask == false) {
difference() {
color("#252525") slab([size_x, size_y, size_z], corner_radius);
color("#252525") translate([hole_size, size_y-hole_size, -adj]) cylinder(d=hole_size,h=6);
color("#252525") translate([hole_size, hole_size, -adj]) cylinder(d=hole_size, h=4);
for(i=[6:2.54:20]) {
color("#fee5a6",1) translate([i, 21.5, -adj]) cylinder(d=.8, h=6);
}
}
pcbpad("round", 6, 21.5, 0, "top", 0, [6, 1, 0], [.8, "#fee5a6", 1.2], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", hole_size, size_y-hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", hole_size, hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
ic("generic", 12.5, 11, 0, "top", 0, [9, 9, 2], ["dimgrey"], size_z, enablemask, [false, 20, 0, "default"]);
ic("generic", 13.5, 5, 0, "top", 0, [4, 4, .8], ["dimgrey"], size_z, enablemask, [false, 20, 0, "default"]);
jst("ph",0,8.5,0,"top",90,[2,0,0],["thruhole","side","white"], size_z, enablemask, [true,10,2,"default"]);
usb2("single_horizontal_a",23,4.5,0,"top",270,[0,13,0],[0], size_z, enablemask, [true,10,2,"default"]);
}
}
/*
NAME: adafruit_lcd
DESCRIPTION: adafruit 4311 2in TFT IPS Display model
TODO: none
USAGE: adafruit_4311_lcd(mask[])
mask[0] = true enables mask
mask[1] = mask length
mask[2] = mask setback
mask[3] = mstyle "default"
*/
module adafruit_4311_lcd(mask) {
size_x = 35.5;
size_y = 59;
@@ -83,4 +143,72 @@ module adafruit_lcd(mask) {
pcbpad("round", size_x-hole_size, size_y-hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
}
}
}
/*
NAME: adafruit_4755_solar_charger
DESCRIPTION: adafruit 4755 Universal USB/DC/Solar Lithium Ion/Polymer charger - bq24074
TODO: none
USAGE: adafruit_4755_solar_charger(mask[])
mask[0] = true enables mask
mask[1] = mask length
mask[2] = mask setback
mask[3] = mstyle "default"
*/
module adafruit_4755_solar_charger(mask) {
size_x = 38.1;
size_y = 33.02;
size_z = 1.6;
lcd_size = [34.75,48,2];
corner_radius = 2;
hole_size = 2.54;
enablemask = mask[0];
mlen = mask[1];
back = mask[2];
mstyle = mask[3];
adj = .01;
$fn = 90;
if(enablemask == true && mstyle == "default") {
jst("ph",33.5,8,0,"top",270,[2,0,0],["thruhole","side","white"], size_z, enablemask, [true,10,2,"default"]);
jst("ph",33.5,19,0,"top",270,[2,0,0],["thruhole","side","white"], size_z, enablemask, [true,10,2,"default"]);
usbc("single_horizontal",-1,5.5,0,"top",90,[0,13,0],[0], size_z, enablemask, [true,10,2,"default"]);
power("pj-202ah",-2,17.5,0,"top",90,[0,13,0],[0], size_z, enablemask, [true,10,2,"default"]);
}
if(enablemask == false) {
difference() {
color("#252525") slab([size_x, size_y, size_z], corner_radius);
color("#252525") translate([hole_size, size_y-hole_size, -adj]) cylinder(d=hole_size,h=6);
color("#252525") translate([hole_size, hole_size, -adj]) cylinder(d=hole_size, h=4);
color("#252525") translate([size_x-hole_size, size_y-hole_size, -adj]) cylinder(d=hole_size,h=6);
color("#252525") translate([size_x-hole_size, hole_size, -adj]) cylinder(d=hole_size, h=4);
for(i=[6.5:2.54:25]) {
color("#fee5a6",1) translate([i, 2.5, -adj]) cylinder(d=.8, h=6);
}
}
pcbpad("round", 6.5, 2.5, 0, "top", 0, [11, 1, 0], [.8, "#fee5a6", 1.2], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", hole_size, size_y-hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", hole_size, hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", size_x-hole_size, size_y-hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", size_x-hole_size, hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
ic("generic", 17.5, 15, 0, "top", 0, [4, 4, .8], ["dimgrey"], size_z, enablemask, [false, 20, 0, "default"]);
jst("ph",33.5,8,0,"top",270,[2,0,0],["thruhole","side","white"], size_z, enablemask, [true,10,2,"default"]);
jst("ph",33.5,19,0,"top",270,[2,0,0],["thruhole","side","white"], size_z, enablemask, [true,10,2,"default"]);
usbc("single_horizontal",-1,5.5,0,"top",90,[0,13,0],[0], size_z, enablemask, [true,10,2,"default"]);
power("pj-202ah",-2,17.5,0,"top",90,[0,13,0],[0], size_z, enablemask, [true,10,2,"default"]);
}
}

86
lib/oem_rpi.scad Normal file
View File

@@ -0,0 +1,86 @@
/*
This file is part of SBC Case Builder https://github.com/hominoids/SBC_Case_Builder
Copyright 2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
Code released under GPLv3: http://www.gnu.org/licenses/gpl.html
rpi_m2hat(mask)
*/
/*
NAME: rpi_m2hat
DESCRIPTION: Raspberry Pi M.2 HAT+ M Key model
TODO: none
USAGE: rpim2-hat(mask[])
mask[0] = true enables mask
mask[1] = mask length
mask[2] = mask setback
mask[3] = mstyle "default"
*/
module rpi_m2hat(mask) {
size_x = 65;
size_y = 56.5;
size_z = 1.6;
corner_radius = 3.5;
hole_size = 3.5;
enablemask = mask[0];
mlen = mask[1];
back = mask[2];
mstyle = mask[3];
adj = .01;
$fn = 90;
if(enablemask == true && mstyle == "default") {
translate([6, 49, 0]) slab([52.8, 7, mlen],1);
}
if(enablemask == false) {
difference() {
color("#008066") slab([size_x, size_y, size_z], corner_radius);
color("#008066") translate([hole_size, size_y-hole_size, -adj]) cylinder(d=hole_size,h=6);
color("#008066") translate([size_x-hole_size, size_y-hole_size, -adj]) cylinder(d=hole_size, h=4);
color("#008066") translate([hole_size, hole_size, -adj]) cylinder(d=hole_size,h=6);
color("#008066") translate([size_x-hole_size, hole_size, -adj]) cylinder(d=hole_size, h=4);
color("#008066") translate([-3, 21, -adj]) slab([8,18,6],2);
color("#008066") translate([47.5, -2, -adj]) slab([10,18,6],2);
}
header("open",7,50,0,"top",0,[20,2,4],["smt","black","female",2.54,"#fee5a6"], size_z, enablemask, [false,10,-2,"none"]);
fpc("fh19", 6.5, 25, 0, "top", 90, [16,0,0], ["smt","side","grey","white"], size_z, enablemask, [true,10,2,"default"]);
storage("m.2_header",15,17,0,"top",270,[0,0,0],[0], size_z, enablemask, [true,10,2,"default"]);
pcbpad("round", hole_size, size_y-hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", size_x-hole_size, size_y-hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", hole_size, hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
pcbpad("round", size_x-hole_size, hole_size, 0, "top", 0, [1, 1, 0],
[hole_size, "#fee5a6", hole_size+1], size_z, enablemask, [false, 20, 0, "default"]);
// pillar("hex", hole_size-4, size_y-hole_size, 0, "bottom", 0, [4, 3, 16],
// [0, "#fee5a6"], size_z, enablemask, [false, 20, 0, "default"]);
// pillar("hex", size_x-hole_size-4, size_y-hole_size, 0, "bottom", 0, [4, 3, 16],
// [0, "#fee5a6"], size_z, enablemask, [false, 20, 0, "default"]);
// pillar("hex", hole_size-4, hole_size, 0, "bottom", 0, [4, 3, 16],
// [0, "#fee5a6"], size_z, enablemask, [false, 20, 0, "default"]);
// pillar("hex", size_x-hole_size-4, hole_size, 0, "bottom", 0, [4, 3, 16],
// [0, "#fee5a6"], size_z, enablemask, [false, 20, 0, "default"]);
}
}

118
lib/panel_clamp.scad Normal file
View File

@@ -0,0 +1,118 @@
/*
NAME: panel_clamp
DESCRIPTION: creates various clamps to join two panels
TODO: none
USAGE: panel_clamp(face, style, screw, dia_x, dia_y, height, mask)
data[0] = "top","bottom","rear","front","left","right"
data[1] = "sloped"
data[2] = "m2", "m2.5", "m3", "m4"
size_x = top diameter or x size in mm
size_y = bottom diameter or y size in mm
size_z = clamp height in mm
mask[0] = true enables component mask
mask[1] = mask length
mask[2] = mask setback
mask[3] = mstyle "default", "holes"
*/
module panel_clamp(face, style, screw, dia_x, dia_y, height, mask) {
nuts = [[2,4,1.6], // m2 size, diameter, height
[2.5,5,2], // m2.5 size, diameter, height
[3,5.5,2.4], // m3 size, diameter, height
[4,7,3.2]]; // m4 size, diameter, height
enablemask = mask[0];
mlength = mask[1];
msetback = mask[2];
mstyle = mask[3];
adj = .01;
$fn = 90;
rotx = face == "rear" ? 270 : face == "front" || face == "left" || face == "right" ? 90 : face == "top" ? 180 : 0;
roty = 0;
rotz = face == "left" ? 90 : face == "right" ? 270 : 0;
if(enablemask == true) {
rotate([rotx,roty,rotz]) {
if(mstyle == "default") {
cylinder(d=dia_y, h=height);
}
if(screw == "m2" && mstyle == "holes") {
translate([(-dia_y-(nuts[2][0]+.5)/2)/2, 0, 2.25]) rotate([0,90,0])
cylinder(d=nuts[0][0]+.5, h=dia_y+2);
translate([-(dia_y/2), 0, 2.25]) rotate([0,90,0])
cylinder(d=nuts[0][1]*2/sqrt(3), h=dia_y*.375, $fn=6);
translate([nuts[0][0]+.5, 0, 2.25]) rotate([0,90,0])
cylinder(d=nuts[0][1]+.5, h=dia_y*.375);
}
if(screw == "m2.5" && mstyle == "holes") {
translate([(-dia_y-(nuts[2][0]+.5)/2)/2, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[1][0]+.5, h=dia_y+2);
translate([-(dia_y/2), 0, 3]) rotate([0,90,0])
cylinder(d=nuts[1][1]*2/sqrt(3), h=dia_y*.375, $fn=6);
translate([nuts[1][0]+.5, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[1][1]+.5, h=dia_y*.375);
}
if(screw == "m3" && mstyle == "holes") {
translate([(-dia_y-(nuts[2][0]+.5)/2)/2, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[2][0]+.5, h=dia_y+2);
translate([-(dia_y/2), 0, 3]) rotate([0,90,0])
cylinder(d=nuts[2][1]*2/sqrt(3), h=dia_y*.375, $fn=6);
translate([nuts[2][0]+.5, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[2][1]+.5, h=dia_y*.375);
}
if(screw == "m4" && mstyle == "holes") {
translate([(-dia_y-(nuts[2][0]+.5)/2)/2, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[3][0]+.5, h=dia_y+2);
translate([-(dia_y/2), 0, 3]) rotate([0,90,0])
cylinder(d=nuts[3][1]*2/sqrt(3), h=dia_y*.375, $fn=6);
translate([nuts[3][0]+.5, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[3][1]+.5, h=dia_y*.375);
}
}
}
if(enablemask == false) {
rotate([rotx,roty,rotz]) {
difference() {
cylinder(d2=dia_x, d1=dia_y, h=height);
if(screw == "m2") {
translate([(-dia_y-(nuts[2][0]+.5)/2)/2, 0, 2.25]) rotate([0,90,0])
cylinder(d=nuts[0][0]+.5, h=dia_y+2);
translate([-(dia_y/2), 0, 2.25]) rotate([0,90,0])
cylinder(d=nuts[0][1]*2/sqrt(3), h=dia_y*.375, $fn=6);
translate([nuts[0][0]+.5, 0, 2.25]) rotate([0,90,0])
cylinder(d=nuts[0][1]+.5, h=dia_y*.375);
}
if(screw == "m2.5") {
translate([(-dia_y-(nuts[2][0]+.5)/2)/2, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[1][0]+.5, h=dia_y+2);
translate([-(dia_y/2), 0, 3]) rotate([0,90,0])
cylinder(d=nuts[1][1]*2/sqrt(3), h=dia_y*.375, $fn=6);
translate([nuts[1][0]+.5, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[1][1]+.5, h=dia_y*.375);
}
if(screw == "m3") {
translate([(-dia_y-(nuts[2][0]+.5)/2)/2, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[2][0]+.5, h=dia_y+2);
translate([-(dia_y/2), 0, 3]) rotate([0,90,0])
cylinder(d=nuts[2][1]*2/sqrt(3), h=dia_y*.375, $fn=6);
translate([nuts[2][0]+.5, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[2][1]+.5, h=dia_y*.375);
}
if(screw == "m4") {
translate([(-dia_y-(nuts[2][0]+.5)/2)/2, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[3][0]+.5, h=dia_y+2);
translate([-(dia_y/2), 0, 3]) rotate([0,90,0])
cylinder(d=nuts[3][1]*2/sqrt(3), h=dia_y*.375, $fn=6);
translate([nuts[3][0]+.5, 0, 3]) rotate([0,90,0])
cylinder(d=nuts[3][1]+.5, h=dia_y*.375);
}
}
}
}
}

205
lib/rack.scad Normal file
View File

@@ -0,0 +1,205 @@
/*
This file is part of SBC Case Builder https://github.com/hominoids/SBC_Case_Builder
Copyright 2022,2023,2024,2025 Edward A. Kisiel hominoid@cablemi.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
Code released under GPLv3: http://www.gnu.org/licenses/gpl.html
rack_end_bracket(side, size, thick)
rack_rail(style, rack_1u, hole_dia, thick)
rack_stand(rack_1u)
*/
/*
NAME: rack_end_bracket
DESCRIPTION: creates rack mounting ears
TODO: none
USAGE: rack_end_bracket(side, size, thick)
side = "left", "right"
size = "1u", "2u", "3u", "4u"
thick = thickness of bracket
*/
module rack_end_bracket(side, size, thick) {
u1 = 44.45;
depth = size == "1u" ? 44.45 : size == "1u+" ? 59.26 : size == "1u++" ? 74.07 : size == "2u" ? 2*44.45 : size == "3u" ? 3*44.45 : 4*44.45;
mask = size == "1u" ? 44.45 : size == "1u+" ? 88.9 : size == "1u++" ? 88.9 : size == "2u" ? 2*44.45 : size == "3u" ? 3*44.45 : 4*44.45;
c_fillet = 2;
hole = 3.2;
rack_hole = 6;
tab_width = 15.875+thick;
b_width = thick;
b_depth = depth;
b_height = thick;
b_loc = [-thick,0,0];
adjust = .01;
$fn=90;
if(side == "left") {
translate([thick,0,0]) rotate([90,0,0])
difference() {
union() {
translate([(-tab_width/2),(depth/2),thick/2])
cube_fillet_inside([tab_width,depth,thick],
vertical=[0,c_fillet,c_fillet,0],top=[0,0,0,0],bottom=[0,0,0,0], $fn=90);
translate([(b_width/2)+b_loc[0],(b_depth/2)+b_loc[1],(b_height/2)+b_loc[2]])
cube_fillet_inside([b_width,b_depth,b_height],
vertical=[0,0,0,0],top=[c_fillet,0,c_fillet,0],bottom=[0,0,0,0], $fn=90);
}
for(i=[0:u1:mask-u1]) {
for(c=[6.35:15.875:44.45]) {
translate([(3-thick)-9-(15.875-9)/2,c+i,-adjust])
slot(rack_hole,3,thick+(adjust*2));
}
}
}
}
if(side == "right") {
translate([-thick,-thick,0]) rotate([270,180,0])
difference() {
union() {
translate([(-tab_width/2),(depth/2),thick/2])
cube_fillet_inside([tab_width,depth,thick],
vertical=[0,c_fillet,c_fillet,0],top=[0,0,0,0],bottom=[0,0,0,0], $fn=90);
translate([(b_width/2)+b_loc[0],(b_depth/2)+b_loc[1],(b_height/2)+b_loc[2]])
cube_fillet_inside([b_width,b_depth,b_height],
vertical=[0,0,0,0],top=[c_fillet,0,c_fillet,0],bottom=[0,0,0,0], $fn=90);
}
for(i=[0:u1:mask-u1]) {
for(c=[6.35:15.875:44.45]) {
translate([(3-thick)-9-(15.875-9)/2,c+i,-adjust]) slot(rack_hole,3,thick+(adjust*2));
}
}
}
}
}
/*
NAME: rack_rail
DESCRIPTION: creates rack rail lengths
TODO: none
USAGE: rack_rail(style, rack_1u, hole_dia, thick)
style = "none", "nut", "insert"
rack_1u = number of 1u
hole_dia = hole size to create
thick = thickness of bracket
*/
module rack_rail(style, rack_1u, hole_dia, thick) {
1u = 44.45;
mount_rail = 15.875;
1u_hole_offset = 6.35;
1u_hole_spacing = 15.875;
height = rack_1u * 1u;
difference() {
union() {
cube([mount_rail, thick, height]);
if(style == "nut" || style == "insert") {
fastner = style == "insert" ? "m3-insert" : "m3";
for(i=[0:rack_1u-1]) {
translate([mount_rail/2, adj, i*1u]) {
translate([0,0,1u_hole_offset]) rotate([90,0,0])
nut_holder(fastner, "sloped", 7, mount_rail-1, 3, [false,10,2,"default"]);
translate([0,0,1u_hole_offset+1u_hole_spacing])
rotate([90,0,0]) nut_holder(fastner, "sloped", 7, mount_rail-1, 3, [false,10,2,"default"]);
translate([0,0,1u_hole_offset+2*1u_hole_spacing])
rotate([90,0,0]) nut_holder(fastner, "sloped", 7, mount_rail-1, 3, [false,10,2,"default"]);
}
}
}
}
for(i=[0:rack_1u-1]) {
translate([mount_rail/2, -1, i*1u]) {
translate([0,thick+2,1u_hole_offset]) rotate([90,0,0]) cylinder(d = hole_dia, h=thick+2);
translate([0,thick+2,1u_hole_offset+1u_hole_spacing]) rotate([90,0,0]) cylinder(d = hole_dia, h=thick+2);
translate([0,thick+2,1u_hole_offset+2*1u_hole_spacing]) rotate([90,0,0]) cylinder(d = hole_dia, h=thick+2);
}
}
translate([-1,-1,height]) cube([mount_rail+2,thick+2,10]);
}
}
/*
NAME: rack_stand
DESCRIPTION: creates rack stand of 1u hieght
TODO: none
USAGE: rack_stand(rack_1u)
rack_1u = number of 1u
*/
module rack_stand(rack_1u) {
1u = 44.45;
mount_rail = 15.875;
thick = 5;
height = rack_1u * 1u;
height_offset = 25.4/2;
hole_dia = 3.2;
c_fillet = 9;
rail_offset = 87.5;
foot_length = 175;
foot_thick = 4;
$fn=180;
// vertical rack rails
translate([0, 0, height_offset-adj]) rack_rail(rack_fasteners, rack_1u, hole_dia, thick);
// bottom feet
translate([mount_rail/2, -rail_offset/2, foot_thick-2]) cube_fillet_inside([mount_rail, foot_length, foot_thick],
vertical=[0,0,0,0], top=[c_fillet,0,c_fillet,0], bottom=[0,0,0,0], $fn=90);
// bottom connection piece
translate([0, 0, 0]) cube([mount_rail, thick, height_offset]);
// top extension piece
ext_len = rack_1u == 4 ? thick : rack_1u == 3 ? thick : thick;
translate([0, 0, height+height_offset-adj]) cube([mount_rail, thick, ext_len]);
// support arc
if(rack_1u > 0) {
ext_adj = rack_1u == 4 ? 4.5*thick : rack_1u == 3 ? 3.5*thick : 2.5*thick;
difference() {
translate([0,(height/2)-5*thick,ext_adj]) rotate([0,90,0]) {
difference() {
translate([0,0,0]) cylinder(d=(2*height)+(3*thick), h=mount_rail);
translate([0,0,-adj]) cylinder(d=(2*height)+thick+4, h=mount_rail+(2*adj));
}
}
// top trim
translate([-1, thick, height+height_offset-5]) cube([mount_rail+2, 300, 40]);
// front trim
translate([-1, 42.75, -175]) cube([mount_rail+2, 300, 400]);
translate([-1, thick, foot_thick]) cube([mount_rail+2, 300, 400]);
// bottom trim
translate([-1, -150, -174.5]) cube([mount_rail+2, 300, 175]);
}
}
}

View File

@@ -76,7 +76,7 @@ module standoff(stand_off, mask){
mstyle = mask[3];
ps = size == "m2_tap" || size == "m2" || size == "m2+" ? 4 :
size == "m2.5_tap" || size == "m2.5" || size == "m2.5+" ? 5 :
size == "m2.5_tap" || size == "m2.5" || size == "m2.5+" ? 5.375 :
size == "m3_tap" || size == "m3" || size == "m3+" ? 6.72 :
size == "m4_tap" || size == "m4" || size == "m4+" ? 8.96 : (2*holesize)+.5;
ds = size == "m2_tap" || size == "m2" || size == "m2+" ? 1.2 :

View File

@@ -82,6 +82,9 @@ module add(type, loc_x, loc_y, loc_z, face, rotation, size, data, mask) {
if(type == "feet") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) feet(size_x, size_z);
}
if(type == "grommet") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) grommet(data[0], data[1], size_x, size_y, size_z, data[2], mask);
}
if(type == "hd_holder") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) hd_mount(data[0],data[1],data[2],data[3]);
}
@@ -112,6 +115,9 @@ module add(type, loc_x, loc_y, loc_z, face, rotation, size, data, mask) {
if(type == "nut_holder") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) nut_holder(data[0], data[1], size_x, size_y, size_z, mask);
}
if(type == "panel_clamp") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) panel_clamp(data[0], data[1], data[2], size_x, size_y, size_z, mask);
}
if(type == "pcb_holder") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) pcb_holder([size_x,size_y,size_z],data[0]);
}
@@ -139,8 +145,14 @@ module add(type, loc_x, loc_y, loc_z, face, rotation, size, data, mask) {
}
// models
if(type == "adafruit_lcd") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) adafruit_lcd(mask);
if(type == "adafruit_2030_powerboost") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) adafruit_2030_powerboost(mask);
}
if(type == "adafruit_4311_lcd") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) adafruit_4311_lcd(mask);
}
if(type == "adafruit_4755_solar_charger") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) adafruit_4755_solar_charger(mask);
}
if(type == "dsub") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) dsub(data[0], data[1], mask);
@@ -202,6 +214,12 @@ module add(type, loc_x, loc_y, loc_z, face, rotation, size, data, mask) {
if(type == "hk_xu4_shifter_shield") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) hk_xu4_shifter_shield(mask);
}
if(type == "pillar") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) pillar(data[0], 0, 0, 0, data[2], 0, size, data, 0, false, mask);
}
if(type == "rpi_m2hat") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) rpi_m2hat(mask);
}
if(type == "stl_model") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) stl_model(data[0],data[1]);
}

View File

@@ -97,14 +97,14 @@ mb_adapters=[
}
}
}
// adapter standoff holes
// adapter holes
for (i=[2:len(mb_adapters[mb[0]])-3:len(mb_adapters[mb[0]])-3]) {
for (c=[1:1:len(mb_adapters[mb[0]])-3]) {
mbhole_pos = mb_adapters[mb[0]][i+c][0];
mbhole_x = mb_adapters[mb[0]][i+c][1]+mba_offset_x;
mbhole_y = mb_adapters[mb[0]][i+c][2]+mba_offset_y;
mbhole_z = -floorthick;
translate([mbhole_x,mbhole_y,-1]) cylinder(d=6.5, h=mba_z+2);
translate([mbhole_x,mbhole_y,-1]) cylinder(d=4, h=mba_z+2);
}
}

View File

@@ -44,7 +44,7 @@ module case_bottom(case_design) {
translate([(width/2)-wallthick-gap,
(depth/2)-wallthick-gap,(bottom_height/2)+floorthick])
cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),bottom_height],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick],
top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
}
}
@@ -62,6 +62,22 @@ module case_bottom(case_design) {
cube([8,wallthick+2*adj,floorthick]);
}
}
if(case_design == "panel_nas") {
x_adj = pcb_width > 100 ? width-2*sidethick : 101.6+case_offset_x;
xtab_adj = pcb_width > 100 ? width-gap-2*sidethick-adj : 101.6-gap+case_offset_x-adj;
union() {
translate([-gap,-wallthick,0])
cube([x_adj,depth-(2*wallthick),floorthick]);
translate([-gap-sidethick-(2*adj),depth-(3*wallthick)-gap-adj-20,0])
cube([sidethick+(2*adj),10,floorthick]);
translate([xtab_adj,depth-(3*wallthick)-gap-adj-20,0])
cube([sidethick+2*adj,10,floorthick]);
translate([-gap-sidethick-(2*adj),40-wallthick-gap+adj,0])
cube([sidethick+2*adj,10,floorthick]);
translate([xtab_adj,40-wallthick-gap+adj,0])
cube([sidethick+2*adj,10,floorthick]);
}
}
if(case_design == "stacked") {
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,floorthick/2])
cube_fillet_inside([width-(2*wallthick),depth-(2*wallthick),floorthick],
@@ -76,7 +92,7 @@ module case_bottom(case_design) {
bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,(bottom_height/2)+floorthick])
cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),bottom_height+adj],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick],
top=[0,0,0,0],bottom=[2,2,2,2], $fn=90);
}
// case nut placement
@@ -91,7 +107,8 @@ module case_bottom(case_design) {
pcbhole_pos = sbc_data[s[0]][i+10][4];
if(class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_rear") {
if((pcbhole_y <= 10 && pcbhole_x <= 10) || (ext_bottom_standoffs == true && ext_bottom_rear_left_enable == true)) {
if((pcbhole_y <= 10 && pcbhole_x <= 10) ||
(ext_bottom_standoffs == true && ext_bottom_rear_left_enable == true)) {
translate([-adj-gap,wallthick+gap+10,floorthick+3.4]) rotate([90,0,90])
cylinder(d=10, h=4, $fn=6);
}
@@ -101,7 +118,8 @@ module case_bottom(case_design) {
}
}
if(class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_front") {
if((pcbhole_y >= pcb_depth+case_offset_y-10 && pcbhole_x <= 10) || (ext_bottom_standoffs == true && ext_bottom_front_left_enable == true)) {
if((pcbhole_y >= pcb_depth+case_offset_y-10 && pcbhole_x <= 10) ||
(ext_bottom_standoffs == true && ext_bottom_front_left_enable == true)) {
translate([-adj-gap,wallthick-gap+pcb_depth+case_offset_y-14,floorthick+3.4])
rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
}
@@ -111,7 +129,8 @@ module case_bottom(case_design) {
}
}
if(class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_rear") {
if((pcbhole_y <= 10 && pcbhole_x >= pcb_width-10) || (ext_bottom_standoffs == true && ext_bottom_rear_right_enable == true)) {
if((pcbhole_y <= 10 && pcbhole_x >= pcb_width-10) || (ext_bottom_standoffs == true &&
ext_bottom_rear_right_enable == true)) {
translate([width-wallthick-gap-wallthick-4+adj,wallthick+gap+10,floorthick+3.4])
rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
}
@@ -121,13 +140,16 @@ module case_bottom(case_design) {
}
}
if(class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_front") {
if((pcbhole_y >= pcb_depth+case_offset_y-10 && pcbhole_x >= width-10) || (ext_bottom_standoffs == true && ext_bottom_front_right_enable == true)) {
translate([width-wallthick-gap-wallthick-4+adj,wallthick-gap+pcb_depth+case_offset_y-14,floorthick+3.4])
rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
if((pcbhole_y >= pcb_depth+case_offset_y-10 && pcbhole_x >= width-10) ||
(ext_bottom_standoffs == true && ext_bottom_front_right_enable == true)) {
translate([width-wallthick-gap-wallthick-4+adj,
wallthick-gap+pcb_depth+case_offset_y-14,floorthick+3.4])
rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
}
else {
translate([width-wallthick-gap-wallthick-4+adj,wallthick+gap+pcb_depth+case_offset_y-8,floorthick+3.4])
rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
translate([width-wallthick-gap-wallthick-4+adj,
wallthick+gap+pcb_depth+case_offset_y-8,floorthick+3.4])
rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
}
}
}
@@ -135,11 +157,11 @@ module case_bottom(case_design) {
// front panel
if(case_design == "tray_vu5" || case_design == "tray_vu7" || case_design == "tray_sides") {
translate([-wallthick-gap,depth-(2*wallthick)-gap,bottom_height-adj])
rotate([0,0,0]) cube([width,wallthick,top_height]);
cube([width,wallthick,top_height]);
}
else {
translate([-wallthick-gap,depth-(2*wallthick)-gap,bottom_height-adj])
rotate([0,0,0]) cube([width,wallthick,top_height-floorthick]);
cube([width,wallthick,top_height-floorthick]);
}
// rear panel
@@ -214,21 +236,21 @@ module case_bottom(case_design) {
}
else {
difference() {
translate([pcb_width/2,pcb_depth/2,bottom_height/2]) rotate([0,0,0])
translate([pcb_width/2,pcb_depth/2,bottom_height/2])
cylinder_fillet_inside(h=bottom_height, r=hex_diameter/2,
top=0, bottom=edge_fillet, $fn=6, fillet_fn=case_ffn, center=true);
translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+floorthick]) rotate([0,0,0])
translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+floorthick])
cylinder_fillet_inside(h=bottom_height+adj,r=(hex_diameter/2)-lip/2,top=0,
bottom=edge_fillet-1,$fn=6,fillet_fn=case_ffn, center=true);
difference() {
translate([pcb_width/2,pcb_depth/2,bottom_height-lip]) rotate([0,0,0])
translate([pcb_width/2,pcb_depth/2,bottom_height-lip])
cylinder(h=lip+adj,r=(hex_diameter/2)+1, $fn=6);
translate([pcb_width/2,pcb_depth/2,bottom_height-lip]) rotate([0,0,0])
translate([pcb_width/2,pcb_depth/2,bottom_height-lip])
cylinder(h=lip+2*adj,r=(hex_diameter/2)-lip/4, $fn=6);
}
}
difference() {
translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+2*floorthick]) rotate([0,0,0])
translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+2*floorthick])
cylinder_fillet_inside(h=bottom_height+adj+floorthick+lip,
r=(hex_diameter/2)-lip/2,top=0, bottom=edge_fillet-1, $fn=6,
fillet_fn=case_ffn, center=true);
@@ -247,7 +269,7 @@ module case_bottom(case_design) {
top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,floorthick+(floorthick+case_z)/2])
cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),case_z+floorthick],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick],
top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
// snap top indent
translate([-gap-wallthick+.75,(depth/2)-(depth*.75)/2-gap-wallthick,case_z-.5])
@@ -265,7 +287,7 @@ module case_bottom(case_design) {
translate([(width/2)-wallthick-gap,
(depth/2)-wallthick-gap,(case_z/2)+floorthick])
cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),case_z],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick],
top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
difference() {
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,case_z-lip/2])
@@ -275,7 +297,7 @@ module case_bottom(case_design) {
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,case_z-lip/2])
cube_fillet_inside([width-wallthick,depth-wallthick,lip+adj],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],top=[0,0,0,0],
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick],top=[0,0,0,0],
bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
}
}
@@ -384,77 +406,191 @@ echo(pcb_depth+case_offset_y-10);
pcbhole_size = sbc_data[s[0]][i+9][0];
pcbhole_pos = sbc_data[s[0]][i+10][4];
if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_rear" &&
if (class == "pcbhole" && id == 0 && pcbhole_pos == "left_rear" &&
bottom_rear_left_enable == true && bottom_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,-1]) cylinder(d=bottom_standoff[4]-.2, h=bottom_height);
ahpx = sbc_model == "n2" ? 7 : sbc_model == "n2+" ? 9.25 :
sbc_model == "m1" ? 9.25 : pcbhole_x;
ahpy = sbc_model == "n2" ? 15 : sbc_model == "n2+" ? 9.25 :
sbc_model == "m1" ? 9.25 : pcbhole_y;
translate([ahpx,ahpy,-adj])
cylinder(d=bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_front" &&
if (class == "pcbhole" && id == 0 && pcbhole_pos == "left_front" &&
bottom_front_left_enable == true && bottom_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,-1]) cylinder(d=bottom_standoff[4]-.2, h=bottom_height);
ahpx = sbc_model == "n2" ? 8 : sbc_model == "n2+" ? 9.25 :
sbc_model == "m1" ? 9.25 : pcbhole_x;
ahpy = sbc_model == "n2" ? 75 : sbc_model == "n2+" ? 80.75 :
sbc_model == "m1" ? 112.75 : pcbhole_y;
translate([ahpx,ahpy,-adj])
cylinder(d=bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_rear" &&
if (class == "pcbhole" && id == 0 && pcbhole_pos == "right_rear" &&
bottom_rear_right_enable == true && bottom_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,-1]) cylinder(d=bottom_standoff[4]-.2, h=bottom_height);
ahpx = sbc_model == "n2" ? 82 : sbc_model == "n2+" ? 80.75 :
sbc_model == "m1" ? 80.75 : pcbhole_x;
ahpy = sbc_model == "n2" ? 6 : sbc_model == "n2+" ? 9.25 :
sbc_model == "m1" ? 9.25 : pcbhole_y;
translate([ahpx,ahpy,-adj])
cylinder(d=bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_front" &&
if (class == "pcbhole" && id == 0 && pcbhole_pos == "right_front" &&
bottom_front_right_enable == true && bottom_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,-1]) cylinder(d=bottom_standoff[4]-.2, h=bottom_height);
ahpx = sbc_model == "n2" ? 82 : sbc_model == "n2+" ? 80.75 :
sbc_model == "m1" ? 80.75 : pcbhole_x;
ahpy = sbc_model == "n2" ? 75 : sbc_model == "n2+" ? 80.75 :
sbc_model == "m1" ? 112.75 : pcbhole_y;
translate([ahpx,ahpy,-adj])
cylinder(d=bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
}
}
// multi-pcb standoff holes
if(multipcb_bottom_standoffs == true) {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
pcbid = sbc_data[s[0]][i+3];
pcbloc_x = sbc_data[s[0]][i+4];
pcbloc_y = sbc_data[s[0]][i+5];
pcbloc_z = sbc_data[s[0]][i+6];
if(class == "pcb") {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
pcbclass = sbc_data[s[0]][i+1];
pcbtype = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
pcbhole_x = sbc_data[s[0]][i+4]+pcb_loc_x+pcbloc_x;
pcbhole_y = sbc_data[s[0]][i+5]+pcb_loc_y+pcbloc_y;
pcbhole_z = sbc_data[s[0]][i+6];
pcbhole_size = sbc_data[s[0]][i+9][0];
pcbhole_state = sbc_data[s[0]][i+10][0];
pcbhole_pos = sbc_data[s[0]][i+10][4];
if(id == pcbid && id != 0 && pcbclass == "pcbhole") {
if (pcbclass == "pcbhole" && pcbhole_pos == "left_rear" &&
multipcb_bottom_rear_left_enable == true &&
(pcbhole_state == "bottom" || pcbhole_state == "both")) {
translate([pcbhole_x,pcbhole_y,-adj]) cylinder(d=multipcb_bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
if (pcbclass == "pcbhole" && pcbhole_pos == "left_front" &&
multipcb_bottom_front_left_enable == true &&
(pcbhole_state == "bottom" || pcbhole_state == "both")) {
translate([pcbhole_x,pcbhole_y,-adj]) cylinder(d=multipcb_bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
if (pcbclass == "pcbhole" && pcbhole_pos == "right_rear" &&
multipcb_bottom_rear_right_enable == true &&
(pcbhole_state == "bottom" || pcbhole_state == "both")) {
translate([pcbhole_x,pcbhole_y,-adj]) cylinder(d=multipcb_bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
if (pcbclass == "pcbhole" && pcbhole_pos == "right_front" &&
multipcb_bottom_front_right_enable == true &&
(pcbhole_state == "bottom" || pcbhole_state == "both")) {
translate([pcbhole_x,pcbhole_y,-adj]) cylinder(d=multipcb_bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
}
}
}
}
}
// extended standoff holes
if(ext_bottom_standoffs == true) {
// right-rear standoff
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 || pcb_loc_y >= 10)) &&
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_bottom_standoff_support_size
|| pcb_loc_y >= ext_bottom_standoff_support_size)) &&
ext_bottom_rear_right_enable == true && ext_bottom_standoff[6] != "blind") {
translate([width-ext_bottom_standoff_support_size/4-(2*(wallthick+gap))-(corner_fillet/2),
(corner_fillet/2)+ext_bottom_standoff_support_size/4,-1]) cylinder(d=ext_bottom_standoff[4]-.2, h=bottom_height);
translate([width-ext_bottom_standoff_support_size/4-(2*(wallthick+gap)),
ext_bottom_standoff_support_size/4,-adj])
cylinder(d=ext_bottom_standoff[4]-.2, h=floorthick+(2+adj));
}
// right-front standoff
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth >= 10) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth <= 10) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= 10 && depth-pcb_loc_y-pcb_depth >= 10)) &&
ext_bottom_front_right_enable == true && ext_bottom_standoff[6] != "blind") {
translate([width-ext_bottom_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),
depth-ext_bottom_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),-1])
cylinder(d=ext_bottom_standoff[4]-.2, h=bottom_height);
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_bottom_standoff_support_size &&
depth-pcb_loc_y-pcb_depth >= ext_bottom_standoff_support_size) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_bottom_standoff_support_size &&
depth-pcb_loc_y-pcb_depth <= ext_bottom_standoff_support_size) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= ext_bottom_standoff_support_size &&
depth-pcb_loc_y-pcb_depth >= ext_bottom_standoff_support_size)) &&
ext_bottom_front_right_enable == true && ext_bottom_standoff[6] != "blind") {
translate([width-ext_bottom_standoff_support_size/4-(2*(wallthick+gap)),
depth-ext_bottom_standoff_support_size/4-(2*(wallthick+gap)),-adj])
cylinder(d=ext_bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
// left-rear standoff
if((pcb_loc_x >= 10 || pcb_loc_y >= 10) && ext_bottom_rear_left_enable == true && ext_bottom_standoff[6] != "blind") {
translate([(corner_fillet/2)+ext_bottom_standoff_support_size/4,
(corner_fillet/2)+ext_bottom_standoff_support_size/4,-1]) cylinder(d=ext_bottom_standoff[4]-.2, h=bottom_height);
if((pcb_loc_x >= ext_bottom_standoff_support_size || pcb_loc_y >= ext_bottom_standoff_support_size) &&
ext_bottom_rear_left_enable == true && ext_bottom_standoff[6] != "blind") {
translate([ext_bottom_standoff_support_size/4,
ext_bottom_standoff_support_size/4,-adj])
cylinder(d=ext_bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
// left-front standoff
if(((pcb_loc_x >= 10 && (depth-(pcb_loc_y+pcb_depth)) >= 10) ||
(pcb_loc_x <= 10 && (depth-(pcb_loc_y+pcb_depth)) >= 10) ||
(pcb_loc_x >= 10 && (depth-(pcb_loc_y+pcb_depth)) <= 10)) &&
ext_bottom_front_left_enable == true && ext_bottom_standoff[6] != "blind") {
translate([(corner_fillet/2)+ext_bottom_standoff_support_size/4,
depth-ext_bottom_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),-1])
cylinder(d=ext_bottom_standoff[4]-.2, h=bottom_height);
if(((pcb_loc_x >= ext_bottom_standoff_support_size &&
(depth-(pcb_loc_y+pcb_depth)) >= ext_bottom_standoff_support_size) ||
(pcb_loc_x <= ext_bottom_standoff_support_size &&
(depth-(pcb_loc_y+pcb_depth)) >= ext_bottom_standoff_support_size) ||
(pcb_loc_x >= ext_bottom_standoff_support_size &&
(depth-(pcb_loc_y+pcb_depth)) <= ext_bottom_standoff_support_size)) &&
ext_bottom_front_left_enable == true && ext_bottom_standoff[6] != "blind") {
translate([ext_bottom_standoff_support_size/4,
depth-(ext_bottom_standoff_support_size/4)-(2*(wallthick+gap)),-adj])
cylinder(d=ext_bottom_standoff[4]-.2, h=floorthick+(2*adj));
}
}
// bottom cover pattern
if(bottom_cover_pattern != "solid") {
xvent8_adj = pcb_width > 100 ? width/5.5 : width/6;
if(bottom_cover_pattern == "hex_5mm") {
translate([1,0,-2]) vent_hex((width)/3.75,(depth)/6,floorthick+4,5,1.5,"horizontal");
if(case_design == "panel_nas") {
translate([6,5,-floorthick+adj])
vent_hex((width-10)/3.75,(depth-10)/7,floorthick+4,5,1.5,"horizontal");
}
else {
translate([1,0,-floorthick]) vent_hex(width/3.75,depth/6,floorthick+4,5,1.5,"horizontal");
}
}
if(bottom_cover_pattern == "hex_8mm") {
translate([1,2,-2]) vent_hex((width)/5.5,(depth)/9.5,floorthick+4,8,1.5,"horizontal");
if(case_design == "panel_nas") {
translate([-gap+5,6,-floorthick+adj]) vent_hex(xvent8_adj,depth/9.5,floorthick+4,8,1.5,"horizontal");
}
else {
translate([1,2,-floorthick]) vent_hex(width/5.5,depth/9.5,floorthick+4,8,1.5,"horizontal");
}
}
if(bottom_cover_pattern == "linear_vertical") {
translate([0,-gap,-2]) vent(wallthick,depth-2*wallthick-gap,floorthick+4,1,1,(width-2*wallthick-gap)/4,"horizontal");
if(case_design == "panel_nas") {
translate([wallthick+gap,wallthick,-floorthick+adj])
vent(wallthick,depth-6*wallthick-gap,floorthick+4,1,1,(width-2*(sidethick+gap))/5.35,"horizontal");
}
else {
translate([0,-gap,-floorthick])
vent(wallthick,depth-2*wallthick-gap,floorthick+4,1,1,(width-2*wallthick-gap)/4,"horizontal");
}
}
if(bottom_cover_pattern == "linear_horizontal") {
translate([-gap,-gap,-2]) vent(width-2*wallthick-gap,wallthick,floorthick+4,1,(depth-2*wallthick-gap)/3,1,"horizontal");
if(case_design == "panel_nas") {
translate([wallthick+gap,wallthick,-floorthick+adj])
vent(width-4*(sidethick+gap),wallthick,floorthick+4,1,
(depth-2*(wallthick-gap))/4.35,1,"horizontal");
}
else {
translate([-gap,-gap,-floorthick])
vent(width-2*(wallthick+gap),wallthick,floorthick+4,1,(depth-2*wallthick-gap)/3,1,"horizontal");
}
}
if(bottom_cover_pattern == "astroid") {
if(case_design == "panel_nas") {
xast_adj = pcb_width <= 100 ? 8 : 6;
for(c=[xast_adj:12:depth-16]) {
for(r=[12:12:width-16]) {
translate([r,c,-floorthick]) linear_extrude(floorthick+5) import("./dxf/astroid_8mm.dxf");
}
}
}
else {
for(c=[3:12:depth-8]) {
for(r=[4:12:width-8]) {
translate([r,c,-4]) linear_extrude(floorthick+5) import("./dxf/astroid_8mm.dxf");
translate([r,c,-(2*floorthick)]) linear_extrude(floorthick+5) import("./dxf/astroid_8mm.dxf");
}
}
}
}
}
}
// rear io shield opening for standard form motherboards
@@ -473,7 +609,7 @@ echo(pcb_depth+case_offset_y-10);
}
}
}
// pcb standoffs
// primary pcb standoffs
if(sbc_bottom_standoffs == true) {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
@@ -484,14 +620,15 @@ echo(pcb_depth+case_offset_y-10);
pcbhole_z = sbc_data[s[0]][i+6];
pcbhole_size = sbc_data[s[0]][i+9][0];
pcbhole_pos = sbc_data[s[0]][i+10][4];
pcbadj_z = sbc_model == "n2" || sbc_model == "m1" ? -6 :
sbc_model == "n2+" ? -4.5 : 0;
if(class == "pcbhole" && id == pcb_id &&
(pcbhole_pos == "left_rear" || pcbhole_pos == "left_front" || pcbhole_pos == "right_rear" || pcbhole_pos == "right_front")) {
if(class == "pcbhole" && id == pcb_id) {
if (pcbhole_pos == "left_rear" && bottom_rear_left_enable == true) {
bottom_support = bottom_sidewall_support == true ? bottom_rear_left_support : "none";
pcb_standoff = [bottom_standoff[0],
bottom_standoff[1],
bottom_height-pcb_z+pcb_loc_z+bottom_rear_left_adjust,
bottom_height-pcb_z+pcb_loc_z+bottom_rear_left_adjust+pcbadj_z,
bottom_standoff[3],
bottom_standoff[4],
bottom_standoff[5],
@@ -502,13 +639,18 @@ echo(pcb_depth+case_offset_y-10);
bottom_standoff[10],
bottom_standoff[11],
bottom_standoff[12]];
translate([pcbhole_x,pcbhole_y,0]) standoff(pcb_standoff,[false,10,2,"default"]);
ahpx = sbc_model == "n2" ? 7 : sbc_model == "n2+" ? 9.25 :
sbc_model == "m1" ? 9.25 : pcbhole_x;
ahpy = sbc_model == "n2" ? 15 : sbc_model == "n2+" ? 9.25 :
sbc_model == "m1" ? 9.25 : pcbhole_y;
translate([ahpx,ahpy,0])
standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "left_front" && bottom_front_left_enable == true) {
bottom_support = bottom_sidewall_support == true ? bottom_front_left_support : "none";
pcb_standoff = [bottom_standoff[0],
bottom_standoff[1],
bottom_height-pcb_z+pcb_loc_z+bottom_front_left_adjust,
bottom_height-pcb_z+pcb_loc_z+bottom_front_left_adjust+pcbadj_z,
bottom_standoff[3],
bottom_standoff[4],
bottom_standoff[5],
@@ -519,13 +661,18 @@ echo(pcb_depth+case_offset_y-10);
bottom_standoff[10],
bottom_standoff[11],
bottom_standoff[12]];
translate([pcbhole_x,pcbhole_y,0]) standoff(pcb_standoff,[false,10,2,"default"]);
ahpx = sbc_model == "n2" ? 8 : sbc_model == "n2+" ? 9.25 :
sbc_model == "m1" ? 9.25 : pcbhole_x;
ahpy = sbc_model == "n2" ? 75 : sbc_model == "n2+" ? 80.75 :
sbc_model == "m1" ? 112.75 : pcbhole_y;
translate([ahpx,ahpy,0])
standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "right_rear" && bottom_rear_right_enable == true) {
bottom_support = bottom_sidewall_support == true ? bottom_rear_right_support : "none";
pcb_standoff = [bottom_standoff[0],
bottom_standoff[1],
bottom_height-pcb_z+pcb_loc_z+bottom_rear_right_adjust,
bottom_height-pcb_z+pcb_loc_z+bottom_rear_right_adjust+pcbadj_z,
bottom_standoff[3],
bottom_standoff[4],
bottom_standoff[5],
@@ -536,13 +683,18 @@ echo(pcb_depth+case_offset_y-10);
bottom_standoff[10],
bottom_standoff[11],
bottom_standoff[12]];
translate([pcbhole_x,pcbhole_y,0]) standoff(pcb_standoff,[false,10,2,"default"]);
ahpx = sbc_model == "n2" ? 82 : sbc_model == "n2+" ? 80.75 :
sbc_model == "m1" ? 80.75 : pcbhole_x;
ahpy = sbc_model == "n2" ? 6 : sbc_model == "n2+" ? 9.25 :
sbc_model == "m1" ? 9.25 : pcbhole_y;
translate([ahpx,ahpy,0])
standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "right_front" && bottom_front_right_enable == true) {
bottom_support = bottom_sidewall_support == true ? bottom_front_right_support : "none";
pcb_standoff = [bottom_standoff[0],
bottom_standoff[1],
bottom_height-pcb_z+pcb_loc_z+bottom_front_right_adjust,
bottom_height-pcb_z+pcb_loc_z+bottom_front_right_adjust+pcbadj_z,
bottom_standoff[3],
bottom_standoff[4],
bottom_standoff[5],
@@ -553,16 +705,120 @@ echo(pcb_depth+case_offset_y-10);
bottom_standoff[10],
bottom_standoff[11],
bottom_standoff[12]];
translate([pcbhole_x,pcbhole_y,0]) standoff(pcb_standoff,[false,10,2,"default"]);
ahpx = sbc_model == "n2" ? 82 : sbc_model == "n2+" ? 80.75 :
sbc_model == "m1" ? 80.75 : pcbhole_x;
ahpy = sbc_model == "n2" ? 75 : sbc_model == "n2+" ? 80.75 :
sbc_model == "m1" ? 112.75 : pcbhole_y;
translate([ahpx,ahpy,0])
standoff(pcb_standoff,[false,10,2,"default"]);
}
}
}
}
// multi-pcb standoffs
if(multipcb_bottom_standoffs == true) {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
pcbid = sbc_data[s[0]][i+3];
pcbloc_x = sbc_data[s[0]][i+4];
pcbloc_y = sbc_data[s[0]][i+5];
pcbloc_z = sbc_data[s[0]][i+6];
if(class == "pcb") {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
pcbclass = sbc_data[s[0]][i+1];
pcbtype = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
pcbhole_x = sbc_data[s[0]][i+4]+pcb_loc_x+pcbloc_x;
pcbhole_y = sbc_data[s[0]][i+5]+pcb_loc_y+pcbloc_y;
pcbhole_z = sbc_data[s[0]][i+6];
pcbhole_size = sbc_data[s[0]][i+9][0];
pcbhole_state = sbc_data[s[0]][i+10][0];
pcbhole_pos = sbc_data[s[0]][i+10][4];
if(pcbclass == "pcbhole" && pcbid == id && id != 0) {
if (pcbhole_pos == "left_rear" && multipcb_bottom_rear_left_enable == true &&
(pcbhole_state == "bottom" || pcbhole_state == "both")) {
bottom_support = multipcb_bottom_sidewall_support == true ? multipcb_bottom_rear_left_support : "none";
pcb_standoff = [multipcb_bottom_standoff[0],
multipcb_bottom_standoff[1],
bottom_height-pcb_z+pcb_loc_z+multipcb_bottom_rear_left_adjust,
multipcb_bottom_standoff[3],
multipcb_bottom_standoff[4],
multipcb_bottom_standoff[5],
multipcb_bottom_standoff[6],
multipcb_bottom_standoff[7],
bottom_support,
multipcb_bottom_standoff[9],
multipcb_bottom_standoff[10],
multipcb_bottom_standoff[11],
multipcb_bottom_standoff[12]];
translate([pcbhole_x,pcbhole_y,0]) standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "left_front" && multipcb_bottom_front_left_enable == true &&
(pcbhole_state == "bottom" || pcbhole_state == "both")) {
bottom_support = multipcb_bottom_sidewall_support == true ? multipcb_bottom_front_left_support : "none";
pcb_standoff = [multipcb_bottom_standoff[0],
multipcb_bottom_standoff[1],
bottom_height-pcb_z+pcb_loc_z+multipcb_bottom_front_left_adjust,
multipcb_bottom_standoff[3],
multipcb_bottom_standoff[4],
multipcb_bottom_standoff[5],
multipcb_bottom_standoff[6],
multipcb_bottom_standoff[7],
bottom_support,
multipcb_bottom_standoff[9],
multipcb_bottom_standoff[10],
multipcb_bottom_standoff[11],
multipcb_bottom_standoff[12]];
translate([pcbhole_x,pcbhole_y,0]) standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "right_rear" && multipcb_bottom_rear_right_enable == true &&
(pcbhole_state == "bottom" || pcbhole_state == "both")) {
bottom_support = multipcb_bottom_sidewall_support == true ? multipcb_bottom_rear_right_support : "none";
pcb_standoff = [multipcb_bottom_standoff[0],
multipcb_bottom_standoff[1],
bottom_height-pcb_z+pcb_loc_z+multipcb_bottom_rear_right_adjust,
multipcb_bottom_standoff[3],
multipcb_bottom_standoff[4],
multipcb_bottom_standoff[5],
multipcb_bottom_standoff[6],
multipcb_bottom_standoff[7],
bottom_support,
multipcb_bottom_standoff[9],
multipcb_bottom_standoff[10],
multipcb_bottom_standoff[11],
multipcb_bottom_standoff[12]];
translate([pcbhole_x,pcbhole_y,0]) standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "right_front" && multipcb_bottom_front_right_enable == true &&
(pcbhole_state == "bottom" || pcbhole_state == "both")) {
bottom_support = multipcb_bottom_sidewall_support == true ? multipcb_bottom_front_right_support : "none";
pcb_standoff = [multipcb_bottom_standoff[0],
multipcb_bottom_standoff[1],
bottom_height-pcb_z+pcb_loc_z+multipcb_bottom_front_right_adjust,
multipcb_bottom_standoff[3],
multipcb_bottom_standoff[4],
multipcb_bottom_standoff[5],
multipcb_bottom_standoff[6],
multipcb_bottom_standoff[7],
bottom_support,
multipcb_bottom_standoff[9],
multipcb_bottom_standoff[10],
multipcb_bottom_standoff[11],
multipcb_bottom_standoff[12]];
translate([pcbhole_x,pcbhole_y,0]) standoff(pcb_standoff,[false,10,2,"default"]);
}
}
}
}
}
}
// extended standoffs
if(ext_bottom_standoffs == true) {
// extended right-rear standoff
if((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 || pcb_loc_y >= 10) && ext_bottom_rear_right_enable == true) {
if((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_bottom_standoff_support_size ||
pcb_loc_y >= ext_bottom_standoff_support_size) && ext_bottom_rear_right_enable == true) {
extended_standoff = [ext_bottom_standoff[0],
ext_bottom_standoff[1],
bottom_height+ext_bottom_rear_right_adjust,
@@ -576,14 +832,18 @@ echo(pcb_depth+case_offset_y-10);
ext_bottom_standoff[10],
ext_bottom_standoff[11],
ext_bottom_standoff[12]];
translate([width-ext_top_standoff_support_size/4-(2*(wallthick+gap))-(corner_fillet/2),
(corner_fillet/2)+ext_top_standoff_support_size/4,0]) standoff(extended_standoff,[false,10,2,"default"]);
translate([width-ext_bottom_standoff_support_size/4-(2*(wallthick+gap)),
ext_bottom_standoff_support_size/4,0])
standoff(extended_standoff,[false,10,2,"default"]);
}
// extended right-front standoff
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth >= 10) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth <= 10) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= 10 && depth-pcb_loc_y-pcb_depth >= 10)) &&
ext_bottom_front_right_enable == true) {
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_bottom_standoff_support_size &&
depth-pcb_loc_y-pcb_depth >= ext_bottom_standoff_support_size) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_bottom_standoff_support_size &&
depth-pcb_loc_y-pcb_depth <= ext_bottom_standoff_support_size) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= ext_bottom_standoff_support_size &&
depth-pcb_loc_y-pcb_depth >= ext_bottom_standoff_support_size)) &&
ext_bottom_front_right_enable == true) {
extended_standoff = [ext_bottom_standoff[0],
ext_bottom_standoff[1],
bottom_height+ext_bottom_front_right_adjust,
@@ -597,11 +857,13 @@ echo(pcb_depth+case_offset_y-10);
ext_bottom_standoff[10],
ext_bottom_standoff[11],
ext_bottom_standoff[12]];
translate([width-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),
depth-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),0]) standoff(extended_standoff,[false,10,2,"default"]);
translate([width-ext_bottom_standoff_support_size/4-(2*(wallthick+gap)),
depth-ext_bottom_standoff_support_size/4-(2*(wallthick+gap)),0])
standoff(extended_standoff,[false,10,2,"default"]);
}
// extended left-rear standoff
if((pcb_loc_x >= 10 || pcb_loc_y >= 10) && ext_bottom_rear_left_enable == true) {
if((pcb_loc_x >= ext_bottom_standoff_support_size || pcb_loc_y >= ext_bottom_standoff_support_size)
&& ext_bottom_rear_left_enable == true) {
extended_standoff = [ext_bottom_standoff[0],
ext_bottom_standoff[1],
bottom_height+ext_bottom_rear_left_adjust,
@@ -615,14 +877,17 @@ echo(pcb_depth+case_offset_y-10);
ext_bottom_standoff[10],
ext_bottom_standoff[11],
ext_bottom_standoff[12]];
translate([(corner_fillet/2)+ext_top_standoff_support_size/4,
(corner_fillet/2)+ext_top_standoff_support_size/4,0]) standoff(extended_standoff,[false,10,2,"default"]);
translate([ext_bottom_standoff_support_size/4, ext_bottom_standoff_support_size/4,0])
standoff(extended_standoff,[false,10,2,"default"]);
}
// extended left-front standoff
if(((pcb_loc_x >= 10 && depth-(pcb_loc_y+pcb_depth) >= 10) ||
(pcb_loc_x <= 10 && depth-(pcb_loc_y+pcb_depth) >= 10) ||
(pcb_loc_x >= 10 && depth-(pcb_loc_y+pcb_depth) <= 10)) &&
ext_bottom_front_left_enable == true) {
if(((pcb_loc_x >= ext_bottom_standoff_support_size &&
depth-(pcb_loc_y+pcb_depth) >= ext_bottom_standoff_support_size) ||
(pcb_loc_x <= ext_bottom_standoff_support_size &&
depth-(pcb_loc_y+pcb_depth) >= ext_bottom_standoff_support_size) ||
(pcb_loc_x >= ext_bottom_standoff_support_size &&
depth-(pcb_loc_y+pcb_depth) <= ext_bottom_standoff_support_size)) &&
ext_bottom_front_left_enable == true) {
extended_standoff = [ext_bottom_standoff[0],
ext_bottom_standoff[1],
bottom_height+ext_bottom_front_left_adjust,
@@ -636,8 +901,8 @@ echo(pcb_depth+case_offset_y-10);
ext_bottom_standoff[10],
ext_bottom_standoff[11],
ext_bottom_standoff[12]];
translate([(corner_fillet/2)+ext_top_standoff_support_size/4,
depth-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),0])
translate([ext_bottom_standoff_support_size/4,
depth-(ext_bottom_standoff_support_size/4)-(2*(wallthick+gap)),0])
standoff(extended_standoff,[false,10,2,"default"]);
}
}
@@ -694,7 +959,8 @@ echo(pcb_depth+case_offset_y-10);
access_panel([access_panel_size[0],access_panel_size[1],floorthick], access_panel_orientation, [true,10,2,"default"]);
}
if(access_panel_rotation == 180) {
translate([access_panel_location[0]+access_panel_size[0],access_panel_location[1]+access_panel_size[1],0]) rotate([0,0,access_panel_rotation])
translate([access_panel_location[0]+access_panel_size[0],access_panel_location[1]+access_panel_size[1],0])
rotate([0,0,access_panel_rotation])
access_panel([access_panel_size[0],access_panel_size[1],floorthick], access_panel_orientation, [true,10,2,"default"]);
}
if(access_panel_rotation == 270) {
@@ -713,20 +979,29 @@ echo(pcb_depth+case_offset_y-10);
}
// indents
if(indents == true) {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
loc_x = sbc_data[s[0]][i+4]+pcb_loc_x;
loc_y = sbc_data[s[0]][i+5]+pcb_loc_y;
loc_z = sbc_data[s[0]][i+6]+pcb_loc_z;
side = sbc_data[s[0]][i+7];
rotation = sbc_data[s[0]][i+8];
// indent(loc_x, loc_y, bottom_height+pcb_loc_z-adj, rotation[2], side, class, type, wallthick, gap, floorthick, pcb_z);
indent(loc_x, loc_y, bottom_height+pcb_loc_z-adj, rotation[2], side, class, type, wallthick, gap, floorthick, pcb_z);
}
pcbid = sbc_data[s[0]][i+3];
pcbloc_x = sbc_data[s[0]][i+4];
pcbloc_y = sbc_data[s[0]][i+5];
pcbloc_z = sbc_data[s[0]][i+6];
if(class == "pcb") {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
loc_x = sbc_data[s[0]][i+4]+pcb_loc_x+pcbloc_x;
loc_y = sbc_data[s[0]][i+5]+pcb_loc_y+pcbloc_y;
loc_z = sbc_data[s[0]][i+6]+pcb_loc_z+pcbloc_z;
side = sbc_data[s[0]][i+7];
rotation = sbc_data[s[0]][i+8];
if(id == pcbid) {
indent(loc_x, loc_y, bottom_height+loc_z-adj, rotation[2], side, class, type, wallthick, gap, floorthick, pcb_z);
}
}
}
}
}
// clean fillets
if(case_design == "shell") {

1293
mod/case_rack.scad Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -128,6 +128,317 @@ module case_side(case_design, side) {
}
}
}
if(case_design == "panel_nas") {
x_adj = pcb_width > 100 ? width-2*sidethick : 101.6+case_offset_x;
xtab_adj = pcb_width > 100 ? width-gap-2*sidethick-adj : 101.6-gap+case_offset_x-adj;
xvent8_adj = pcb_width > 100 ? width/5.5 : width/6;
if(side == "rear") {
difference() {
union() {
translate([-gap,-(2*wallthick),0])
cube([x_adj,wallthick,case_z-floorthick]);
// bottom right tab
translate([xtab_adj,-(2*wallthick),20])
cube([sidethick+(2*adj),wallthick,10]);
// top right tab
translate([xtab_adj,-(2*wallthick),case_z-30])
cube([sidethick+(2*adj),wallthick,10]);
// bottom left tab
translate([-sidethick-gap-adj,-(2*wallthick),20])
cube([sidethick+(2*adj),wallthick,10]);
// top left tab
translate([-sidethick-gap-adj,-(2*wallthick),case_z-30])
cube([sidethick+(2*adj),wallthick,10]);
if(hd_bays > 3) {
// middle right tab
translate([xtab_adj,-(2*wallthick),(case_z/2)-5])
cube([sidethick+(2*adj),wallthick,10]);
// middle left tab
translate([-sidethick-gap-adj,-(2*wallthick),(case_z/2)-5])
cube([sidethick+(2*adj),wallthick,10]);
}
}
if(rear_fan == 1 || rear_fan == 2) {
if(rear_fan_center == false) {
translate([-1+(101.6-rear_fan_size)/2,-1,rear_fan_position])
rotate([90,0,0]) fan_mask(rear_fan_size, wallthick+2, rear_cooling);
}
if(rear_fan_center == true) {
translate([-1+(101.6-rear_fan_size)/2+(width-2*(sidethick+gap)-101.6)/2,-1,rear_fan_position])
rotate([90,0,0]) fan_mask(rear_fan_size, wallthick+2, rear_cooling);
}
}
if(rear_fan == 2) {
if(rear_fan_center == false) {
translate([-1+(101.6-rear_fan_size)/2,-1,rear_fan_position+rear_dualfan_spacing+rear_fan_size])
rotate([90,0,0]) fan_mask(rear_fan_size, wallthick+2, rear_cooling);
}
if(rear_fan_center == true) {
translate([-1+(101.6-rear_fan_size)/2+(width-2*(sidethick+gap)-101.6)/2,
-1,rear_fan_position+rear_dualfan_spacing+rear_fan_size])
rotate([90,0,0]) fan_mask(rear_fan_size, wallthick+2, rear_cooling);
}
}
}
}
if(side == "front") {
difference() {
union() {
translate([-gap,depth-(4*wallthick),floorthick])
cube([x_adj,wallthick,case_z-3*floorthick]);
// bottom right tab
translate([xtab_adj,depth-(4*wallthick),20])
cube([sidethick+(2*adj),wallthick,10]);
// top right tab
translate([xtab_adj,depth-(4*wallthick),case_z-30])
cube([sidethick+(2*adj),wallthick,10]);
// bottom left tab
translate([-sidethick-gap-adj,depth-(4*wallthick),20])
cube([sidethick+(2*adj),wallthick,10]);
// top left tab
translate([-sidethick-gap-adj,depth-(4*wallthick),case_z-30])
cube([sidethick+(2*adj),wallthick,10]);
if(hd_bays > 3) {
// middle right tab
translate([xtab_adj,depth-(4*wallthick),(case_z/2)-5])
cube([sidethick+(2*adj),wallthick,10]);
// middle left tab
translate([-sidethick-gap-adj,depth-(4*wallthick),(case_z/2)-5])
cube([sidethick+(2*adj),wallthick,10]);
}
}
// front cover pattern
if(front_cover_pattern != "solid" && case_design == "panel_nas") {
xvent_pos = pcb_width <= 100 ? -gap+3 : -gap+6;
if(front_cover_pattern == "hex_5mm" && hd_bays < 6) {
translate([xvent_pos,depth-3*(wallthick)+gap,hd_z_position-5])
vent_hex(round(width/3.85),round(hd_bays*(27.1+hd_space)/5.75),wallthick+4,5,1.5,"vertical");
}
if(front_cover_pattern == "hex_5mm" && hd_bays == 6) {
translate([xvent_pos,depth-3*(wallthick)+gap,hd_z_position])
vent_hex(round(width/3.85),round(hd_bays*(27.1+hd_space)/5.75),wallthick+4,5,1.5,"vertical");
}
if(front_cover_pattern == "hex_8mm") {
translate([-gap+4,depth-3*(wallthick)+gap,hd_z_position])
vent_hex(xvent8_adj,round(hd_bays*(27.1+hd_space)/5.75)-5,floorthick+4,8,1.5,"vertical");
}
if(front_cover_pattern == "linear_vertical") {
translate([-gap+4,depth-3*(wallthick)+gap,hd_z_position])
vent(wallthick,(case_z-2*(wallthick+gap)-20)/8,floorthick+4,1,1,
(width-2*(sidethick+gap))/5.35,"vertical");
translate([-gap+4,depth-3*(wallthick)+gap,case_z-(top_height+bottom_height+4*floorthick)-5])
vent(wallthick,(case_z-2*(wallthick+gap)-20)/8,floorthick+4,1,1,
(width-2*(sidethick+gap))/5.35,"vertical");
}
if(front_cover_pattern == "linear_horizontal") {
translate([wallthick+gap,depth-3*(wallthick)+gap,hd_z_position])
vent(width-2*(wallthick+gap+sidethick)-4,wallthick,floorthick+4,2,
(case_z-2*(wallthick+gap)-20)/20,1,"vertical");
translate([wallthick+gap,depth-3*(wallthick)+gap,
case_z-(top_height+bottom_height+4*floorthick)-20])
vent(width-4*(sidethick+gap),,wallthick,floorthick+4,2,
(case_z-2*(wallthick+gap)-20)/20,1,"vertical");
}
if(front_cover_pattern == "astroid") {
xast_adj = pcb_width <= 100 ? 8 : 6;
for(c=[xast_adj:12:case_z-20]) {
for(r=[8:12:width-8]) {
translate([r,depth-2*wallthick,c]) rotate([90,0,0])
linear_extrude(wallthick+5) import("./dxf/astroid_8mm.dxf");
}
}
}
}
}
}
if(side == "right") {
difference() {
if(case_design == "panel_nas") {
if(pcb_width > 100) {
translate([pcb_width+sidethick+gap+case_offset_x,-(3*wallthick)-gap,-2*wallthick])
rotate([0,-90,0]) slab([case_z+(3*wallthick),depth+2*wallthick,sidethick],corner_fillet);
}
if(pcb_width <= 100) {
translate([101.6-gap+sidethick+case_offset_x,-(3*wallthick)-gap,-2*wallthick])
rotate([0,-90,0]) slab([case_z+(3*wallthick),depth+2*wallthick,sidethick],corner_fillet);
}
}
else {
translate([width-2*sidethick-gap,-(3*wallthick)-gap,-2*wallthick])
rotate([0,-90,0]) slab([case_z+(3*wallthick),depth+2*wallthick,sidethick],corner_fillet);
}
// rear edge top tab openings
translate([width-3*sidethick-gap-adj,-2*wallthick+adj-tol,case_z-30])
cube([2*sidethick+2*adj,wallthick+tol,20+tol]);
translate([width-3*sidethick-gap-adj,-(4*wallthick)+2*adj,case_z-20])
cube([2*sidethick+(2*adj),2*wallthick,10+tol]);
// rear edge bottom tab openings
translate([width-3*sidethick-gap-adj,-2*wallthick+adj-tol,20])
cube([2*sidethick+2*adj,wallthick+tol,20+tol]);
translate([width-3*sidethick-gap-adj,-(4*wallthick)+2*adj,30])
cube([2*sidethick+(2*adj),2*wallthick,10+tol]);
// front edge top tab openings
translate([width-3*sidethick-gap-adj,depth-(4*wallthick),case_z-30])
cube([2*sidethick+(2*adj),wallthick+tol,20+tol]);
translate([width-3*sidethick-gap-adj,depth-(4*wallthick),case_z-20])
cube([2*sidethick+(2*adj),3*wallthick,10+tol]);
// front edge bottom tab openings
translate([width-3*sidethick-gap-adj,depth-(4*wallthick),20])
cube([2*sidethick+(2*adj),wallthick+tol,20+tol]);
translate([width-3*sidethick-gap-adj,depth-(4*wallthick),30])
cube([2*sidethick+(2*adj),3*wallthick,10+tol]);
if(hd_bays > 3) {
// front edge middle tab openings
translate([width-3*sidethick-gap-adj,depth-(4*wallthick),(case_z/2)-5])
cube([2*sidethick+2*adj,wallthick+tol,20+tol]);
translate([width-3*sidethick-gap-adj,depth-(4*wallthick),(case_z/2)-5+10])
cube([2*sidethick+(2*adj),3*wallthick,10+tol]);
// rear edge middle tab openings
translate([width-3*sidethick-gap-adj,-2*wallthick+adj-tol,(case_z/2)-5])
cube([2*sidethick+2*adj,wallthick+tol,20+tol]);
translate([width-3*sidethick-gap-adj,-(4*wallthick),(case_z/2)-5+10])
cube([2*sidethick+(2*adj),3*wallthick,10+tol]);
}
// hd holes for bays
if(hd_reverse == false) {
for( i=[0:1:hd_bays-1]) {
translate([(width-101.6)-(4*sidethick)-gap+adj,
-(3*wallthick)-gap+hd_y_position,hd_z_position+(hd_space+27.1)*i])
hd_holes(3.5, "portrait", "both", 4*sidethick+2);
}
}
else {
for( i=[0:1:hd_bays-1]) {
translate([width-(4*sidethick)-adj,-(3*wallthick)-gap+hd_y_position+147,
hd_z_position+(hd_space+27.1)*i])
rotate([0,0,180]) hd_holes(3.5, "portrait", "both", 4*sidethick+2);
}
}
// top edge front tab opening
translate([width-3*sidethick-gap-adj,depth-(3*wallthick)-gap-adj-30-tol,
case_z-(2*floorthick)])
cube([2*sidethick+(2*adj),20+tol,floorthick+tol]);
translate([width-3*sidethick-gap-adj,depth-(3*wallthick)-gap-adj-30-tol,
case_z-(2*floorthick)])
cube([2*sidethick+(2*adj),10+tol,(3*floorthick)+adj]);
// top edge rear tab opening
translate([width-3*sidethick-gap-adj,40-wallthick-gap-adj-tol,
case_z-(2*floorthick)])
cube([2*sidethick+(2*adj),10+tol,floorthick+tol]);
translate([width-3*sidethick-gap-adj,30-wallthick-gap+adj-tol,
case_z-(2*floorthick)])
cube([2*sidethick+(2*adj),10+tol,(3*floorthick)+adj]);
// bottom edge front tab opening
translate([width-3*sidethick-gap-adj,depth-(3*wallthick)-gap-adj-30-tol,-tol])
cube([2*sidethick+2*adj,20+tol,floorthick+tol]);
translate([width-3*sidethick-gap-adj,depth-(3*wallthick)-gap-adj-30-tol,-(3*floorthick)+adj])
cube([2*sidethick+2*adj,10+tol,(3*floorthick)+adj]);
// bottom edge rear tab opening
translate([width-3*sidethick-gap-adj,30-wallthick-gap+adj-tol,-tol])
cube([2*sidethick+2*adj,20+tol,floorthick+tol]);
translate([width-3*sidethick-gap-adj,30-wallthick-gap+adj-tol,-(3*floorthick)+adj])
cube([2*sidethick+(2*adj),10+tol,(3*floorthick)+adj]);
}
}
if(side == "left") {
difference() {
translate([-gap,-(3*wallthick)-gap,-2*wallthick])
rotate([0,-90,0]) slab([case_z+(3*wallthick),depth+(2*wallthick),sidethick],corner_fillet);
// rear edge top tab openings
translate([-sidethick-gap-adj,-2*wallthick+adj-tol,case_z-30])
cube([sidethick+2*adj,wallthick+tol,20]);
translate([-sidethick-gap-adj,-(4*wallthick)+tol,case_z-20])
cube([sidethick+(2*adj),3*wallthick+adj,10+tol]);
// rear edge bottom tab openings
translate([-sidethick-gap-adj,-2*wallthick+adj-tol,20])
cube([sidethick+2*adj,wallthick+tol,20]);
translate([-sidethick-gap-adj,-(4*wallthick)+tol,30])
cube([sidethick+(2*adj),3*wallthick,10+tol]);
// front edge top tab openings
translate([-sidethick-gap-adj,depth-(4*wallthick),case_z-30])
cube([sidethick+(2*adj),wallthick+tol,20]);
translate([-sidethick-gap-adj,depth-(4*wallthick),case_z-20])
cube([sidethick+(2*adj),3*wallthick,10+tol]);
// front edge bottom tab openings
translate([-sidethick-gap-adj,depth-(4*wallthick),20])
cube([sidethick+(2*adj),wallthick+tol,20]);
translate([-sidethick-gap-adj,depth-(4*wallthick),30])
cube([sidethick+(2*adj),3*wallthick,10+tol]);
if(hd_bays > 3) {
// rear edge middle tab openings
translate([-sidethick-gap-adj,-2*wallthick+adj-tol,(case_z/2)-5])
cube([sidethick+2*adj,wallthick+tol,20]);
translate([-sidethick-gap-adj,-(4*wallthick)+tol,(case_z/2)-5+10])
cube([sidethick+(2*adj),3*wallthick,10+tol]);
// front edge middle tab openings
translate([-sidethick-gap-adj,depth-(4*wallthick),(case_z/2)-5])
cube([sidethick+2*adj,wallthick+tol,20]);
translate([-sidethick-gap-adj,depth-(4*wallthick),(case_z/2)-5+10])
cube([sidethick+(2*adj),3*wallthick,10+tol]);
}
// hd holes for bays
if(hd_reverse == false) {
for( i=[0:1:hd_bays-1]) {
translate([-gap+adj,-(3*wallthick)-gap+hd_y_position,hd_z_position+(hd_space+27.1)*i])
hd_holes(3.5, "portrait", "both", sidethick+2);
}
}
else {
for( i=[0:1:hd_bays-1]) {
translate([101.6-gap+adj,-(3*wallthick)-gap+hd_y_position+147,
hd_z_position+(hd_space+27.1)*i])
rotate([0,0,180]) hd_holes(3.5, "portrait", "both", sidethick+2);
}
}
// top edge front tab openings
translate([-gap-sidethick-adj,depth-(3*wallthick)-gap-adj-30,
case_z-(2*floorthick)])
cube([sidethick+(2*adj),20,floorthick+tol]);
translate([-gap-sidethick-adj,depth-(3*wallthick)-gap-adj-30-tol,
case_z-(2*floorthick)])
cube([sidethick+(2*adj),10+tol,(3*floorthick)+adj]);
// top edge rear tab openings
translate([-gap-sidethick-adj,30-wallthick-gap+adj,
case_z-(2*floorthick)])
cube([sidethick+(2*adj),20,floorthick+tol]);
translate([-gap-sidethick-adj,30-wallthick-gap+adj-tol,
case_z-(2*floorthick)])
cube([sidethick+(2*adj),10+tol,(3*floorthick)+adj]);
// bottom edge front tab openings
translate([-gap-sidethick-adj,depth-(3*wallthick)-gap-adj-30,-tol])
cube([sidethick+(2*adj),20,floorthick+tol]);
translate([-gap-sidethick-adj,depth-(3*wallthick)-gap-adj-30-tol,-(2*floorthick)-adj])
cube([sidethick+(2*adj),10+tol,(3*floorthick)+adj]);
// bottom edge rear tab openings
translate([-gap-sidethick-adj,30-wallthick-gap+adj,-tol])
cube([sidethick+(2*adj),20,floorthick+tol]);
translate([-gap-sidethick-adj,30-wallthick-gap+adj-tol,-(2*floorthick)-adj])
cube([sidethick+(2*adj),10+tol,(3*floorthick)+adj]);
}
}
}
if(case_design == "tray_sides") {
if(side == "right") {
difference() {
@@ -256,29 +567,72 @@ module case_side(case_design, side) {
}
}
// sbc openings
if(sbc_highlight == true) {
#translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj-adj])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
if(case_design != "panel_nas") {
if(sbc_highlight == true) {
#translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj-adj])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
else {
translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj-adj])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
}
else {
translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj-adj])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
if(nas_sbc_location == "top") {
if(sbc_highlight == true) {
#translate([pcb_loc_x ,pcb_loc_y,case_z-(top_height+pcb_loc_z+(2*floorthick))])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
else {
translate([pcb_loc_x ,pcb_loc_y,case_z-(top_height+pcb_loc_z+(2*floorthick))])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
}
if(nas_sbc_location == "bottom") {
if(sbc_highlight == true) {
#translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
else {
translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
}
}
// indents
if(indents == true) {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
loc_x = sbc_data[s[0]][i+4]+pcb_loc_x;
loc_y = sbc_data[s[0]][i+5]+pcb_loc_y;
loc_z = sbc_data[s[0]][i+6]+pcb_loc_z;
side = sbc_data[s[0]][i+7];
rotation = sbc_data[s[0]][i+8];
pcbid = sbc_data[s[0]][i+3];
pcbloc_x = sbc_data[s[0]][i+4];
pcbloc_y = sbc_data[s[0]][i+5];
pcbloc_z = sbc_data[s[0]][i+6];
if(class == "pcb") {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
loc_x = sbc_data[s[0]][i+4]+pcb_loc_x+pcbloc_x;
loc_y = sbc_data[s[0]][i+5]+pcb_loc_y+pcbloc_y;
loc_z = sbc_data[s[0]][i+6]+pcb_loc_z+pcbloc_z;
side = sbc_data[s[0]][i+7];
rotation = sbc_data[s[0]][i+8];
if(id == pcbid && case_design != "panel_nas") {
indent(loc_x, loc_y, bottom_height+loc_z-adj, rotation[2], side, class, type, wallthick, gap, floorthick, pcb_z);
}
if(id == pcbid && case_design == "panel_nas" && nas_sbc_location == "bottom") {
indent(loc_x, loc_y, bottom_height+loc_z-adj, rotation[2], side, class,
type, 2*wallthick, gap, floorthick, pcb_z);
indent(loc_x, loc_y, bottom_height+pcb_loc_z-adj, rotation[2], side, class, type, wallthick, gap, floorthick, pcb_z);
}
}
if(id == pcbid && case_design == "panel_nas" && nas_sbc_location == "top") {
indent(loc_x, loc_y, case_z-(top_height+pcb_loc_z+(2*floorthick))+.5, rotation[2],
side, class, type, 2*wallthick, gap, floorthick, pcb_z);
}
}
}
}
}
}
if(accessory_name != "none") {

View File

@@ -47,7 +47,7 @@ module case_top(case_design) {
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,
bottom_height+(top_height/2)-floorthick])
cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),top_height],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick],
top=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet],
bottom=[0,0,0,0], $fn=90);
}
@@ -70,6 +70,26 @@ module case_top(case_design) {
cube([8,wallthick+2*adj,floorthick]);
}
}
if(case_design == "panel_nas") {
x_adj = pcb_width > 100 ? width-2*sidethick : 101.6+case_offset_x;
xtab_adj = pcb_width > 100 ? width-gap-2*sidethick-adj : 101.6-gap+case_offset_x-adj;
union() {
translate([-gap,-wallthick,case_z-2*floorthick])
cube([x_adj,depth-(2*wallthick),floorthick]);
translate([-gap-sidethick+(2*adj),depth-(3*wallthick)-gap-adj-20,
case_z-2*floorthick])
cube([sidethick+(2*adj),10,floorthick]);
translate([xtab_adj,depth-(3*wallthick)-gap-adj-20,
case_z-2*floorthick])
cube([sidethick+2*adj,10,floorthick]);
translate([-gap-sidethick+(2*adj),40-wallthick-gap+adj,
case_z-2*floorthick])
cube([sidethick+2*adj,10,floorthick]);
translate([xtab_adj,40-wallthick-gap+adj,
case_z-2*floorthick])
cube([sidethick+2*adj,10,floorthick]);
}
}
if(case_design == "stacked") {
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,
case_z-(floorthick/2)])
@@ -91,8 +111,8 @@ module case_top(case_design) {
bottom=[0,0,0,0], $fn=90);
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,(case_z/2)-floorthick+.25])
cube_fillet_inside([width+1,depth+(wallthick*2),case_z],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
top=[0,0,0,0],bottom=[0,0,0,0], $fn=90);
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,
corner_fillet-wallthick],top=[0,0,0,0],bottom=[0,0,0,0], $fn=90);
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
@@ -104,7 +124,8 @@ module case_top(case_design) {
pcbhole_pos = sbc_data[s[0]][i+10][4];
if(class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_rear") {
if((pcbhole_y <= 10 && pcbhole_x <= 10) || (ext_top_standoffs == true && ext_top_rear_left_enable == true)) {
if((pcbhole_y <= 10 && pcbhole_x <= 10) || (ext_top_standoffs == true &&
ext_top_rear_left_enable == true)) {
translate([-wallthick-gap-adj-6,wallthick+gap+10,floorthick+3.4]) rotate([0,90,0])
cylinder(d=3, h=10+sidethick+(2*adj));
}
@@ -114,7 +135,8 @@ module case_top(case_design) {
}
}
if(class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_front") {
if((pcbhole_y >= pcb_depth+case_offset_y-10 && pcbhole_x <= 10) || (ext_top_standoffs == true && ext_top_front_left_enable == true)) {
if((pcbhole_y >= pcb_depth+case_offset_y-10 && pcbhole_x <= 10) ||
(ext_top_standoffs == true && ext_top_front_left_enable == true)) {
translate([-wallthick-gap-adj-6,wallthick-gap+pcb_depth+case_offset_y-14,
floorthick+3.4]) rotate([0,90,0]) cylinder(d=3, h=10+sidethick+(2*adj));
}
@@ -124,7 +146,8 @@ module case_top(case_design) {
}
}
if(class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_rear") {
if((pcbhole_y <= 10 && pcbhole_x >= pcb_width-10) || (ext_top_standoffs == true && ext_top_rear_right_enable == true)) {
if((pcbhole_y <= 10 && pcbhole_x >= pcb_width-10) || (ext_top_standoffs == true &&
ext_top_rear_right_enable == true)) {
translate([width-2*(wallthick+gap)-sidethick-adj,wallthick+gap+10,floorthick+3.4])
rotate([0,90,0]) cylinder(d=3, h=10+sidethick+(2*adj));
}
@@ -134,7 +157,8 @@ module case_top(case_design) {
}
}
if(class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_front") {
if((pcbhole_y >= pcb_depth+case_offset_y-10 && pcbhole_x >= width-10) || (ext_bottom_standoffs == true && ext_bottom_front_right_enable == true)) {
if((pcbhole_y >= pcb_depth+case_offset_y-10 && pcbhole_x >= width-10) ||
(ext_bottom_standoffs == true && ext_bottom_front_right_enable == true)) {
translate([width-3*(wallthick+gap)-adj,wallthick-gap+pcb_depth+case_offset_y-14,
floorthick+3.4]) rotate([0,90,0]) cylinder(d=3, h=10+sidethick+(2*adj));
}
@@ -204,13 +228,13 @@ module case_top(case_design) {
}
else {
difference() {
translate([pcb_width/2,pcb_depth/2,bottom_height+(top_height/2)-lip/2]) rotate([0,0,0])
translate([pcb_width/2,pcb_depth/2,bottom_height+(top_height/2)-lip/2])
cylinder_fillet_inside(h=top_height+lip, r=hex_diameter/2,
top=edge_fillet, bottom=0, $fn=6, fillet_fn=case_ffn, center=true);
translate([pcb_width/2,pcb_depth/2,bottom_height+(top_height/2)-floorthick-lip/2])
rotate([0,0,0]) cylinder_fillet_inside(h=top_height+lip, r=(hex_diameter/2)-wallthick,
cylinder_fillet_inside(h=top_height+lip, r=(hex_diameter/2)-wallthick,
top=edge_fillet-1, bottom=0, $fn=6, fillet_fn=case_ffn, center=true);
translate([pcb_width/2,pcb_depth/2,bottom_height-adj-lip/2]) rotate([0,0,0])
translate([pcb_width/2,pcb_depth/2,bottom_height-adj-lip/2])
cylinder_fillet_inside(h=lip+2*adj, r=(hex_diameter/2)-wallthick/2+tol/2,
top=edge_fillet-1, bottom=0, $fn=6, fillet_fn=case_ffn, center=true);
// io cutout
@@ -243,21 +267,22 @@ module case_top(case_design) {
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,case_z-adj])
cube_fillet_inside([width-(3*wallthick),depth-(3*wallthick),2*floorthick+1.5+adj],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],top=[0,0,0,0],
bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,
corner_fillet-wallthick],top=[0,0,0,0],
bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
}
// snap top outdent
difference() {
translate([-wallthick-gap+1.25+tol,(depth/2)-((depth*.75)/2)+2.5-gap-wallthick,case_z-.5])
rotate([0,45,0]) cube([4,(depth*.75)-5,4]);
translate([-wallthick-gap+3,(depth/2)-((depth*.75)/2)+1.25-gap-wallthick,case_z+floorthick-5.75])
rotate([0,0,0]) cube([6,(depth*.75)-2,6]);
cube([6,(depth*.75)-2,6]);
}
difference() {
translate([width-wallthick-gap-6.8-tol,(depth/2)-((depth*.75)/2)+2.5-gap-wallthick,case_z-.5])
rotate([0,45,0]) cube([4,(depth*.75)-5,4]);
translate([width-wallthick-gap-8.5,(depth/2)-((depth*.75)/2)+1.25-gap-wallthick,case_z+floorthick-5.75])
rotate([0,0,0]) cube([6,(depth*.75)-2,6]);
translate([width-wallthick-gap-8.5,(depth/2)-((depth*.75)/2)+1.25-gap-wallthick,
case_z+floorthick-5.75]) cube([6,(depth*.75)-2,6]);
}
}
if(case_design == "fitted") {
@@ -270,7 +295,7 @@ module case_top(case_design) {
bottom=[0,0,0,0], $fn=90);
translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,case_z-floorthick-1])
cube_fillet_inside([width-wallthick+tol,depth-wallthick+tol,lip+floorthick],
vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
vertical=[corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick,corner_fillet-wallthick],
top=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet],
bottom=[0,0,0,0], $fn=90);
}
@@ -306,77 +331,194 @@ module case_top(case_design) {
pcbhole_z = sbc_data[s[0]][i+6];
pcbhole_size = sbc_data[s[0]][i+9][0];
pcbhole_pos = sbc_data[s[0]][i+10][4];
case_z = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? case_z+floorthick :
case_design == "snap" ? case_z+(2 * floorthick) :
case_design == "panel_nas" ? case_z-floorthick : case_z;
if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_rear" && top_rear_left_enable == true &&
top_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,top_height+5]) cylinder(d=top_standoff[4]-.2, h=top_height);
if (class == "pcbhole" && id == 0 && pcbhole_pos == "left_rear" &&
top_rear_left_enable == true && top_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,case_z-(floorthick+adj)])
cylinder(d=top_standoff[4]-.2, h=floorthick+(2*adj));
}
if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_front" && top_front_left_enable == true &&
top_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,top_height+5]) cylinder(d=top_standoff[4]-.2, h=top_height);
if (class == "pcbhole" && id == 0 && pcbhole_pos == "left_front" &&
top_front_left_enable == true && top_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,case_z-(floorthick+adj)])
cylinder(d=top_standoff[4]-.2, h=floorthick+(2*adj));
}
if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_rear" && top_rear_right_enable == true &&
top_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,top_height+5]) cylinder(d=top_standoff[4]-.2, h=top_height);
if (class == "pcbhole" && id == 0 && pcbhole_pos == "right_rear" &&
top_rear_right_enable == true && top_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,case_z-(floorthick+adj)])
cylinder(d=top_standoff[4]-.2, h=floorthick+(2*adj));
}
if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_front" && top_front_right_enable == true &&
top_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,top_height+5]) cylinder(d=top_standoff[4]-.2, h=top_height);
if (class == "pcbhole" && id == 0 && pcbhole_pos == "right_front" &&
top_front_right_enable == true && top_standoff[6] != "blind") {
translate([pcbhole_x,pcbhole_y,case_z-(floorthick+adj)])
cylinder(d=top_standoff[4]-.2, h=floorthick+(2*adj));
}
}
}
// multi-pcb standoff holes
if(multipcb_top_standoffs == true) {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
pcbid = sbc_data[s[0]][i+3];
pcbloc_x = sbc_data[s[0]][i+4];
pcbloc_y = sbc_data[s[0]][i+5];
pcbloc_z = sbc_data[s[0]][i+6];
if(class == "pcb") {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
pcbclass = sbc_data[s[0]][i+1];
pcbtype = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
pcbhole_x = sbc_data[s[0]][i+4]+pcb_loc_x+pcbloc_x;
pcbhole_y = sbc_data[s[0]][i+5]+pcb_loc_y+pcbloc_y;
pcbhole_z = sbc_data[s[0]][i+6];
pcbhole_size = sbc_data[s[0]][i+9][0];
pcbhole_state = sbc_data[s[0]][i+10][0];
pcbhole_pos = sbc_data[s[0]][i+10][4];
case_z = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? case_z+floorthick :
case_design == "snap" ? case_z+(2 * floorthick) :
case_design == "panel_nas" ? case_z-floorthick : case_z;
if(id == pcbid && id != 0 && pcbclass == "pcbhole") {
if (pcbclass == "pcbhole" && pcbhole_pos == "left_rear" &&
multipcb_top_rear_left_enable == true &&
(pcbhole_state == "top" || pcbhole_state == "both")) {
translate([pcbhole_x,pcbhole_y,case_z-(floorthick+adj)])
cylinder(d=multipcb_top_standoff[4]-.2, h=floorthick+(2*adj));
}
if (pcbclass == "pcbhole" && pcbhole_pos == "left_front" &&
multipcb_top_front_left_enable == true &&
(pcbhole_state == "top" || pcbhole_state == "both")) {
translate([pcbhole_x,pcbhole_y,case_z-(floorthick+adj)])
cylinder(d=multipcb_top_standoff[4]-.2, h=floorthick+(2*adj));
}
if (pcbclass == "pcbhole" && pcbhole_pos == "right_rear" &&
multipcb_top_rear_right_enable == true &&
(pcbhole_state == "top" || pcbhole_state == "both")) {
translate([pcbhole_x,pcbhole_y,case_z-(floorthick+adj)])
cylinder(d=multipcb_top_standoff[4]-.2, h=floorthick+(2*adj));
}
if (pcbclass == "pcbhole" && pcbhole_pos == "right_front" &&
multipcb_top_front_right_enable == true &&
(pcbhole_state == "top" || pcbhole_state == "both")) {
translate([pcbhole_x,pcbhole_y,case_z-(floorthick+adj)])
cylinder(d=multipcb_top_standoff[4]-.2, h=floorthick+(2*adj));
}
}
}
}
}
}
// extended standoff holes
if(ext_top_standoffs == true) {
case_z = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? case_z+floorthick :
case_design == "snap" ? case_z+(2 * floorthick) :
case_design == "panel_nas" ? case_z-floorthick : case_z;
// right-rear standoff
if((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 || pcb_loc_y >= 10) &&
if((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_top_standoff_support_size ||
pcb_loc_y >= ext_top_standoff_support_size) &&
ext_top_rear_right_enable == true && ext_top_standoff[6] != "blind") {
translate([width-ext_top_standoff_support_size/4-(2*(wallthick+gap))-(corner_fillet/2),
(corner_fillet/2)+ext_top_standoff_support_size/4,top_height+5]) cylinder(d=ext_top_standoff[4]-.2, h=top_height);
translate([width-ext_top_standoff_support_size/4-(2*(wallthick+gap)),
ext_top_standoff_support_size/4,case_z-(floorthick+adj)])
cylinder(d=ext_top_standoff[4]-.2, h=floorthick+(2*adj));
}
// right-front standoff
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth >= 10) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth <= 10) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= 10 && depth-pcb_loc_y-pcb_depth >= 10)) &&
ext_top_front_right_enable == true && ext_top_standoff[6] != "blind") {
translate([width-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),
depth-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),top_height+5])
cylinder(d=ext_top_standoff[4]-.2, h=top_height);
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_top_standoff_support_size &&
depth-pcb_loc_y-pcb_depth >= ext_top_standoff_support_size) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_top_standoff_support_size &&
depth-pcb_loc_y-pcb_depth <= ext_top_standoff_support_size) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= ext_top_standoff_support_size &&
depth-pcb_loc_y-pcb_depth >= ext_top_standoff_support_size)) &&
ext_top_front_right_enable == true && ext_top_standoff[6] != "blind") {
translate([width-ext_top_standoff_support_size/4-(2*(wallthick+gap)),
depth-ext_top_standoff_support_size/4-(2*(wallthick+gap)),case_z-(floorthick+adj)])
cylinder(d=ext_top_standoff[4]-.2, h=floorthick+(2*adj));
}
// left-rear standoff
if((pcb_loc_x >= 10 || pcb_loc_y >= 10) && ext_top_rear_left_enable == true && ext_top_standoff[6] != "blind") {
translate([(corner_fillet/2)+ext_top_standoff_support_size/4,
(corner_fillet/2)+ext_top_standoff_support_size/4,top_height+5]) cylinder(d=ext_top_standoff[4]-.2, h=top_height);
if((pcb_loc_x >= ext_top_standoff_support_size || pcb_loc_y >= ext_top_standoff_support_size) &&
ext_top_rear_left_enable == true && ext_top_standoff[6] != "blind") {
translate([ext_top_standoff_support_size/4, ext_top_standoff_support_size/4,case_z-(floorthick+adj)])
cylinder(d=ext_top_standoff[4]-.2, h=floorthick+(2*adj));
}
// left-front standoff
if(((pcb_loc_x >= 10 && (depth-(pcb_loc_y+pcb_depth)) >= 10) ||
(pcb_loc_x <= 10 && (depth-(pcb_loc_y+pcb_depth)) >= 10) ||
(pcb_loc_x >= 10 && (depth-(pcb_loc_y+pcb_depth)) <= 10)) &&
ext_top_front_left_enable == true && ext_top_standoff[6] != "blind") {
translate([+(corner_fillet/2)+ext_top_standoff_support_size/4,
depth-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),top_height+5])
cylinder(d=ext_top_standoff[4]-.2, h=top_height);
if(((pcb_loc_x >= ext_top_standoff_support_size &&
(depth-(pcb_loc_y+pcb_depth)) >= ext_top_standoff_support_size) ||
(pcb_loc_x <= ext_top_standoff_support_size &&
(depth-(pcb_loc_y+pcb_depth)) >= ext_top_standoff_support_size) ||
(pcb_loc_x >= ext_top_standoff_support_size &&
(depth-(pcb_loc_y+pcb_depth)) <= ext_top_standoff_support_size)) &&
ext_top_front_left_enable == true && ext_top_standoff[6] != "blind") {
translate([ext_top_standoff_support_size/4,
depth-ext_top_standoff_support_size/4-(2*(wallthick+gap)),case_z-(floorthick+adj)])
cylinder(d=ext_top_standoff[4]-.2, h=floorthick+(2*adj));
}
}
// top cover pattern
if(top_cover_pattern != "solid") {
xvent8_adj = pcb_width > 100 ? width/5.5 : width/6;
if(top_cover_pattern == "hex_5mm") {
translate([1,0,case_z-2]) vent_hex((width)/3.75,(depth)/6,floorthick+4,5,1.5,"horizontal");
if(case_design == "panel_nas") {
translate([6,5,case_z-(2*floorthick)])
vent_hex((width-10)/3.75,(depth-10)/7,floorthick+4,5,1.5,"horizontal");
}
else {
translate([1,0,case_z-(2*floorthick)]) vent_hex(width/3.75,depth/6,floorthick+4,5,1.5,"horizontal");
}
}
if(top_cover_pattern == "hex_8mm") {
translate([1,2,case_z-2]) vent_hex((width)/5.5,(depth)/9.5,floorthick+4,8,1.5,"horizontal");
if(top_cover_pattern == "hex_8mm") {
if(case_design == "panel_nas") {
translate([-gap+5,6,case_z-(2*floorthick)]) vent_hex(xvent8_adj,depth/9.5,floorthick+4,8,1.5,"horizontal");
}
else {
translate([1,2,case_z-(2*floorthick)]) vent_hex(width/5.5,depth/9.5,floorthick+4,8,1.5,"horizontal");
}
}
if(top_cover_pattern == "linear_vertical") {
translate([0,-gap,case_z-2]) vent(wallthick,depth-2*wallthick-gap,floorthick+4,1,1,(width-2*wallthick-gap)/4,"horizontal");
if(case_design == "panel_nas") {
translate([wallthick+gap,wallthick,case_z-(2*floorthick)])
vent(wallthick,depth-6*wallthick-gap,floorthick+4,1,1,(width-2*(sidethick+gap))/5.35,"horizontal");
}
else {
translate([0,-gap,case_z-(2*floorthick)])
vent(wallthick,depth-2*wallthick-gap,floorthick+4,1,1,(width-2*wallthick-gap)/4,"horizontal");
}
}
if(top_cover_pattern == "linear_horizontal") {
translate([-gap,-gap,case_z-2]) vent(width-2*wallthick-gap,wallthick,floorthick+4,1,(depth-2*wallthick-gap)/3,1,"horizontal");
if(case_design == "panel_nas") {
translate([wallthick+gap,wallthick,case_z-(2*floorthick)])
vent(width-4*(sidethick+gap),wallthick,floorthick+4,1,
(depth-2*(wallthick-gap))/4.35,1,"horizontal");
}
else {
translate([-gap,-gap,case_z-(2*floorthick)])
vent(width-2*wallthick-gap,wallthick,floorthick+4,1,(depth-2*wallthick-gap)/3,1,"horizontal");
}
}
if(top_cover_pattern == "astroid") {
for(c=[3:12:depth-8]) {
for(r=[4:12:width-8]) {
translate([r,c,case_z-4]) linear_extrude(floorthick+5) import("./dxf/astroid_8mm.dxf");
xast_adj = pcb_width <= 100 ? 8 : 6;
if(case_design == "panel_nas") {
for(c=[xast_adj:12:depth-16]) {
for(r=[8:12:width-16]) {
translate([r,c,case_z-(2*floorthick)-adj])
linear_extrude(floorthick+5) import("./dxf/astroid_8mm.dxf");
}
}
}
}
else {
for(c=[3:12:depth-8]) {
for(r=[4:12:width-8]) {
translate([r,c,case_z-(2*floorthick)-adj])
linear_extrude(floorthick+5) import("./dxf/astroid_8mm.dxf");
}
}
}
}
}
// rear io shield opening for standard form motherboards
@@ -406,13 +548,22 @@ module case_top(case_design) {
pcbhole_z = sbc_data[s[0]][i+6];
pcbhole_size = sbc_data[s[0]][i+9][0];
pcbhole_pos = sbc_data[s[0]][i+10][4];
case_z = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? case_z+floorthick :
case_design == "snap" ? case_z+(2 * floorthick) :
case_design == "panel_nas" ? case_z-floorthick : case_z;
stand_off_adj = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? floorthick :
case_design == "snap" ? 2 * floorthick : 0;
if(class == "pcbhole" && id == pcb_id &&
(pcbhole_pos == "left_rear" || pcbhole_pos == "left_front" || pcbhole_pos == "right_rear" || pcbhole_pos == "right_front")) {
(pcbhole_pos == "left_rear" || pcbhole_pos == "left_front" ||
pcbhole_pos == "right_rear" || pcbhole_pos == "right_front")) {
if (pcbhole_pos == "left_rear" && top_rear_left_enable == true) {
top_support = top_sidewall_support == true ? top_rear_left_support : "none";
pcb_standoff = [top_standoff[0],
top_standoff[1],
top_height+top_rear_left_adjust-pcb_loc_z,
top_height+top_rear_left_adjust-pcb_loc_z+stand_off_adj,
top_standoff[3],
top_standoff[4],
top_standoff[5],
@@ -429,7 +580,7 @@ module case_top(case_design) {
top_support = top_sidewall_support == true ? top_front_left_support : "none";
pcb_standoff = [top_standoff[0],
top_standoff[1],
top_height+top_front_left_adjust-pcb_loc_z,
top_height+top_front_left_adjust-pcb_loc_z+stand_off_adj,
top_standoff[3],
top_standoff[4],
top_standoff[5],
@@ -446,7 +597,7 @@ module case_top(case_design) {
top_support = top_sidewall_support == true ? top_rear_right_support : "none";
pcb_standoff = [top_standoff[0],
top_standoff[1],
top_height+top_rear_right_adjust-pcb_loc_z,
top_height+top_rear_right_adjust-pcb_loc_z+stand_off_adj,
top_standoff[3],
top_standoff[4],
top_standoff[5],
@@ -463,7 +614,7 @@ module case_top(case_design) {
top_support = top_sidewall_support == true ? top_front_right_support : "none";
pcb_standoff = [top_standoff[0],
top_standoff[1],
top_height+top_front_right_adjust-pcb_loc_z,
top_height+top_front_right_adjust-pcb_loc_z+stand_off_adj,
top_standoff[3],
top_standoff[4],
top_standoff[5],
@@ -479,13 +630,129 @@ module case_top(case_design) {
}
}
}
// multi-pcb standoffs
if(multipcb_top_standoffs == true) {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
pcbid = sbc_data[s[0]][i+3];
pcbloc_x = sbc_data[s[0]][i+4];
pcbloc_y = sbc_data[s[0]][i+5];
pcbloc_z = sbc_data[s[0]][i+6];
if(class == "pcb") {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
pcbclass = sbc_data[s[0]][i+1];
pcbtype = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
pcbhole_x = sbc_data[s[0]][i+4]+pcb_loc_x+pcbloc_x;
pcbhole_y = sbc_data[s[0]][i+5]+pcb_loc_y+pcbloc_y;
pcbhole_z = sbc_data[s[0]][i+6];
pcbhole_size = sbc_data[s[0]][i+9][0];
pcbhole_state = sbc_data[s[0]][i+10][0];
pcbhole_pos = sbc_data[s[0]][i+10][4];
case_z = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? case_z+floorthick :
case_design == "snap" ? case_z+(2 * floorthick) :
case_design == "panel_nas" ? case_z-floorthick : case_z;
stand_off_adj = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? floorthick :
case_design == "snap" ? 2 * floorthick : 0;
if(pcbclass == "pcbhole" && pcbid == id && id != 0) {
if (pcbhole_pos == "left_rear" && multipcb_top_rear_left_enable == true &&
(pcbhole_state == "top" || pcbhole_state == "both")) {
top_support = multipcb_top_sidewall_support == true ? multipcb_top_rear_left_support : "none";
pcb_standoff = [multipcb_top_standoff[0],
multipcb_top_standoff[1],
top_height+top_rear_right_adjust-pcb_loc_z+stand_off_adj,
multipcb_top_standoff[3],
multipcb_top_standoff[4],
multipcb_top_standoff[5],
multipcb_top_standoff[6],
multipcb_top_standoff[7],
top_support,
multipcb_top_standoff[9],
multipcb_top_standoff[10],
multipcb_top_standoff[11],
multipcb_top_standoff[12]];
translate([pcbhole_x,pcbhole_y,case_z]) standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "left_front" && multipcb_top_front_left_enable == true &&
(pcbhole_state == "top" || pcbhole_state == "both")) {
top_support = multipcb_top_sidewall_support == true ? multipcb_top_front_left_support : "none";
pcb_standoff = [multipcb_top_standoff[0],
multipcb_top_standoff[1],
top_height+top_rear_right_adjust-pcb_loc_z+stand_off_adj,
multipcb_top_standoff[3],
multipcb_top_standoff[4],
multipcb_top_standoff[5],
multipcb_top_standoff[6],
multipcb_top_standoff[7],
top_support,
multipcb_top_standoff[9],
multipcb_top_standoff[10],
multipcb_top_standoff[11],
multipcb_top_standoff[12]];
translate([pcbhole_x,pcbhole_y,case_z]) standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "right_rear" && multipcb_top_rear_right_enable == true &&
(pcbhole_state == "top" || pcbhole_state == "both")) {
top_support = multipcb_top_sidewall_support == true ? multipcb_top_rear_right_support : "none";
pcb_standoff = [multipcb_top_standoff[0],
multipcb_top_standoff[1],
top_height+top_rear_right_adjust-pcb_loc_z+stand_off_adj,
multipcb_top_standoff[3],
multipcb_top_standoff[4],
multipcb_top_standoff[5],
multipcb_top_standoff[6],
multipcb_top_standoff[7],
top_support,
multipcb_top_standoff[9],
multipcb_top_standoff[10],
multipcb_top_standoff[11],
multipcb_top_standoff[12]];
translate([pcbhole_x,pcbhole_y,case_z]) standoff(pcb_standoff,[false,10,2,"default"]);
}
if (pcbhole_pos == "right_front" && multipcb_top_front_right_enable == true &&
(pcbhole_state == "top" || pcbhole_state == "both")) {
top_support = multipcb_top_sidewall_support == true ? multipcb_top_front_right_support : "none";
pcb_standoff = [multipcb_top_standoff[0],
multipcb_top_standoff[1],
top_height+top_rear_right_adjust-pcb_loc_z+stand_off_adj,
multipcb_top_standoff[3],
multipcb_top_standoff[4],
multipcb_top_standoff[5],
multipcb_top_standoff[6],
multipcb_top_standoff[7],
top_support,
multipcb_top_standoff[9],
multipcb_top_standoff[10],
multipcb_top_standoff[11],
multipcb_top_standoff[12]];
translate([pcbhole_x,pcbhole_y,case_z]) standoff(pcb_standoff,[false,10,2,"default"]);
}
}
}
}
}
}
// extended standoffs
if(ext_top_standoffs == true) {
case_z = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? case_z+floorthick :
case_design == "snap" ? case_z+(2 * floorthick) :
case_design == "panel_nas" ? case_z-floorthick : case_z;
stand_off_adj = case_design == "fitted" || case_design == "tray_sides" ||
case_design == "tray_vu5" || case_design == "tray_vu7" ? floorthick :
case_design == "snap" ? 2 * floorthick : 0;
// extended right-rear standoff
if((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 || pcb_loc_y >= 10) && ext_top_rear_right_enable == true) {
if((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_top_standoff_support_size ||
pcb_loc_y >= ext_top_standoff_support_size) && ext_top_rear_right_enable == true) {
extended_standoff = [ext_top_standoff[0],
ext_top_standoff[1],
top_height+ext_top_rear_right_adjust,
top_height+ext_top_rear_right_adjust+stand_off_adj,
ext_top_standoff[3],
ext_top_standoff[4],
ext_top_standoff[5],
@@ -496,17 +763,20 @@ module case_top(case_design) {
ext_top_standoff[10],
ext_top_standoff[11],
ext_top_standoff[12]];
translate([width-ext_top_standoff_support_size/4-(2*(wallthick+gap))-(corner_fillet/2),
(corner_fillet/2)+ext_top_standoff_support_size/4,case_z]) standoff(extended_standoff,[false,10,2,"default"]);
translate([width-ext_top_standoff_support_size/4-(2*(wallthick+gap)),
ext_top_standoff_support_size/4,case_z]) standoff(extended_standoff,[false,10,2,"default"]);
}
// extended right-front standoff
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth >= 10) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth <= 10) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= 10 && depth-pcb_loc_y-pcb_depth >= 10)) &&
ext_top_front_right_enable == true) {
if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_top_standoff_support_size &&
depth-pcb_loc_y-pcb_depth >= ext_top_standoff_support_size) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= ext_top_standoff_support_size &&
depth-pcb_loc_y-pcb_depth <= ext_top_standoff_support_size) ||
(width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= ext_top_standoff_support_size &&
depth-pcb_loc_y-pcb_depth >= ext_top_standoff_support_size)) &&
ext_top_front_right_enable == true) {
extended_standoff = [ext_top_standoff[0],
ext_top_standoff[1],
top_height+ext_top_front_right_adjust,
top_height+ext_top_front_right_adjust+stand_off_adj,
ext_top_standoff[3],
ext_top_standoff[4],
ext_top_standoff[5],
@@ -517,36 +787,40 @@ module case_top(case_design) {
ext_top_standoff[10],
ext_top_standoff[11],
ext_top_standoff[12]];
translate([width-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),
depth-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),case_z])
standoff(extended_standoff,[false,10,2,"default"]);
translate([width-ext_top_standoff_support_size/4-(2*(wallthick+gap)),
depth-ext_top_standoff_support_size/4-(2*(wallthick+gap)),case_z])
standoff(extended_standoff,[false,10,2,"default"]);
}
// extended left-rear standoff
if((pcb_loc_x >= 10 || pcb_loc_y >= 10) && ext_top_rear_left_enable == true) {
extended_standoff = [ext_top_standoff[0],
ext_top_standoff[1],
top_height+ext_top_rear_left_adjust,
ext_top_standoff[3],
ext_top_standoff[4],
ext_top_standoff[5],
ext_top_standoff[6],
ext_top_standoff[7],
ext_top_rear_left_support,
ext_top_standoff[9],
ext_top_standoff[10],
ext_top_standoff[11],
ext_top_standoff[12]];
translate([(corner_fillet/2)+ext_top_standoff_support_size/4,
(corner_fillet/2)+ext_top_standoff_support_size/4,case_z]) standoff(extended_standoff,[false,10,2,"default"]);
if((pcb_loc_x >= ext_top_standoff_support_size || pcb_loc_y >= ext_top_standoff_support_size) &&
ext_top_rear_left_enable == true) {
extended_standoff = [ext_top_standoff[0],
ext_top_standoff[1],
top_height+ext_top_rear_left_adjust+stand_off_adj,
ext_top_standoff[3],
ext_top_standoff[4],
ext_top_standoff[5],
ext_top_standoff[6],
ext_top_standoff[7],
ext_top_rear_left_support,
ext_top_standoff[9],
ext_top_standoff[10],
ext_top_standoff[11],
ext_top_standoff[12]];
translate([ext_top_standoff_support_size/4,
ext_top_standoff_support_size/4,case_z]) standoff(extended_standoff,[false,10,2,"default"]);
}
// extended left-front standoff
if(((pcb_loc_x >= 10 && (depth-(pcb_loc_y+pcb_depth)) >= 10) ||
(pcb_loc_x <= 10 && (depth-(pcb_loc_y+pcb_depth)) >= 10) ||
(pcb_loc_x >= 10 && depth-(pcb_loc_y+pcb_depth) <= 10)) &&
ext_top_front_left_enable == true) {
if(((pcb_loc_x >= ext_top_standoff_support_size &&
(depth-(pcb_loc_y+pcb_depth)) >= ext_top_standoff_support_size) ||
(pcb_loc_x <= ext_top_standoff_support_size &&
(depth-(pcb_loc_y+pcb_depth)) >= ext_top_standoff_support_size) ||
(pcb_loc_x >= ext_top_standoff_support_size &&
depth-(pcb_loc_y+pcb_depth) <= ext_top_standoff_support_size)) &&
ext_top_front_left_enable == true) {
extended_standoff = [ext_top_standoff[0],
ext_top_standoff[1],
top_height+ext_top_front_left_adjust,
top_height+ext_top_front_left_adjust+stand_off_adj,
ext_top_standoff[3],
ext_top_standoff[4],
ext_top_standoff[5],
@@ -557,8 +831,8 @@ module case_top(case_design) {
ext_top_standoff[10],
ext_top_standoff[11],
ext_top_standoff[12]];
translate([(corner_fillet/2)+ext_top_standoff_support_size/4,
depth-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)), case_z])
translate([ext_top_standoff_support_size/4,
depth-ext_top_standoff_support_size/4-(2*(wallthick+gap)), case_z])
standoff(extended_standoff,[false,10,2,"default"]);
}
}
@@ -594,38 +868,75 @@ module case_top(case_design) {
// create openings for additive
if((class == "add1" || class == "add2" || class == "model") && mask[0] == true) {
if(accessory_highlight == false) {
parametric_move_add(type,loc_x,loc_y,loc_z,face,rotation,parametric,[size_x,size_y,size_z],data,mask);
parametric_move_add(type,loc_x,loc_y,loc_z,face,rotation,
parametric,[size_x,size_y,size_z],data,mask);
}
else {
#parametric_move_add(type,loc_x,loc_y,loc_z,face,rotation,parametric,[size_x,size_y,size_z],data,mask);
#parametric_move_add(type,loc_x,loc_y,loc_z,face,rotation,
parametric,[size_x,size_y,size_z],data,mask);
}
}
}
}
// sbc openings
if(sbc_highlight == true) {
#translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
if(case_design != "panel_nas") {
if(sbc_highlight == true) {
#translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
else {
translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
}
else {
translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
if(nas_sbc_location == "top") {
if(sbc_highlight == true) {
#translate([pcb_loc_x ,pcb_loc_y,case_z-(top_height+pcb_loc_z+(2*floorthick))])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
else {
translate([pcb_loc_x ,pcb_loc_y,case_z-(top_height+pcb_loc_z+(2*floorthick))])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
}
if(nas_sbc_location == "bottom") {
if(sbc_highlight == true) {
#translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
else {
translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z])
sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
}
}
}
// indents
if(indents == true) {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
loc_x = sbc_data[s[0]][i+4]+pcb_loc_x;
loc_y = sbc_data[s[0]][i+5]+pcb_loc_y;
loc_z = sbc_data[s[0]][i+6]+pcb_loc_z;
side = sbc_data[s[0]][i+7];
rotation = sbc_data[s[0]][i+8];
indent(loc_x, loc_y, bottom_height+pcb_loc_z-adj, rotation[2], side, class, type, wallthick, gap, floorthick, pcb_z);
}
pcbid = sbc_data[s[0]][i+3];
pcbloc_x = sbc_data[s[0]][i+4];
pcbloc_y = sbc_data[s[0]][i+5];
pcbloc_z = sbc_data[s[0]][i+6];
if(class == "pcb") {
for (i=[1:11:len(sbc_data[s[0]])-2]) {
class = sbc_data[s[0]][i+1];
type = sbc_data[s[0]][i+2];
id = sbc_data[s[0]][i+3];
loc_x = sbc_data[s[0]][i+4]+pcb_loc_x+pcbloc_x;
loc_y = sbc_data[s[0]][i+5]+pcb_loc_y+pcbloc_y;
loc_z = sbc_data[s[0]][i+6]+pcb_loc_z+pcbloc_z;
side = sbc_data[s[0]][i+7];
rotation = sbc_data[s[0]][i+8];
if(id == pcbid) {
indent(loc_x, loc_y, bottom_height+loc_z-adj, rotation[2],
side, class, type, wallthick, gap, floorthick, pcb_z);
}
}
}
}
}
// clean fillets
if(case_design == "shell") {
@@ -653,7 +964,8 @@ module case_top(case_design) {
mask = accessory_data[a[0]][i+10];
if (class == "add2" && face == "top") {
parametric_move_add(type,loc_x,loc_y,loc_z,face,rotation,parametric,size,data,[false,mask[1],mask[2],mask[3]]);
parametric_move_add(type,loc_x,loc_y,loc_z,face,rotation,
parametric,size,data,[false,mask[1],mask[2],mask[3]]);
}
}
}

View File

@@ -64,7 +64,7 @@ module indent(loc_x, loc_y, loc_z, rotation, side, class, type, wallthick, gap,
}
// hdmi micro indent
if(class == "video" && type == "hdmi_micro" && rotation == 0 && side == "top") {
place(loc_x-.5,-(wallthick+gap)+wallthick/2,loc_z+1.5,6,8,rotation,side)
place(loc_x-.75,-(wallthick+gap)+wallthick/2,loc_z+1.5,6,8,rotation,side)
rotate([90,0,0]) long_slot(6,8,wallthick);
}
if(class == "video" && type == "hdmi_micro" && rotation == 90 && side == "top") {
@@ -150,19 +150,19 @@ module indent(loc_x, loc_y, loc_z, rotation, side, class, type, wallthick, gap,
}
if(class == "power" && type == "pwr2.5_5x7.5" && rotation == 0 && side == "top") {
place(loc_x+2.75,-(wallthick+gap)+wallthick/2,loc_z+2.1,7,7,rotation,side)
rotate([90,0,0]) cylinder(d=7, h=wallthick);
rotate([90,0,0]) cylinder(d=9, h=wallthick);
}
if(class == "power" && type == "pwr2.5_5x7.5" && rotation == 90 && side == "top") {
place(-(wallthick+gap)+wallthick/2,loc_y-4.5,loc_z+2,7,7,rotation,side)
rotate([90,0,0]) cylinder(d=7, h=wallthick);
rotate([90,0,0]) cylinder(d=9, h=wallthick);
}
if(class == "power" && type == "pwr2.5_5x7.5" && rotation == 180 && side == "top") {
place(loc_x-4.5,depth-(wallthick+gap)-7-wallthick/2,loc_z+2,7,7,rotation,side)
rotate([90,0,0]) cylinder(d=7, h=wallthick);
rotate([90,0,0]) cylinder(d=9, h=wallthick);
}
if(class == "power" && type == "pwr2.5_5x7.5" && rotation == 270 && side == "top") {
place(width-(wallthick+gap)-7-wallthick/2,loc_y+2.5,loc_z+2,7,7,rotation,side)
rotate([90,0,0]) cylinder(d=7, h=wallthick);
rotate([90,0,0]) cylinder(d=9, h=wallthick);
}
// micro usb indent
if(class == "usb2" && type == "micro" && rotation == 0 && side == "top") {
@@ -209,7 +209,7 @@ module indent(loc_x, loc_y, loc_z, rotation, side, class, type, wallthick, gap,
rotate([90,0,0]) long_slot(6,8,wallthick);
}
if(class == "usbc" && type == "single_horizontal" && rotation == 180 && side == "top") {
place(loc_x+2.5,depth-(wallthick+gap)-8-wallthick/2,loc_z+2,6,8,rotation,side)
place(loc_x+2.5,depth-(wallthick+gap)-8-wallthick/2,loc_z+1.875,6,8,rotation,side)
rotate([90,0,0]) long_slot(6,8,wallthick);
}
if(class == "usbc" && type == "single_horizontal" && rotation == 270 && side == "top") {
@@ -234,7 +234,7 @@ module indent(loc_x, loc_y, loc_z, rotation, side, class, type, wallthick, gap,
}
// audio jack indent
if(class == "audio" && type == "jack_3.5" && rotation == 0 && side == "top") {
place(loc_x+3.15,-(wallthick+gap)+wallthick/2,loc_z+2,8,8,rotation,side)
place(loc_x+3.25,-(wallthick+gap)+wallthick/2,loc_z+2.75,8,8,rotation,side)
rotate([90,0,0]) cylinder(d=10, h=wallthick);
}
if(class == "audio" && type == "jack_3.5" && rotation == 90 && side == "top") {
@@ -242,11 +242,11 @@ module indent(loc_x, loc_y, loc_z, rotation, side, class, type, wallthick, gap,
rotate([90,0,0]) cylinder(d=10, h=wallthick);
}
if(class == "audio" && type == "jack_3.5" && rotation == 180 && side == "top") {
place(loc_x-4.6,depth-(wallthick+gap)-8-wallthick/2,loc_z+2,8,8,rotation,side)
place(loc_x-5.5,depth-(wallthick+gap)-8-wallthick/2,loc_z+2,8,8,rotation,side)
rotate([90,0,0]) cylinder(d=10, h=wallthick);
}
if(class == "audio" && type == "jack_3.5" && rotation == 270 && side == "top") {
place(width-(wallthick+gap)-8-wallthick/2,loc_y+3.15,loc_z+2,8,8,rotation,side)
place(width-(wallthick+gap)-8-wallthick/2,loc_y+3.25,loc_z+2.5,8,8,rotation,side)
rotate([90,0,0]) cylinder(d=10, h=wallthick);
}
if(class == "audio" && type == "jack_3.5" && rotation == 0 && side == "bottom") {

View File

@@ -55,7 +55,7 @@ module sub(type, loc_x, loc_y, loc_z, face, rotation, size, data, mask) {
translate([loc_x,loc_y,loc_z]) rotate(rotation) fan_mask(size_x, size_z, data[0]);
}
if(type == "hd_holes") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) hd_bottom_holes(data[0],data[1],data[2],data[3]);
translate([loc_x,loc_y,loc_z]) rotate(rotation) hd_bottom_holes(data[0],data[1],data[2],data[3],data[4]);
}
if(type == "knockout") {
translate([loc_x,loc_y,loc_z]) rotate(rotation) knockout(size_x,size_y,data[0],size_z,data[1],data[2]);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -33,7 +33,8 @@
hk_boom_grill,hk_boom_speaker_holder,hk_boom_vring,hk_h3_port_extender_holder,hk_hc4_oled_holder,hk_uart_holder,
hk_uart_strap,keyhole,nut_holder,pcb_holder,rectangle,round,slot,sphere,standoff,text,vent_panel_hex
types for subtractive: art,fan_mask,hd_holes,knockout,rectangle,round,slot,sphere,text,vent,vent_hex
types for model: adafruit_lcd,dsub,fan,hd25,hd35,hk_boom,hk_boom_speaker,hk_h3_port_extender,hk_hc4_oled,hk_lcd35,hk_m1s_ups,hk_netcard,
types for model: adafruit_2030_powerboost,adafruit_4311_lcd,adafruit_4755_solar_charger,dsub,fan,hd25,hd35,hk_boom,
hk_boom_speaker,hk_h3_port_extender,hk_hc4_oled,hk_lcd35,hk_m1s_ups,hk_netcard,
hk_pwr_button,hk_speaker,hk_uart,hk_vu7c,hk_vu8m,hk_vu8s,hk_wb2,hk_xu4_shifter_shield,stl_model
types for platter: access_cover,button_assembly,fan_cover,feet,hk_boom_speaker_holder,hk_boom_vring,hk_h3_port_extender_holder,hk_uart_strap,vent_panel_hex
@@ -118,19 +119,19 @@ accessory_data = [
"sub","round",-3.75,54,-32,"left",[0,90,0],["case",false,false,false],[60,0,3],[0],[false,10,2,"default"],
"sub","round",126.4,54,-32,"right",[0,90,0],["case",false,false,false],[60,0,3],[0],[false,10,2,"default"],
"sub","vent",-3,22,13,"left",[0,0,90],["case",false,false,false],[2,10,5],[1,8,"vertical",1],[false,10,2,"default"],
"add2","button",89.875,45,27,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,2],["cutout",[2,2,2,2],2.25],[true,10,2,"default"],
"add2","button",89.875,34,27,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,2],["cutout",[2,2,2,2],2.25],[true,10,2,"default"],
"add2","button",89.875,23,27,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,2],["cutout",[2,2,2,2],2.25],[true,10,2,"default"],
"add2","button",89.875,12,27,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,2],["cutout",[2,2,2,2],2.25],[true,10,2,"default"],
"add2","button",100.875,45,31,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,2],["cutout",[2,2,2,2],2.25],[true,10,2,"default"],
"add2","button",100.875,34,31,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,2],["cutout",[2,2,2,2],2.25],[true,10,2,"default"],
"add2","button",100.875,23,31,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,2],["cutout",[2,2,2,2],2.25],[true,10,2,"default"],
"add2","button",100.875,12,31,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,2],["cutout",[2,2,2,2],2.25],[true,10,2,"default"],
"add2","pcb_holder",.75,66.1,1.99,"bottom",[0,0,0],["case",false,false,false],[123.5,35,1.6],[2],[false,10,2,"default"],
"add2","hk_boom_grill",16.5,72.5,21.5,"front",[90,0,180],["case",false,false,false],[0,0,2],["flat"],[false,10,2,"default"],
"add2","hk_boom_grill",108,72.5,21.5,"front",[90,0,180],["case",false,false,false],[0,0,2],["flat"],[false,10,2,"default"],
"add2","hk_boom_grill",16.5,72.5,21.5,"front",[90,0,180],["case",false,false,false],[0,0,2],["flat"],[true,10,2,"default"],
"add2","hk_boom_grill",108,72.5,21.5,"front",[90,0,180],["case",false,false,false],[0,0,2],["flat"],[true,10,2,"default"],
"add2","hk_uart_holder",10,0,1.9,"bottom",[0,0,0],["case",false,false,false],[10,10,0],[0],[true,10,2,"default"],
"model","hk_uart",12.5,22,5,"bottom",[0,0,270],["case",false,false,false],[10,10,0],[0],[false,10,2,"default"],
"model","hk_uart_strap",25,15,5,"bottom",[0,0,90],["case",false,false,false],[0,0,0],[0],[false,10,2,"default"],
// "model","hk_boom",32.25,68,4,"bottom",[90,0,0],["case",false,false,false],[0,0,0],[true,"front"],[true,10,2,"default"],
"model","hk_boom",32.25,68,4,"bottom",[90,0,0],["case",false,false,false],[0,0,0],[true,"front"],[true,10,2,"default"],
"model","hk_boom_vring",76.75,64.5,31,"bottom",[90,0,0],["case",false,false,false],[0,0,0],[0],[false,10,2,"default"],
"model","hk_lcd35",106.25,55,22.5,"bottom",[0,0,180],["sbc",false,false,true],[0,0,0],[0],[true,10,2,"default"],
"model","hk_lcd35",106.25,55,18.5,"bottom",[0,0,180],["sbc",false,false,true],[0,0,0],[0],[true,10,2,"default"],
"platter","hk_uart_strap",-35,75,-9,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[0],[false,10,2,"default"],
"platter","hk_boom_vring",-60,100,0,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[0],[false,10,2,"default"]],
@@ -177,11 +178,27 @@ accessory_data = [
"suball","round",10.5,-2,14.5,"top",[90,0,0],["case",false,false,false],[11,0,18],[0],[false,10,2,"default"],
"suball","rectangle",35,-26,4,"top",[0,0,0],["case",false,false,false],[21,10,15.5],[[1,1,1,1]],[false,10,2,"default"]],
["c-series_rack19-1u",
"add2","hd_holder",320,9,1.99,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[2.5,"landscape"],[false,10,2,"default"],
"model","hd25",320,9,2,"bottom",[0,0,0],["case",false,false,false],[0,0,0],["landscape",15],[true,25,2,"both"],
"model","hd25",320,9,20.5,"bottom",[0,0,0],["case",false,false,false],[0,0,0],["landscape",15],[true,25,2,"default"]],
// Odroid-XU4
["xu4_shifter_shield",
"model","pillar",3.5,3.5,8,"bottom",[0,0,0],["sbc",true,true,true],[4,3,19],["hex","silver","top"],[false,10,2,"default"],
"model","pillar",3.5,55.5,8,"bottom",[0,0,0],["sbc",true,true,true],[4,3,19],["hex","silver","top"],[false,10,2,"default"],
"model","pillar",79.5,3.5,8,"bottom",[0,0,0],["sbc",true,true,true],[4,3,19],["hex","silver","top"],[false,10,2,"default"],
"model","pillar",79.5,55.5,8,"bottom",[0,0,0],["sbc",true,true,true],[4,3,19],["hex","silver","top"],[false,10,2,"default"],
"model","hk_xu4_shifter_shield",0,0,27,"bottom",[0,0,0],["sbc",true,true,true],[0,0,0],[0],[true,10,2,"default"]],
["xu4_keyhole",
"add1","keyhole",40,30,0,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[[7,3.2,6,2]],[true,10,2,"default"]],
// Odroid-HC4
["hc4_panel_nas",
"add2","hk_hc4_oled_holder",35,178,2.99,"bottom",[0,0,0],["case",true,true,false],[0,0,2],[0],[true,10,2,"default"],
"model","hk_hc4_oled",35,178,2.99,"bottom",[0,0,0],["case",true,true,false],[0,0,0],[0],[true,10,2,"default"]],
["hc4_shell_drivebox2.5",
"add2","hk_hc4_oled_holder",20,82,1.99,"bottom",[0,0,0],["case",false,true,false],[0,0,2],[0],[true,10,2,"default"],
"model","hk_hc4_oled",20,82,1.99,"bottom",[0,0,0],["case",false,true,false],[0,0,0],[0],[false,10,2,"default"],
@@ -243,6 +260,47 @@ accessory_data = [
"model","fan_cover",37,-4,7,"bottom",[90,0,0],["case",true,false,false],[40,0,3],["fan_1"],[false,10,2,"default"],
"platter","fan_cover",-50,50,0,"bottom",[0,0,0],["case",false,false,false],[40,0,3],["fan_1"],[false,10,2,"default"]],
// Odroid-N2
["n-series_rack19-1u",
"add2","hd_holder",234,101,1.99,"bottom",[0,0,180],["case",false,false,false],[0,0,0],[2.5,"portrait"],[false,10,2,"default"],
"model","hd25",234,101,2,"bottom",[0,0,180],["case",false,false,false],[0,0,0],["portrait",15],[true,10,2,"both"],
"model","hd25",234,101,20.5,"bottom",[0,0,180],["case",false,false,false],[0,0,0],["portrait",15],[true,10,2,"default"]],
["n1_rack10-1u",
"add2","hd_holder",1,10,1.99,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[2.5,"landscape"],[false,10,2,"default"],
"model","hd25",1,10,3,"bottom",[0,0,0],["case",false,false,false],[0,0,0],["landscape",15],[true,20,2,"both"],
"model","hd25",1,10,20.5,"bottom",[0,0,0],["case",false,false,false],[0,0,0],["landscape",15],[true,20,2,"default"]],
// Odroid-M2
["m2_shell",
"add2","button",5.5,56,24,"top",[0,0,180],["sbc-case_z",false,false,true],[12,8,1.5],["cutout",[2,2,2,2],2.25],[true,10,2,"default"]],
// Adafruit models available at https://github.com/adafruit/Adafruit_CAD_Parts/tree/main
["m2_eyespi_eink1.54",
// "model","stl_model",109.62,9.8,19.25,"bottom",[0,0,180],["sbc",true,true,true],[0,0,0],[1,"stl/EYESPI-Dual_I2C.stl"],[false,10,2,"default"],
// "model","stl_model",50.5,99.75,3,"bottom",[90,0,180],["sbc",false,false,false],[0,0,0],[1,"adafruit/4196 1.54in eink display SSD1681.stl"],[false,10,2,"default"],
"add2","pcb_holder",56,99.5,49.5,"top",[180,0,180],["case",false,false,false],[47,35,2.5],[2],[false,10,2,"default"],
"add2","standoff",13.5,104.5,5.5,"bottom",[90,0,0],["sbc",false,false,false],[0,0,0],[["m2.5+",3,3.25,3.6,6,3.25,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"add2","standoff",51.5,104.5,5.5,"bottom",[90,0,0],["sbc",false,false,false],[0,0,0],[["m2.5+",3,3.25,3.6,6,3.25,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"sub","rectangle",17,100,8.75,"top",[0,0,0],["sbc",true,true,true],[31,5,31.5],[[1,1,1,1]],[false,10,2,"default"],
"sub","rectangle",80,83,8.75,"top",[0,0,0],["sbc",true,true,true],[5,7,15],[[1,1,1,1]],[false,10,2,"default"],
"add1","rectangle",11,101.25,1.5,"bottom",[0,0,0],["sbc",false,false,false],[5,2,2.5],[[1,1,1,1]],[false,10,2,"default"],
"add1","rectangle",49,101.25,1.5,"bottom",[0,0,0],["sbc",false,false,false],[5,2,2.5],[[1,1,1,1]],[false,10,2,"default"],
"add2","button",5.5,56,25.5,"top",[0,0,0],["sbc-case_z",true,true,true],[10,0,25],["recess"],[true,10,2,"default"],
"model","button_assembly",5.5,56,25.5,"top",[0,0,0],["sbc-case_z",true,true,true],[10,0,26],["recess"],[false,10,2,"default"],
"platter","button_assembly",-20,0,0,"top",[0,0,0],["case",false,false,false],[10,0,26.5],["recess"],[false,10,2,"default"]],
["m2_eyespi_lcd2.8",
// "model","stl_model",109.62,9.8,19.25,"bottom",[0,0,180],["sbc",true,true,true],[0,0,0],[1,"stl/EYESPI-Dual_I2C.stl"],[false,10,2,"default"],
// "model","stl_model",46,100.75,34,"bottom",[90,90,0],["sbc",false,false,false],[0,0,0],[1,"adafruit/2090 2.8in TFT Cap Touch.stl"],[false,10,2,"default"],
"add2","pcb_holder",5,99.5,0,"bottom",[0,0,0],["case",false,false,false],[82,63,2.5],[2],[false,10,2,"default"],
"add2","pcb_holder",87,99.5,68.5,"top",[180,0,180],["case",false,false,false],[82,63,2.5],[2],[false,10,2,"default"],
"sub","rectangle",19,90.5,12,"top",[0,0,0],["case",false,true,false],[58,5,44],[[1,1,1,1]],[false,10,2,"default"],
"add2","button",5.5,56,25.5,"top",[0,0,0],["sbc-case_z",true,true,true],[10,0,44],["recess"],[true,10,2,"default"],
"model","button_assembly",5.5,56,25.5,"top",[0,0,0],["sbc-case_z",true,true,true],[10,0,44.5],["recess"],[false,10,2,"default"],
"platter","button_assembly",-20,0,0,"top",[0,0,0],["case",false,false,false],[10,0,26.5],["recess"],[false,10,2,"default"]],
// Odroid-M1S
["m1s_shell_nvme",
"sub","vent_hex",37,5,-1,"bottom",[0,0,0],["sbc",false,false,false],[11,3,5],[5,1.5,"horizontal",1],[false,10,2,"default"],
@@ -368,6 +426,9 @@ accessory_data = [
"platter","button_assembly",-20,0,0,"top",[0,0,0],["case",false,false,false],[10,0,11],["recess"],[false,10,2,"default"],
"platter","button_assembly",-30,0,0,"top",[0,0,0],["case",false,false,false],[10,0,11],["recess"],[false,10,2,"default"]],
["h3_panel_nas",
"model","hk_pwr_button",20,150,137,"top",[0,0,0],["case",true,true,true],[0,0,0],[0],[true,10,2,"default"]],
["h3_ultimate",
"sub","vent",-3.5,30,58,"top",[0,0,90],["case",false,false,false],[2,12,4],[1,17,"vertical",1],[false,10,2,"default"],
"sub","vent",111.5,30,58,"top",[0,0,90],["case",true,false,false],[2,12,4],[1,17,"vertical",1],[false,10,2,"default"],
@@ -420,11 +481,45 @@ accessory_data = [
"model","hk_pwr_button",18,113,55.25,"top",[0,0,180],["case",false,false,true],[0,0,0],[0],[true,10,2,"default"],
"model","dsub",18,-1,46,"top",[90,90,0],["case",false,false,false],[0,0,0],["db9","female"],[true,10,2,"default"]],
// Odroid-H4
["h4_panel_nas",
"model","hk_pwr_button",20,150,206,"top",[0,0,0],["case",true,true,true],[0,0,0],[0],[true,10,2,"default"]],
["h4_panel_nas-bottom_sbc",
"model","hk_pwr_button",20,155,183.5,"top",[0,0,0],["case",true,true,true],[0,0,0],[0],[true,10,2,"default"]],
["show2_shell",
"model","hk_wb2",6.25,24.675,16,"bottom",[0,0,180],["sbc",true,true,true],[0,0,0],[0],[false,10,2,"default"],
"sub","rectangle",.5,8,8.5,"top",[0,0,0],["case",false,false,false],[6,16.5,8],[[.5,.5,.5,.5]],[false,10,2,"default"]],
// RPI
["rpi5_m2hat",
"model","pillar",3.5,3.5,9.65,"bottom",[0,0,0],["sbc",true,true,true],[4,3,16],["hex","#fee5a6","top"],[false,10,2,"default"],
"model","pillar",3.5,52.5,9.65,"bottom",[0,0,0],["sbc",true,true,true],[4,3,16],["hex","#fee5a6","top"],[false,10,2,"default"],
"model","pillar",61.5,3.5,9.65,"bottom",[0,0,0],["sbc",true,true,true],[4,3,16],["hex","#fee5a6","top"],[false,10,2,"default"],
"model","pillar",61.5,52.5,9.65,"bottom",[0,0,0],["sbc",true,true,true],[4,3,16],["hex","#fee5a6","top"],[false,10,2,"default"],
"model","rpi_m2hat",0,0,25.65,"top",[0,0,0],["sbc",true,true,true],[0,0,0],[0],[true,20,2,"default"]],
["rpi5_bottom_m2hat",
// "model","stl_model",-1,0,7.6,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[1,"./pimoroni-nvme-rpi5-base.stl"],[false,20,2,"default"],
"model","pillar",3.5,3.5,1,"bottom",[0,0,0],["sbc",true,true,true],[4,3,7],["hex","#fee5a6","top"],[false,10,2,"default"],
"model","pillar",3.5,52.5,1,"bottom",[0,0,0],["sbc",true,true,true],[4,3,7],["hex","#fee5a6","top"],[false,10,2,"default"],
"model","pillar",61.5,3.5,1,"bottom",[0,0,0],["sbc",true,true,true],[4,3,7],["hex","#fee5a6","top"],[false,10,2,"default"],
"model","pillar",61.5,52.5,1,"bottom",[0,0,0],["sbc",true,true,true],[4,3,7],["hex","#fee5a6","top"],[false,10,2,"default"]],
// Radxa
["rock5b",
// UL standoff adjustment
"sub","rectangle",-1,66.5,12.99,"top",[0,0,0],["sbc",true,true,true],[10,2,8],[[.25,.25,.25,.25]],[false,10,2,"default"],
// LR standoff adjustment
"sub","rectangle",92,17.5,12.99,"top",[0,0,0],["sbc",true,true,true],[10,2,15],[[.25,.25,.25,.25]],[false,10,2,"default"],
// LR standoff adjustment
"sub","rectangle",93,17.5,12.99,"top",[0,0,0],["sbc",true,true,true],[2,10,15],[[.25,.25,.25,.25]],[false,10,2,"default"]],
// Standard Motherboard Cases
["adapter_mini-stx_m1s",
"add2","standoff",5,100,0,"bottom",[0,0,0],["sbc",false,false,false],[0,0,0],[["custom",5.75,5,3.6,10,4,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
@@ -432,5 +527,88 @@ accessory_data = [
"add2","standoff",113,100,0,"bottom",[0,0,0],["sbc",false,false,false],[0,0,0],[["custom",5.75,5,3.6,10,4,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"add2","standoff",113,125,0,"bottom",[0,0,0],["sbc",false,false,false],[0,0,0],[["custom",5.75,5,3.6,10,4,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"model","hk_m1s_ups",2,97,5,"bottom",[0,0,0],["sbc",false,false,false],[0,0,0],[0],[true,110,2,"default"]],
// NAS Case
["nas",
"model","hd35",-1,-67,40,"bottom",[0,0,0],["case",true,true,false],[0,0,0],["portrait"],[true,20,2,"both"]],
// circuitsetup solar energy meter
["cs_solarmeter",
"sub","slot",-3,47,10.1,"top",[0,90,0],["sbc",true,true,true],[1.6,4.5,4],[[0]],[false,10,2,"default"]],
// N2L environmental sensors
// Adafruit models available at https://github.com/adafruit/Adafruit_CAD_Parts/tree/main
["n2l_env_sensors",
// divider walls
"add1","rectangle",-1,57,0,"bottom",[0,0,0],["case",false,false,false],[71,2,10.25],[[.1,.1,.1,.1]],[false,10,2,"default"],
"add2","rectangle",-1,57,10.2,"top",[0,0,0],["case",false,false,false],[71,2,33],[[.1,.1,.1,.1]],[false,10,2,"default"],
"suball","round",35,61,9,"bottom",[90,0,0],["case",false,false,false],[4,0,6],[[.1,.1,.1,.1]],[false,10,2,"default"],
// wall opening
"suball","rectangle",69,70,4.5,"bottom",[0,0,0],["case",false,false,false],[6,45,34],[[.1,.1,.1,.1]],[false,10,2,"default"],
// i2c radial hub holder
// "model","stl_model",31,60.75,4,"bottom",[90,0,180],["sbc",false,false,false],[0,0,0],[1,"./adafruit/5625 Stemma 5 Port Hub.stl"],[false,10,2,"default"],
"add2","pcb_holder",5,60.75,1,"bottom",[0,0,0],["case",false,false,false],[26.5,35,1.65],[2],[false,10,2,"default"],
// BMP388 and holder
// "model","stl_model",38,121,22,"bottom",[90,180,90],["sbc",false,false,false],[0,0,0],[1,"./adafruit/3966 BMP388 QT.stl",0,0],[false,10,2,"default"],
"add2","pcb_holder",39.5,95,1,"bottom",[0,0,90],["case",false,false,false],[26.5,35,1.65],[2],[false,10,2,"default"],
// SCD30 and holder
// "model","stl_model",55,69,27,"bottom",[270,0,90],["sbc",false,false,false],[0,0,0],[1,"./adafruit/4867 Adafruit SCD30.stl"],[false,10,2,"default"],
"add2","pcb_holder",55,68,1,"bottom",[0,0,90],["case",false,false,false],[53,35,1.65],[2],[false,10,2,"default"],
// ST7789 IPS TFT Display and holder
// "model","stl_model",67,61,4,"bottom",[90,270,270],["sbc",false,false,false],[0,0,0],[1,"./adafruit/4311 2in TFT IPS Display.stl"],[false,10,2,"default"],
"add2","pcb_holder",65.4,121,1,"bottom",[0,0,270],["case",false,false,false],[61,35,1.65],[2],[false,10,2,"default"],
// PMSA003I Partical Air Quality
// "model","stl_model",0,70,4,"bottom",[0,0,0],["sbc",false,false,false],[0,0,0],[1,"./adafruit/4632 PMSA003I.stl"],[false,10,2,"default"],
"add2","standoff",2.75,72.5,0,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"add2","standoff",2.75,117.5,0,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"add2","standoff",32.75,72.5,0,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"add2","standoff",32.75,117.5,0,"bottom",[0,0,0],["case",false,false,false],[0,0,0],[["m2",5.75,4,3.6,8,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"sub","vent",-3,100,11,"top",[0,0,90],["case",false,false,false],[2,7,4],[1,5,"vertical",1],[false,10,2,"default"],
// SGP30 VOC and eCO2 holder
"add2","pcb_holder",39.5,61,1,"bottom",[0,0,90],["case",false,false,false],[26.5,35,1.65],[2],[false,10,2,"default"]],
// avr128da48 environmental sensors
// Adafruit models available at https://github.com/adafruit/Adafruit_CAD_Parts/tree/main
["avr_env_sensors",
// i2c radial hub holder
// "model","stl_model",31,24,4,"bottom",[90,0,180],["sbc",true,true,false],[0,0,0],[1,"./adafruit/5625 Stemma 5 Port Hub.stl"],[false,10,2,"default"],
"add2","pcb_holder",5,24,0,"bottom",[0,0,0],["sbc",true,true,false],[26.5,35,1.65],[2],[false,10,2,"default"],
// SGP30 VOC and eCO2 holder
"add2","pcb_holder",40.5,26,0,"bottom",[0,0,90],["sbc",true,true,false],[26.5,35,1.65],[2],[false,10,2,"default"],
// BMP388 and holder
// "model","stl_model",39,84,22,"bottom",[90,180,90],["sbc",true,true,false],[0,0,0],[1,"./adafruit/3966 BMP388 QT.stl",0,0],[false,10,2,"default"],
"add2","pcb_holder",40.5,58,0,"bottom",[0,0,90],["sbc",true,true,false],[26.5,35,1.65],[2],[false,10,2,"default"],
// SCD30 and holder
// "model","stl_model",69,32,27,"bottom",[270,0,90],["sbc",true,true,false],[0,0,0],[1,"./adafruit/4867 Adafruit SCD30.stl"],[false,10,2,"default"],
"add2","pcb_holder",69,31,0,"bottom",[0,0,90],["sbc",true,true,false],[53,35,1.65],[2],[false,10,2,"default"],
// ST7789 IPS TFT Display and holder
// "model","stl_model",82,23,2.5,"bottom",[90,270,270],["sbc",true,true,false],[0,0,0],[1,"./adafruit/4311 2in TFT IPS Display.stl"],[false,10,2,"default"],
"add2","pcb_holder",80.5,83,0,"bottom",[0,0,270],["sbc",true,true,false],[61,35,1.65],[2],[false,10,2,"default"],
"add2","pcb_holder",80.5,22,10.5,"top",[0,180,270],["sbc-case_z",true,true,true],[61,35,1.65],[2],[false,10,2,"default"],
// display opening
"suball","rectangle",82,32,3,"bottom",[0,0,0],["sbc",true,true,false],[6,44,34],[[.1,.1,.1,.1]],[false,10,2,"default"],
// empty
"add2","pcb_holder",52,58,0,"bottom",[0,0,90],["sbc",true,true,false],[26.5,35,1.65],[2],[false,10,2,"default"],
"add2","pcb_holder",52,26,0,"bottom",[0,0,90],["sbc",true,true,false],[26.5,35,1.65],[2],[false,10,2,"default"],
// PMSA003I Partical Air Quality
// "model","stl_model",.25,32.5,4,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[1,"./adafruit/4632 PMSA003I.stl"],[false,10,2,"default"],
"add2","standoff",2.75,35,0,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"add2","standoff",2.75,80.75,0,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"add2","standoff",33.25,35,0,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"add2","standoff",33.25,80.75,0,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[["m2",5.75,4,3.6,8,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"sub","vent",-3,61.5,11,"top",[0,0,90],["sbc",true,true,false],[2,7,4],[1,5,"vertical",1],[false,10,2,"default"]],
// adafruit solar charger
["adafruit_solar_charger",
// "add2","standoff",2.75,35,0,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
// "add2","standoff",2.75,80.75,0,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
// "add2","standoff",33.25,35,0,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[["m2",5.75,4,3.6,7,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
// "add2","standoff",33.25,80.75,0,"bottom",[0,0,0],["sbc",true,true,false],[0,0,0],[["m2",5.75,4,3.6,8,3,"countersunk","hex",false,false,4.5,5.1]],[true,10,2,"default"],
"model","adafruit_4755_solar_charger",0,24,4,"bottom",[0,0,0],["sbc",false,false,false],[0,0,0],[0],[true,10,2,"default"],
"model","adafruit_2030_powerboost",53,34,4,"bottom",[0,0,0],["sbc",false,false,false],[0,0,0],[0],[true,10,2,"default"]]
];

View File

@@ -25,6 +25,7 @@ use <./SBC_Model_Framework/sbc_models_library.scad>
include <./mod/add.scad>;
include <./mod/case_adapter.scad>;
include <./mod/case_bottom.scad>;
include <./mod/case_rack.scad>;
include <./mod/case_side.scad>;
include <./mod/case_top.scad>;
include <./mod/case_folded.scad>;
@@ -44,10 +45,14 @@ include <./lib/dsub.scad>;
include <./lib/fans.scad>;
include <./lib/fastener.scad>;
include <./lib/feet.scad>;
include <./lib/grommet.scad>;
include <./lib/hd.scad>;
include <./lib/holder.scad>;
include <./lib/keyhole.scad>;
include <./lib/oem_adafruit.scad>;
include <./lib/oem_hk.scad>;
include <./lib/oem_rpi.scad>;
include <./lib/panel_clamp.scad>;
include <./lib/rack.scad>;
include <./lib/standoff.scad>;
include <./lib/vent.scad>;

114
sbccb_accessory_tool.scad Normal file
View File

@@ -0,0 +1,114 @@
/*
SBC Case Builder Accessory Tool Copyright 2025 Edward A. Kisiel hominoid@cablemi.com
This file is part of SBC Case Builder https://github.com/hominoids/SBC_Case_Builder
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Code released under GPLv3: http://www.gnu.org/licenses/gpl.html
see https://github.com/hominoids/SBC_Case_Builder
*/
include <./sbc_case_builder_library.scad>;
/* [View] */
// viewing mode "model", "platter"
view = "model"; // [model, platter]
individual_part = "bottom"; // [top, bottom, right, left, front, rear, io_shield, accessories]
// section individual parts for panel cases
section_part = false; // [true,false]
accessory = "grommet"; // ["1u rack stand", "2.5 drive holder", "fan cover", "grommet", "washer"]
/* [1U Rack Stand] */
rack_width = 19; // [10, 19]
rack_1u = 4; // [1 : 4]
rack_fasteners = "nut"; // ["none", "nut", "insert"]
/* [2.5" Drive Holder] */
holder_length = 110; // [110, 145]
holder_width = 101.6; // [101.6 : .1 : 150]
/* [Fan Cover] */
fan_style = "fan_hex"; // ["fan_open", "fan_1", "fan_2", "fan_hex"]
fan_size = 40; // [25, 30, 40, 50, 60, 80, 92, 120]
fan_cover_thickness = 2; // [2 : .25 : 5]
/* [Grommet] */
grommet_style = "sleeve"; // ["sleeve"]
grommet_od = 10; // [6 : .25 : 20]
grommet_id = 6; // [2 : .25 : 20]
installation_wall_thickness = 2; // [2 : .25 : 5]
/* [Washer] */
washer_style = "flat"; // ["flat", "shouldered"]
washer_od = 5; // [3 : .25 : 20]
washer_id = 3; // [2 : .25 : 20]
washer_thickness = 2; // [1 : .25 : 8]
shoulder_height = 3; // [1 : .25 : 4]
shoulder_countersunk = false; // [true,false]
/* [Hidden] */
mask = [true, 10, 2, "default"];
nmask = [false, 10, 2, "default"];
rack_depth = 150;
adj = .01;
$fn = 90;
// model view
if (view == "model") {
if(accessory == "1u rack stand") {
rack_stand(rack_1u);
}
if(accessory == "2.5 drive holder") {
hd35_25holder(holder_length, holder_width);
}
if(accessory == "fan cover") {
fan_cover(fan_size, fan_cover_thickness, fan_style);
}
if(accessory == "grommet") {
grommet("front", grommet_style, grommet_od, grommet_id, installation_wall_thickness, true, nmask);
}
if(accessory == "washer") {
washer(washer_style, washer_id, washer_od, washer_thickness, shoulder_height, shoulder_countersunk, "silver");;
}
}
// platter view
if (view == "platter") {
if(accessory == "1u rack stand") {
rotate([0,270,0]) rack_stand(rack_1u);
}
if(accessory == "2.5 drive holder") {
hd35_25holder(holder_length, holder_width);
}
if(accessory == "fan cover") {
fan_cover(fan_size, fan_cover_thickness, fan_style);
}
if(accessory == "grommet" && grommet_style == "sleeve") {
translate([0,0,0]) rotate([270,0,0]) difference() {
grommet("bottom", grommet_style, grommet_od, grommet_id, installation_wall_thickness, false, nmask);
translate([-grommet_od,-.125,-3]) cube([20,10,20]);
}
translate([0,20,0]) rotate([270,0,0]) difference() {
grommet("bottom", grommet_style, grommet_od, grommet_id, installation_wall_thickness, false, nmask);
translate([-grommet_od,-.125,-3]) cube([20,10,20]);
}
translate([0,-20,0])
grommet_clip(grommet_style, grommet_od, grommet_id, installation_wall_thickness);
}
if(accessory == "washer") {
washer(washer_style, washer_id, washer_od, washer_thickness,
shoulder_height, shoulder_countersunk, "silver");
}
}

Binary file not shown.

View File

@@ -1,20 +0,0 @@
/* find correct tolerance and use for respective entry's data_1 value within sbc_case_builder.cfg */
use <./sbc_case_builder_library.scad>;
battery_tolerance = 0;
speaker_tolerance = 0;
volume_tolerance = 0;
$fn = 90;
translate([-33,0,0]) batt_holder(battery_tolerance);
difference() {
translate([-17,-17,0]) cube([34,34,2]);
translate([0,0,-1]) cylinder(d=24, h=4);
}
translate([0,0,1.99]) boom_speaker_holder("friction",speaker_tolerance);
translate([30,0,0]) boom_vring(volume_tolerance);