Merge pull request 'feat(mechanical): Cable management clips (Issue #264)' (#283) from sl-mechanical/issue-264-cable-clips into main
This commit is contained in:
commit
a4d29376b8
354
chassis/cable_management_clips.scad
Normal file
354
chassis/cable_management_clips.scad
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
// =============================================================================
|
||||||
|
// SaltyBot — Cable Management Clips
|
||||||
|
// Agent: sl-mechanical | 2026-03-02
|
||||||
|
//
|
||||||
|
// MODULAR SNAP-ON CABLE CLIPS with integrated adhesive base and zip-tie anchors.
|
||||||
|
// Designed to organize power cables, sensor bundles, and signal harnesses on the
|
||||||
|
// chassis. Each clip accommodates a range of cable bundle diameters via elastic
|
||||||
|
// snap jaws.
|
||||||
|
//
|
||||||
|
// HOW IT WORKS
|
||||||
|
// 1. Adhesive base (3M VHB or equivalent) adheres to chassis surface.
|
||||||
|
// 2. Cable bundle pressed upward through snap jaws until it seats with audible click.
|
||||||
|
// 3. Overhanging jaw tabs provide two zip-tie anchor points (one per side).
|
||||||
|
// 4. Vertical ear holes accept M3 threaded inserts for wire or strap attachment.
|
||||||
|
//
|
||||||
|
// CLIP FAMILY
|
||||||
|
// • Clip 5mm: Holds 4–6 mm bundles (small signal cables)
|
||||||
|
// • Clip 8mm: Holds 6–10 mm bundles (mixed power + signal)
|
||||||
|
// • Clip 12mm: Holds 10–14 mm bundles (heavy power)
|
||||||
|
//
|
||||||
|
// PARTS (set RENDER= to export each)
|
||||||
|
// clip_5mm — 3D print × N (RENDER="clip_5mm")
|
||||||
|
// clip_8mm — 3D print × N (RENDER="clip_8mm")
|
||||||
|
// clip_12mm — 3D print × N (RENDER="clip_12mm")
|
||||||
|
// assembly_all — Full preview with ghosts (RENDER="assembly_all")
|
||||||
|
//
|
||||||
|
// MATERIALS
|
||||||
|
// • Body: PETG or ASA (weatherproof, adhesive-friendly)
|
||||||
|
// • Adhesive: 3M VHB 5952F (50 mm × 75 mm pads, rated 5 N/cm²)
|
||||||
|
// • Anchors: M3 threaded inserts (optional, for high-load retention)
|
||||||
|
// • Zip-ties: Standard nylon 3.6 mm × 150 mm (e.g., HellermannTyton)
|
||||||
|
//
|
||||||
|
// INSTALLATION
|
||||||
|
// 1. Clean chassis surface with isopropyl alcohol; let dry.
|
||||||
|
// 2. Peel 3M VHB backing; press clip firmly (30 s hold).
|
||||||
|
// 3. Wait 24 hours for full adhesive cure.
|
||||||
|
// 4. Press cable bundle upward through snap jaws until seated.
|
||||||
|
// 5. Route zip-ties through jaw anchor points; cinch at desired tension.
|
||||||
|
// 6. Optionally thread M3 bolts through ear holes for redundant retention.
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
$fn = 64;
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// CLIP GEOMETRY — COMMON PARAMETERS
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
// SNAP JAW PROFILE (all clips share same jaw geometry)
|
||||||
|
JAW_THICKNESS = 2.0; // mm thickness of snap arms (thin = flexible)
|
||||||
|
JAW_BEND_R = 0.8; // mm radius at jaw root (stress relief)
|
||||||
|
JAW_CLOSURE = 0.3; // mm interference fit depth when snapped closed
|
||||||
|
SNAP_TRAVEL = 1.2; // mm vertical distance cable travels before seat
|
||||||
|
SNAP_REST_GAP = 0.2; // mm gap when unloaded (keeps jaws sprung apart)
|
||||||
|
|
||||||
|
// ADHESIVE BASE
|
||||||
|
BASE_LENGTH = 50.0; // mm forward-back footprint
|
||||||
|
BASE_WIDTH = 40.0; // mm left-right footprint
|
||||||
|
BASE_THICKNESS = 2.5; // mm base pad thickness
|
||||||
|
BASE_FILLET = 2.0; // mm corner rounding (aids adhesive contact)
|
||||||
|
|
||||||
|
// ZIP-TIE ANCHOR FEATURES
|
||||||
|
ANCHOR_TAB_H = 5.0; // mm height of jaw-tip anchor tab
|
||||||
|
ANCHOR_TAB_T = 1.5; // mm thickness of anchor tab
|
||||||
|
ANCHOR_SLOT_W = 4.0; // mm width of zip-tie slot (3.6 mm ties + 0.4 mm clearance)
|
||||||
|
ANCHOR_SLOT_H = 1.0; // mm height of slot throat
|
||||||
|
|
||||||
|
// WIRE/STRAP ATTACHMENT EARS
|
||||||
|
EAR_D = 4.2; // mm hole diameter (M3 clearance, 2.6 mm nominal)
|
||||||
|
EAR_WALL_T = 3.0; // mm wall thickness around hole
|
||||||
|
EAR_H = 8.0; // mm ear protrusion height from base
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// CLIP SIZE VARIANTS
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
// For each clip size, define:
|
||||||
|
// CABLE_D — nominal cable bundle diameter
|
||||||
|
// JAW_SPAN — inner span of closed jaws (CABLE_D + JAW_CLOSURE)
|
||||||
|
// CLIP_HEIGHT — overall height of clip body
|
||||||
|
// CLAMP_X — width of clamp section (controls jaw lever arm)
|
||||||
|
|
||||||
|
CLIP_PARAMS = [
|
||||||
|
// [name, cable_d, jaw_span, height, clamp_x]
|
||||||
|
["5mm", 5.0, 5.3, 28.0, 18.0],
|
||||||
|
["8mm", 8.0, 8.3, 35.0, 22.0],
|
||||||
|
["12mm", 12.0, 12.3, 42.0, 26.0],
|
||||||
|
];
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// RENDER CONTROL
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
// "assembly_all" — all clips in array, with base ghosts
|
||||||
|
// "clip_5mm" — single 5mm clip (ready to export STL)
|
||||||
|
// "clip_8mm" — single 8mm clip
|
||||||
|
// "clip_12mm" — single 12mm clip
|
||||||
|
|
||||||
|
RENDER = "assembly_all";
|
||||||
|
|
||||||
|
// Helper to fetch clip parameters by name
|
||||||
|
function get_clip_params(name) =
|
||||||
|
(name == "5mm") ? CLIP_PARAMS[0] :
|
||||||
|
(name == "8mm") ? CLIP_PARAMS[1] :
|
||||||
|
(name == "12mm") ? CLIP_PARAMS[2] :
|
||||||
|
CLIP_PARAMS[0];
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// MAIN RENDER DISPATCH
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
if (RENDER == "assembly_all") {
|
||||||
|
assembly_all();
|
||||||
|
} else if (RENDER == "clip_5mm") {
|
||||||
|
clip_body(get_clip_params("5mm"));
|
||||||
|
} else if (RENDER == "clip_8mm") {
|
||||||
|
clip_body(get_clip_params("8mm"));
|
||||||
|
} else if (RENDER == "clip_12mm") {
|
||||||
|
clip_body(get_clip_params("12mm"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// ASSEMBLY VIEW (all clips in a row, with adhesive pads ghosted)
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
module assembly_all() {
|
||||||
|
for (i = [0 : len(CLIP_PARAMS) - 1]) {
|
||||||
|
p = CLIP_PARAMS[i];
|
||||||
|
x_offset = i * 70; // 70 mm spacing
|
||||||
|
|
||||||
|
translate([x_offset, 0, 0]) {
|
||||||
|
// Clip body
|
||||||
|
color("DodgerBlue", 0.92)
|
||||||
|
clip_body(p);
|
||||||
|
|
||||||
|
// Adhesive base ghost (3M VHB pad)
|
||||||
|
%color("LimeGreen", 0.40)
|
||||||
|
translate([0, 0, -BASE_THICKNESS])
|
||||||
|
rounded_rect([50, 40, 0.2], BASE_FILLET);
|
||||||
|
|
||||||
|
// Label
|
||||||
|
echo(str("Clip ", p[0], " — Cable dia. ", p[1], " mm"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// CLIP BODY MODULE (parametric across all sizes)
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// • Base: rounded rectangle, adhesive-mounting surface
|
||||||
|
// • Spine: central vertical structure, extends from base
|
||||||
|
// • Jaws: two snap arms extending upward/outward from spine
|
||||||
|
// • Ears: two lateral holes for M3 attachment (optional)
|
||||||
|
// • Anchors: small tabs on jaw tips for zip-tie routing
|
||||||
|
//
|
||||||
|
|
||||||
|
module clip_body(params) {
|
||||||
|
name = params[0];
|
||||||
|
cable_d = params[1];
|
||||||
|
jaw_span = params[2];
|
||||||
|
clip_h = params[3];
|
||||||
|
clamp_x = params[4];
|
||||||
|
|
||||||
|
spine_thick = 3.5; // mm thickness of central spine
|
||||||
|
jaw_l = clip_h - BASE_THICKNESS; // jaw arm length
|
||||||
|
jaw_root_x = clamp_x / 2; // X position where jaw originates from spine
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
// ── ADHESIVE BASE ──────────────────────────────────────────────
|
||||||
|
translate([0, 0, -BASE_THICKNESS/2])
|
||||||
|
rounded_rect([BASE_LENGTH, BASE_WIDTH, BASE_THICKNESS], BASE_FILLET);
|
||||||
|
|
||||||
|
// ── CENTRAL SPINE (support structure) ───────────────────────────
|
||||||
|
translate([-spine_thick/2, -clamp_x/2, 0])
|
||||||
|
cube([spine_thick, clamp_x, BASE_THICKNESS + jaw_l]);
|
||||||
|
|
||||||
|
// ── LEFT JAW (snap arm with flexible root) ──────────────────────
|
||||||
|
jaw_body(-jaw_root_x, jaw_l, jaw_span);
|
||||||
|
|
||||||
|
// ── RIGHT JAW (snap arm, mirror) ───────────────────────────────
|
||||||
|
jaw_body(jaw_root_x, jaw_l, jaw_span);
|
||||||
|
|
||||||
|
// ── LEFT EAR (M3 attachment hole) ──────────────────────────────
|
||||||
|
translate([-clamp_x/2 - EAR_WALL_T - EAR_D/2, 0, BASE_THICKNESS])
|
||||||
|
ear_boss();
|
||||||
|
|
||||||
|
// ── RIGHT EAR ──────────────────────────────────────────────────
|
||||||
|
translate([clamp_x/2 + EAR_WALL_T + EAR_D/2, 0, BASE_THICKNESS])
|
||||||
|
ear_boss();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── SUBTRACT: Anchor slot hollows (zip-tie slots in jaw tips) ──────
|
||||||
|
jaw_root_z = BASE_THICKNESS + jaw_l - ANCHOR_TAB_H;
|
||||||
|
|
||||||
|
// Left jaw anchor slot
|
||||||
|
translate([-jaw_root_x - 2, -ANCHOR_SLOT_W/2, jaw_root_z])
|
||||||
|
cube([3, ANCHOR_SLOT_W, ANCHOR_SLOT_H]);
|
||||||
|
|
||||||
|
// Right jaw anchor slot
|
||||||
|
translate([jaw_root_x - 1, -ANCHOR_SLOT_W/2, jaw_root_z])
|
||||||
|
cube([3, ANCHOR_SLOT_W, ANCHOR_SLOT_H]);
|
||||||
|
|
||||||
|
// ── SUBTRACT: Ear attachment holes (M3 clearance) ────────────────
|
||||||
|
// Left ear hole
|
||||||
|
translate([-clamp_x/2 - EAR_WALL_T - EAR_D/2, 0, BASE_THICKNESS + EAR_H/2])
|
||||||
|
cylinder(d=EAR_D, h=EAR_H + 1, center=true);
|
||||||
|
|
||||||
|
// Right ear hole
|
||||||
|
translate([clamp_x/2 + EAR_WALL_T + EAR_D/2, 0, BASE_THICKNESS + EAR_H/2])
|
||||||
|
cylinder(d=EAR_D, h=EAR_H + 1, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// JAW BODY (single snap arm with cable pocket)
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// A flexible cantilever arm extending from the spine.
|
||||||
|
// Lower section: solid (load-bearing).
|
||||||
|
// Upper section: curved U-channel (grips cable).
|
||||||
|
// Jaw tips: overhanging tabs for zip-tie anchors.
|
||||||
|
//
|
||||||
|
|
||||||
|
module jaw_body(x_root, jaw_length, inner_span) {
|
||||||
|
jaw_span_outer = inner_span + 2 * JAW_THICKNESS;
|
||||||
|
|
||||||
|
// The jaw sweeps from x_root (spine side) along +X, curving to grip.
|
||||||
|
// At the tip, it has a slight outward bow for snap action.
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
// Lower jaw arm (solid, structural)
|
||||||
|
translate([x_root, -jaw_span_outer/2, BASE_THICKNESS])
|
||||||
|
cube([jaw_length * 0.65, jaw_span_outer, JAW_THICKNESS * 1.5]);
|
||||||
|
|
||||||
|
// Upper jaw arm (U-channel form)
|
||||||
|
translate([x_root, -inner_span/2 - JAW_THICKNESS, BASE_THICKNESS])
|
||||||
|
cube([jaw_length * 0.85, inner_span + 2*JAW_THICKNESS, JAW_THICKNESS]);
|
||||||
|
|
||||||
|
// Jaw tip anchor tab (for zip-tie slots)
|
||||||
|
tip_x = x_root + jaw_length * 0.8;
|
||||||
|
translate([tip_x, -jaw_span_outer/2 - ANCHOR_TAB_T,
|
||||||
|
BASE_THICKNESS + JAW_THICKNESS])
|
||||||
|
cube([ANCHOR_TAB_H, jaw_span_outer + 2*ANCHOR_TAB_T, ANCHOR_TAB_H]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hollow out the U-channel (cable pocket)
|
||||||
|
// Inner cavity: inner_span wide, runs most of jaw length
|
||||||
|
translate([x_root + JAW_THICKNESS * 0.5, -inner_span/2, BASE_THICKNESS])
|
||||||
|
cube([jaw_length * 0.7, inner_span, JAW_THICKNESS + 0.5]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// EAR BOSS (M3 attachment point)
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// A small raised button with a through-hole, providing optional redundant
|
||||||
|
// attachment for straps or hard-wired retention.
|
||||||
|
//
|
||||||
|
|
||||||
|
module ear_boss() {
|
||||||
|
difference() {
|
||||||
|
cylinder(d=EAR_D + 2*EAR_WALL_T, h=EAR_H);
|
||||||
|
translate([0, 0, -1])
|
||||||
|
cylinder(d=EAR_D, h=EAR_H + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// UTILITY: Rounded Rectangle (for base and ghosts)
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
module rounded_rect(size, r) {
|
||||||
|
// size = [width, length, height]
|
||||||
|
w = size[0];
|
||||||
|
l = size[1];
|
||||||
|
h = size[2];
|
||||||
|
|
||||||
|
linear_extrude(height=h)
|
||||||
|
offset(r=r)
|
||||||
|
offset(r=-r)
|
||||||
|
square([w, l], center=true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// EXPORT / PRINT INSTRUCTIONS
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// CLIP 5mm (3D print × N):
|
||||||
|
// openscad cable_management_clips.scad -D 'RENDER="clip_5mm"' -o clip_5mm.stl
|
||||||
|
// Print settings: PETG/ASA, 4 perimeters, 20% infill, 0.2 mm layer
|
||||||
|
// Orientation: base flat on bed (smooth finish for adhesive)
|
||||||
|
//
|
||||||
|
// CLIP 8mm (3D print × N):
|
||||||
|
// openscad cable_management_clips.scad -D 'RENDER="clip_8mm"' -o clip_8mm.stl
|
||||||
|
// Print settings: Same as 5mm
|
||||||
|
//
|
||||||
|
// CLIP 12mm (3D print × N):
|
||||||
|
// openscad cable_management_clips.scad -D 'RENDER="clip_12mm"' -o clip_12mm.stl
|
||||||
|
// Print settings: Same as 5mm
|
||||||
|
//
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// INSTALLATION GUIDE
|
||||||
|
//
|
||||||
|
// 1. SURFACE PREP
|
||||||
|
// • Clean chassis surface with isopropyl alcohol.
|
||||||
|
// • Let dry for 5 minutes; inspect for dust or residue.
|
||||||
|
//
|
||||||
|
// 2. ADHESIVE APPLICATION
|
||||||
|
// • Cut 3M VHB 5952F into ~50 × 40 mm pads (one per clip).
|
||||||
|
// • Peel foil backing from VHB pad.
|
||||||
|
// • Center pad on clip base; press firmly for 30 seconds.
|
||||||
|
// • Peel clear polyester liner from exposed adhesive.
|
||||||
|
//
|
||||||
|
// 3. MOUNTING
|
||||||
|
// • Position clip on chassis surface (e.g., along frame rail).
|
||||||
|
// • Press and hold for 30 seconds, applying full body weight if possible.
|
||||||
|
// • Let cure for 24 hours before loading cables.
|
||||||
|
//
|
||||||
|
// 4. CABLE INSERTION
|
||||||
|
// • Gather cable bundle (power, signal, etc.); inspect for knots/damage.
|
||||||
|
// • Align bundle perpendicular to clip jaws.
|
||||||
|
// • Press upward with steady pressure until jaws snap closed (audible click).
|
||||||
|
// • Tension should hold cable 5–10 N without slip.
|
||||||
|
//
|
||||||
|
// 5. ZIP-TIE ANCHORING (optional extra security)
|
||||||
|
// • Thread 3.6 mm nylon zip-tie through jaw anchor tabs (left and right).
|
||||||
|
// • Route around cable bundle; cinch to desired tension (avoid crushing).
|
||||||
|
// • Trim excess tie length.
|
||||||
|
//
|
||||||
|
// 6. THREADED INSERTION (optional M3 redundancy)
|
||||||
|
// • Install M3 threaded insert into ear hole (using M3 insertion tool).
|
||||||
|
// • Thread M3 × 16 mm bolt with split washer through ear.
|
||||||
|
// • Tighten 1.5 N·m (firm but not excessive).
|
||||||
|
//
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// CABLE ROUTING BEST PRACTICES
|
||||||
|
//
|
||||||
|
// • Power cables (main): Use 12mm clips, spacing 150–200 mm apart.
|
||||||
|
// • Mixed signal bundles: Use 8mm clips, spacing 100–150 mm apart.
|
||||||
|
// • Individual sensor leads: Use 5mm clips or traditional P-clips.
|
||||||
|
//
|
||||||
|
// • Avoid sharp bends: Route bundles with R ≥ 50 mm (cable bundle diameter).
|
||||||
|
// • Prevent abrasion: Use snap clips where cable crosses sharp edges.
|
||||||
|
// • Allow thermal expansion: Leave ~2–3 mm slack in long runs.
|
||||||
|
// • Color-code bundles: Use electrical tape or heatshrink before clipping.
|
||||||
|
//
|
||||||
|
// =============================================================================
|
||||||
Loading…
x
Reference in New Issue
Block a user