Merge pull request 'feat: Jetson Orin Nano mount bracket (Issue #612)' (#619) from sl-mechanical/issue-612-jetson-mount into main
This commit is contained in:
commit
62aab7164e
386
chassis/jetson_orin_mount.scad
Normal file
386
chassis/jetson_orin_mount.scad
Normal file
@ -0,0 +1,386 @@
|
||||
// ============================================================
|
||||
// Jetson Orin Nano Carrier Board Mount — Issue #612
|
||||
// Agent : sl-mechanical
|
||||
// Date : 2026-03-15
|
||||
// Part catalogue:
|
||||
// 1. tnut_base — 2020 T-slot rail interface plate, M5 T-nut captive pockets
|
||||
// 2. standoff_post — M2.5 captive-nut standoff post (×4), 10 mm airflow gap
|
||||
// 3. side_brace — lateral stiffening brace with port-access cutouts (×2)
|
||||
// 4. duct_shroud — optional top heatsink duct / fan-exhaust channel
|
||||
// 5. cable_clip — snap-on cable management clip for brace edge
|
||||
//
|
||||
// BOM:
|
||||
// 4 × M5×10 BHCS + M5 T-nuts (tnut_base to rail, 2 per rail)
|
||||
// 4 × M2.5×20 SHCS (board to standoff posts)
|
||||
// 4 × M2.5 hex nuts (captured in standoff posts)
|
||||
// 4 × M3×8 SHCS + washers (side_brace to tnut_base)
|
||||
// 2 × M3×16 SHCS (duct_shroud to side_brace tops)
|
||||
//
|
||||
// Jetson Orin Nano carrier board (Seeed reComputer / official dev kit):
|
||||
// Board dims : 100 × 80 mm
|
||||
// Mounting hole pattern : 86 × 58 mm (centre-to-centre), M2.5, Ø3.5 pad
|
||||
// PCB thickness: 1.6 mm
|
||||
// Connector side: -Y (USB-A, USB-C, HDMI, DP, GbE, SD on one long edge)
|
||||
// Fan header & PWM header: +X short edge
|
||||
// M.2 / NVMe: bottom face
|
||||
//
|
||||
// Print settings (PETG):
|
||||
// tnut_base / standoff_post / side_brace / duct_shroud : 5 perimeters, 40 % gyroid, no supports
|
||||
// cable_clip : 3 perimeters, 30 % gyroid, no supports
|
||||
//
|
||||
// Export commands:
|
||||
// openscad -D 'RENDER="tnut_base"' -o tnut_base.stl jetson_orin_mount.scad
|
||||
// openscad -D 'RENDER="standoff_post"' -o standoff_post.stl jetson_orin_mount.scad
|
||||
// openscad -D 'RENDER="side_brace"' -o side_brace.stl jetson_orin_mount.scad
|
||||
// openscad -D 'RENDER="duct_shroud"' -o duct_shroud.stl jetson_orin_mount.scad
|
||||
// openscad -D 'RENDER="cable_clip"' -o cable_clip.stl jetson_orin_mount.scad
|
||||
// openscad -D 'RENDER="assembly"' -o assembly.png jetson_orin_mount.scad
|
||||
// ============================================================
|
||||
|
||||
// ── Render selector ─────────────────────────────────────────
|
||||
RENDER = "assembly"; // tnut_base | standoff_post | side_brace | duct_shroud | cable_clip | assembly
|
||||
|
||||
// ── Global constants ────────────────────────────────────────
|
||||
$fn = 64;
|
||||
EPS = 0.01;
|
||||
|
||||
// 2020 rail
|
||||
RAIL_W = 20.0;
|
||||
SLOT_NECK_H = 3.2;
|
||||
TNUT_W = 9.8;
|
||||
TNUT_H = 5.5;
|
||||
TNUT_L = 12.0;
|
||||
M5_D = 5.2;
|
||||
M5_HEAD_D = 9.5;
|
||||
M5_HEAD_H = 4.0;
|
||||
|
||||
// Jetson Orin Nano carrier board
|
||||
BOARD_L = 100.0; // board X
|
||||
BOARD_W = 80.0; // board Y
|
||||
BOARD_T = 1.6; // PCB thickness
|
||||
MH_SX = 86.0; // mounting hole span X (centre-to-centre)
|
||||
MH_SY = 58.0; // mounting hole span Y
|
||||
M25_D = 2.7; // M2.5 clearance bore
|
||||
M25_NUT_W = 5.0; // M2.5 hex nut across-flats
|
||||
M25_NUT_H = 2.0; // M2.5 hex nut height
|
||||
M25_HEAD_D = 5.0; // M2.5 SHCS head diameter
|
||||
M25_HEAD_H = 2.5;
|
||||
|
||||
// Base plate
|
||||
BASE_L = 120.0; // length along X (covers board + overhang for braces)
|
||||
BASE_W = 50.0; // width along Y (rail mount footprint)
|
||||
BASE_T = 6.0; // plate thickness
|
||||
BOLT_PITCH = 40.0; // M5 rail bolt pitch (per rail, 2 rails at Y=0 & Y=BASE_W)
|
||||
M3_D = 3.2;
|
||||
M3_HEAD_D = 6.0;
|
||||
M3_HEAD_H = 3.0;
|
||||
|
||||
// Standoff posts
|
||||
POST_H = 12.0; // airflow gap + PCB seating (>= 10 mm clearance spec)
|
||||
POST_OD = 8.0; // outer diameter
|
||||
POST_BASE_D = 11.0; // flange diameter
|
||||
POST_BASE_H = 3.0; // flange height
|
||||
NUT_TRAP_H = M25_NUT_H + 0.3;
|
||||
NUT_TRAP_W = M25_NUT_W + 0.4;
|
||||
|
||||
// Side braces
|
||||
BRACE_T = 5.0; // brace thickness (X)
|
||||
BRACE_H = POST_H + POST_BASE_H + BOARD_T + 4.0; // full height
|
||||
BRACE_W = BASE_W; // same width as base
|
||||
|
||||
// Port-access cutouts (connector side -Y)
|
||||
USB_CUT_W = 60.0; // wide cutout for USB-A stack + HDMI + DP
|
||||
USB_CUT_H = 22.0;
|
||||
GBE_CUT_W = 20.0; // GbE jack
|
||||
GBE_CUT_H = 18.0;
|
||||
|
||||
// Duct shroud
|
||||
DUCT_T = 3.0; // wall thickness
|
||||
DUCT_FLANGE = 6.0; // side tab width for M3 attachment
|
||||
FAN_W = 40.0; // standard 40 mm blower clearance cutout
|
||||
FAN_H = 10.0; // duct outlet height
|
||||
|
||||
// Cable clip
|
||||
CLIP_OD = 12.0;
|
||||
CLIP_ID = 7.0;
|
||||
CLIP_GAP = 7.5;
|
||||
CLIP_W = 10.0;
|
||||
SNAP_T = 1.8;
|
||||
|
||||
// ── Utilities ───────────────────────────────────────────────
|
||||
module chamfer_cube(size, ch=1.0) {
|
||||
hull() {
|
||||
translate([ch, ch, 0]) cube([size[0]-2*ch, size[1]-2*ch, EPS]);
|
||||
translate([0, 0, ch]) cube(size - [0, 0, ch]);
|
||||
}
|
||||
}
|
||||
|
||||
module hex_pocket(af, depth) {
|
||||
cylinder(d=af/cos(30), h=depth, $fn=6);
|
||||
}
|
||||
|
||||
// ── Part 1: tnut_base ───────────────────────────────────────
|
||||
module tnut_base() {
|
||||
difference() {
|
||||
union() {
|
||||
chamfer_cube([BASE_L, BASE_W, BASE_T], ch=1.5);
|
||||
|
||||
// Raised mounting bosses for M3 brace attachment (4 corners)
|
||||
for (x = [8, BASE_L-8])
|
||||
for (y = [8, BASE_W-8])
|
||||
translate([x, y, BASE_T])
|
||||
cylinder(d=10, h=2.5);
|
||||
}
|
||||
|
||||
// T-nut pockets and M5 bolts — front rail (y = BASE_W/4)
|
||||
for (x = [BASE_L/2 - BOLT_PITCH/2, BASE_L/2 + BOLT_PITCH/2]) {
|
||||
translate([x, BASE_W/4, -EPS]) {
|
||||
cylinder(d=M5_D, h=BASE_T + 2*EPS);
|
||||
cylinder(d=M5_HEAD_D, h=M5_HEAD_H + EPS);
|
||||
}
|
||||
translate([x - TNUT_L/2, BASE_W/4 - TNUT_W/2, BASE_T - TNUT_H])
|
||||
cube([TNUT_L, TNUT_W, TNUT_H + EPS]);
|
||||
}
|
||||
|
||||
// T-nut pockets and M5 bolts — rear rail (y = 3*BASE_W/4)
|
||||
for (x = [BASE_L/2 - BOLT_PITCH/2, BASE_L/2 + BOLT_PITCH/2]) {
|
||||
translate([x, 3*BASE_W/4, -EPS]) {
|
||||
cylinder(d=M5_D, h=BASE_T + 2*EPS);
|
||||
cylinder(d=M5_HEAD_D, h=M5_HEAD_H + EPS);
|
||||
}
|
||||
translate([x - TNUT_L/2, 3*BASE_W/4 - TNUT_W/2, BASE_T - TNUT_H])
|
||||
cube([TNUT_L, TNUT_W, TNUT_H + EPS]);
|
||||
}
|
||||
|
||||
// M3 boss bolt holes (corner braces)
|
||||
for (x = [8, BASE_L-8])
|
||||
for (y = [8, BASE_W-8])
|
||||
translate([x, y, -EPS])
|
||||
cylinder(d=M3_D, h=BASE_T + 2.5 + 2*EPS);
|
||||
|
||||
// M3 boss counterbores (head from bottom)
|
||||
for (x = [8, BASE_L-8])
|
||||
for (y = [8, BASE_W-8])
|
||||
translate([x, y, -EPS])
|
||||
cylinder(d=M3_HEAD_D, h=M3_HEAD_H + EPS);
|
||||
|
||||
// Standoff post seating holes (board hole pattern, centred on plate)
|
||||
bx0 = BASE_L/2 - MH_SX/2;
|
||||
by0 = BASE_W/2 - MH_SY/2;
|
||||
for (dx = [0, MH_SX])
|
||||
for (dy = [0, MH_SY])
|
||||
translate([bx0+dx, by0+dy, -EPS])
|
||||
cylinder(d=POST_BASE_D + 0.4, h=BASE_T + 2*EPS);
|
||||
|
||||
// Weight relief grid (2 pockets)
|
||||
translate([20, 12, -EPS]) cube([30, BASE_W-24, BASE_T/2]);
|
||||
translate([BASE_L-50, 12, -EPS]) cube([30, BASE_W-24, BASE_T/2]);
|
||||
|
||||
// Cable pass-through slot
|
||||
translate([BASE_L/2 - 8, BASE_W/2 - 3, -EPS])
|
||||
cube([16, 6, BASE_T + 2*EPS]);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Part 2: standoff_post ───────────────────────────────────
|
||||
module standoff_post() {
|
||||
difference() {
|
||||
union() {
|
||||
// Flange
|
||||
cylinder(d=POST_BASE_D, h=POST_BASE_H);
|
||||
// Post body
|
||||
translate([0, 0, POST_BASE_H])
|
||||
cylinder(d=POST_OD, h=POST_H);
|
||||
}
|
||||
|
||||
// M2.5 through bore
|
||||
translate([0, 0, -EPS])
|
||||
cylinder(d=M25_D, h=POST_BASE_H + POST_H + 2*EPS);
|
||||
|
||||
// Captured hex nut trap (from top)
|
||||
translate([0, 0, POST_BASE_H + POST_H - NUT_TRAP_H])
|
||||
hex_pocket(NUT_TRAP_W, NUT_TRAP_H + EPS);
|
||||
|
||||
// Anti-rotation flat on nut pocket
|
||||
translate([-M25_NUT_W/2 - 0.2, -POST_OD/2 - EPS,
|
||||
POST_BASE_H + POST_H - NUT_TRAP_H])
|
||||
cube([M25_NUT_W + 0.4, 2.0, NUT_TRAP_H + EPS]);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Part 3: side_brace ──────────────────────────────────────
|
||||
// Printed as +X face. Mirror for -X side.
|
||||
module side_brace() {
|
||||
difference() {
|
||||
union() {
|
||||
chamfer_cube([BRACE_T, BRACE_W, BRACE_H], ch=1.0);
|
||||
|
||||
// Top lip to retain board edge
|
||||
translate([0, 0, BRACE_H])
|
||||
cube([BRACE_T + 8.0, BRACE_W, 2.5]);
|
||||
}
|
||||
|
||||
// M3 bolt holes at base (attach to tnut_base bosses)
|
||||
for (y = [8, BRACE_W-8])
|
||||
translate([-EPS, y, 4])
|
||||
rotate([0, 90, 0])
|
||||
cylinder(d=M3_D, h=BRACE_T + 2*EPS);
|
||||
|
||||
// M3 counterbore from outer face
|
||||
for (y = [8, BRACE_W-8])
|
||||
translate([-EPS, y, 4])
|
||||
rotate([0, 90, 0])
|
||||
cylinder(d=M3_HEAD_D, h=M3_HEAD_H + EPS);
|
||||
|
||||
// Port-access cutout — USB/HDMI/DP cluster (centred on brace face)
|
||||
translate([-EPS, BRACE_W/2 - USB_CUT_W/2, POST_BASE_H + 2.0])
|
||||
cube([BRACE_T + 2*EPS, USB_CUT_W, USB_CUT_H]);
|
||||
|
||||
// GbE cutout (offset toward +Y)
|
||||
translate([-EPS, BRACE_W/2 + USB_CUT_W/2 - GBE_CUT_W - 2, POST_BASE_H + 2.0])
|
||||
cube([BRACE_T + 2*EPS, GBE_CUT_W, GBE_CUT_H]);
|
||||
|
||||
// M3 duct attachment holes (top edge)
|
||||
for (y = [BRACE_W/4, 3*BRACE_W/4])
|
||||
translate([BRACE_T/2, y, BRACE_H - 2])
|
||||
cylinder(d=M3_D, h=10);
|
||||
|
||||
// Ventilation slots (3 tall slots for airflow)
|
||||
for (i = [0:2])
|
||||
translate([-EPS,
|
||||
(BRACE_W - 3*8 - 2*4) / 2 + i*(8+4),
|
||||
POST_BASE_H + USB_CUT_H + 6])
|
||||
cube([BRACE_T + 2*EPS, 8, BRACE_H - POST_BASE_H - USB_CUT_H - 10]);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Part 4: duct_shroud ─────────────────────────────────────
|
||||
// Top cap that channels fan exhaust away from board; optional print.
|
||||
module duct_shroud() {
|
||||
duct_l = BASE_L - 2*BRACE_T - 1.0; // span between inner brace faces
|
||||
duct_w = BRACE_W;
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
// Top plate
|
||||
cube([duct_l, duct_w, DUCT_T]);
|
||||
|
||||
// Front wall (fan inlet side)
|
||||
translate([0, 0, -FAN_H])
|
||||
cube([DUCT_T, duct_w, FAN_H + DUCT_T]);
|
||||
|
||||
// Rear wall (exhaust side — open centre)
|
||||
translate([duct_l - DUCT_T, 0, -FAN_H])
|
||||
cube([DUCT_T, duct_w, FAN_H + DUCT_T]);
|
||||
|
||||
// Side flanges for M3 attachment
|
||||
translate([-DUCT_FLANGE, 0, -FAN_H])
|
||||
cube([DUCT_FLANGE, duct_w, FAN_H + DUCT_T]);
|
||||
translate([duct_l, 0, -FAN_H])
|
||||
cube([DUCT_FLANGE, duct_w, FAN_H + DUCT_T]);
|
||||
}
|
||||
|
||||
// Fan cutout on top plate (centred)
|
||||
translate([duct_l/2 - FAN_W/2, duct_w/2 - FAN_W/2, -EPS])
|
||||
cube([FAN_W, FAN_W, DUCT_T + 2*EPS]);
|
||||
|
||||
// Fan screw holes (40 mm fan, Ø3.2 at 32 mm BC)
|
||||
for (dx = [-16, 16])
|
||||
for (dy = [-16, 16])
|
||||
translate([duct_l/2 + dx, duct_w/2 + dy, -EPS])
|
||||
cylinder(d=M3_D, h=DUCT_T + 2*EPS);
|
||||
|
||||
// Exhaust slot on rear wall (full width minus corners)
|
||||
translate([duct_l - DUCT_T - EPS, 4, -FAN_H + 2])
|
||||
cube([DUCT_T + 2*EPS, duct_w - 8, FAN_H - 2]);
|
||||
|
||||
// M3 flange attachment holes
|
||||
for (y = [duct_w/4, 3*duct_w/4]) {
|
||||
translate([-DUCT_FLANGE - EPS, y, -FAN_H/2])
|
||||
rotate([0, 90, 0])
|
||||
cylinder(d=M3_D, h=DUCT_FLANGE + 2*EPS);
|
||||
translate([duct_l + DUCT_T - EPS, y, -FAN_H/2])
|
||||
rotate([0, 90, 0])
|
||||
cylinder(d=M3_D, h=DUCT_FLANGE + 2*EPS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Part 5: cable_clip ──────────────────────────────────────
|
||||
module cable_clip() {
|
||||
difference() {
|
||||
union() {
|
||||
// Snap-wrap body
|
||||
difference() {
|
||||
cylinder(d=CLIP_OD + 2*SNAP_T, h=CLIP_W);
|
||||
translate([0, 0, -EPS])
|
||||
cylinder(d=CLIP_ID, h=CLIP_W + 2*EPS);
|
||||
// Front gap
|
||||
translate([-CLIP_GAP/2, 0, -EPS])
|
||||
cube([CLIP_GAP, CLIP_OD, CLIP_W + 2*EPS]);
|
||||
}
|
||||
|
||||
// Mounting tab for brace edge
|
||||
translate([CLIP_OD/2 + SNAP_T - EPS, -SNAP_T, 0])
|
||||
cube([8, SNAP_T*2, CLIP_W]);
|
||||
}
|
||||
|
||||
// Tab screw hole
|
||||
translate([CLIP_OD/2 + SNAP_T + 4, 0, CLIP_W/2])
|
||||
rotate([90, 0, 0])
|
||||
cylinder(d=M3_D, h=SNAP_T*2 + 2*EPS, center=true);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Assembly ────────────────────────────────────────────────
|
||||
module assembly() {
|
||||
// Base plate
|
||||
color("SteelBlue")
|
||||
tnut_base();
|
||||
|
||||
// Standoff posts (board hole pattern)
|
||||
bx0 = BASE_L/2 - MH_SX/2;
|
||||
by0 = BASE_W/2 - MH_SY/2;
|
||||
for (dx = [0, MH_SX])
|
||||
for (dy = [0, MH_SY])
|
||||
color("DodgerBlue")
|
||||
translate([bx0+dx, by0+dy, BASE_T])
|
||||
standoff_post();
|
||||
|
||||
// Side braces (left and right)
|
||||
color("CornflowerBlue")
|
||||
translate([0, 0, BASE_T])
|
||||
side_brace();
|
||||
color("CornflowerBlue")
|
||||
translate([BASE_L, BRACE_W, BASE_T])
|
||||
mirror([1, 0, 0])
|
||||
mirror([0, 1, 0])
|
||||
side_brace();
|
||||
|
||||
// Board silhouette (translucent, for clearance visualisation)
|
||||
color("ForestGreen", 0.25)
|
||||
translate([BASE_L/2 - BOARD_L/2, BASE_W/2 - BOARD_W/2,
|
||||
BASE_T + POST_BASE_H + POST_H])
|
||||
cube([BOARD_L, BOARD_W, BOARD_T]);
|
||||
|
||||
// Duct shroud (above board)
|
||||
color("LightSteelBlue", 0.7)
|
||||
translate([BRACE_T + 0.5, 0,
|
||||
BASE_T + POST_BASE_H + POST_H + BOARD_T + 2.0])
|
||||
duct_shroud();
|
||||
|
||||
// Cable clips (on brace edge, 2×)
|
||||
for (y = [BRACE_W/3, 2*BRACE_W/3])
|
||||
color("SlateGray")
|
||||
translate([BASE_L + 2, y, BASE_T + BRACE_H/2 - CLIP_W/2])
|
||||
rotate([0, 90, 0])
|
||||
cable_clip();
|
||||
}
|
||||
|
||||
// ── Dispatch ────────────────────────────────────────────────
|
||||
if (RENDER == "tnut_base") tnut_base();
|
||||
else if (RENDER == "standoff_post") standoff_post();
|
||||
else if (RENDER == "side_brace") side_brace();
|
||||
else if (RENDER == "duct_shroud") duct_shroud();
|
||||
else if (RENDER == "cable_clip") cable_clip();
|
||||
else assembly();
|
||||
Loading…
x
Reference in New Issue
Block a user