2020 Slot Cable Clip
A quarter-turn cable clip for the 6 mm slot of 2020 aluminium extrusion. Its narrow head goes into the slot, and a quarter turn hooks it behind both slot lips; two square corners on the head stop the turn so it cannot over-rotate. A snap ring with an opening narrower than the cable then holds a cable bundle running along the profile. The default clip for an 8 mm bundle measures 16 x 16.6 x 8 mm. Print it standing on its edge as modeled, with no supports. Adjustable parameters: cable diameter, snap tightness, clip width, slot width, lip thickness, cavity width and slot clearance.
# 2020 Cable Clip - quarter-turn clip that locks into the slot and holds a cable bundle
#
# Use: hold the clip with the cable channel across the slot, push the narrow
# head into the 6 mm slot of a 2020 extrusion and turn it a quarter turn (it
# turns one way only and stops). The head then hooks behind both slot lips and
# the base pad sits on the profile face, with the cable channel running along
# the profile. Press the cable bundle into the snap opening. Turn back to remove.
#
# Print orientation: as modeled, standing on the edge (Z = along the slot once
# fitted). The channel is a vertical extrusion, the neck is an octagon and the
# cut corners of the head are 45 deg, so no supports are needed.
# Axes: X = across the slot, Y = out of the profile face (head at Y < 0), Z = along the slot.
#
# Assumed 2020 slot dimensions (B-type, 6 mm slot) - adjust to your extrusion.
@param 3..16..0.5 desc:"Cable or bundle diameter (mm)"
cable_d = 8
@param 0.55..0.9..0.05 desc:"Snap opening / cable diameter (smaller = tighter)"
snap = 0.7
@param 6..16 desc:"Clip width along the profile (mm)"
clip_w = 8
@param 5.6..6.6..0.1 group:"Extrusion" desc:"Slot opening width (mm, assumed 6.2)"
slot_w = 6.2
@param 1.5..2.2..0.05 group:"Extrusion" desc:"Slot lip thickness (mm, assumed 1.8)"
lip_t = 1.8
@param 10..12..0.1 group:"Extrusion" desc:"Inner cavity width behind the lips (mm, assumed 11)"
cavity_w = 11
@param 0.1..0.4..0.05 group:"Extrusion" desc:"Head and neck clearance per side (mm)"
slot_clear = 0.2
# --- Head: cam-shaped plate behind the lips ---
hw = slot_w - slot_clear * 2 # head width, fits through the slot opening
hl = cavity_w - slot_clear * 2 - 0.2 # head length, spans the cavity after the turn
head_t = 2.4 # head thickness (cavity depth behind the lip is ~4)
neck_len = lip_t + 0.15 # snug over the lip
cr = cavity_w / 2 - slot_clear # radius the cut corners must stay inside
ha = hl / 2
hb = hw / 2
hc = min(ha + sqrt(cr ** 2 - ha ** 2), hb + sqrt(cr ** 2 - hb ** 2)) - 0.05 # 45 deg corner cut: x + z = hc
zc = hb # head and neck axis height (head bottom on the bed)
head = workplane XZ
| polyline [(hb - hc, zc - hb), (ha, zc - hb), (ha, zc + hc - ha), (hc - hb, zc + hb), (-ha, zc + hb), (-ha, zc - hc + ha)]
| extrude head_t | translate 0 (-(neck_len + head_t)) 0
# --- Neck: octagon (flat bottom, 45 deg facets) that turns inside the slot opening ---
nr = slot_w / 2 - slot_clear # circumradius
neck = workplane XZ | polygon 8 nr | rotate 22.5
| extrude (neck_len + 0.5) | translate 0 (-neck_len) zc
# --- Body: base pad + snap ring for the cable, drawn on XY and extruded along Z ---
clear = 0.3 # cable clearance per side
r_in = cable_d / 2 + clear
wall = 2
r_out = r_in + wall
pad_t = 3
pad_w = max(16, r_out * 2)
yc = pad_t + r_in - 0.5 # ring center
gap = cable_d * snap # snap opening (narrower than the cable)
flare = 1.2 # entry chamfer per side
top = yc + r_out
pad = rect pad_w pad_t at:(0, pad_t / 2)
ring = circle r_out at:(0, yc)
bore = circle r_in at:(0, yc)
entry = polyline [(-gap / 2, yc), (gap / 2, yc), (gap / 2, top - flare), (gap / 2 + flare, top + 0.5), (-gap / 2 - flare, top + 0.5), (-gap / 2, top - flare)]
body = (pad + ring - bore - entry) | extrude clip_w
clip = body + neck + head
# --- Intent ---
assert hl > slot_w + 3 # hooks at least 1.5 mm behind each lip
assert sqrt(ha ** 2 + hb ** 2) > cavity_w / 2 # square corners stop the turn
assert nr * 2 < slot_w # neck turns inside the opening
assert gap < cable_d
assert clip.solids == 1
assert clip.bbox.min[2] ~ 0 tol:0.01
assert clip.bbox.x ~ max(pad_w, hl)
assert body.bbox.y > yc + r_in and body.bbox.y < top # ring rim stays above the cable
assert clip.bbox.y ~ body.bbox.y + neck_len + head_t
assert neck.bbox.center[0] ~ 0 tol:0.01
assert neck.bbox.center[2] ~ zc tol:0.01
assert clip.bbox.z ~ max(clip_w, hw)
clip