Skip to content

Instantly share code, notes, and snippets.

@brahimmachkouri
Last active June 16, 2026 12:40
Show Gist options
  • Select an option

  • Save brahimmachkouri/dad6c303edceae9bba49af1bdccf6550 to your computer and use it in GitHub Desktop.

Select an option

Save brahimmachkouri/dad6c303edceae9bba49af1bdccf6550 to your computer and use it in GitHub Desktop.
Capsule porte-clé — Double bouchon dévissable + anneau - !! NON FINALISÉ !!
// =====================================================================
// CAPSULE PORTE-CLÉ — double bouchon dévissable + œillet évasé
// =====================================================================
// FDM / PLA. Filets via threads.scad (rcolyer, CC0).
// -> threads.scad doit être dans le même dossier.
// https://www.thingiverse.com/thing:1686322
// =====================================================================
use <threads.scad>
/* [Dimensions principales] */
inner_d = 13;
inner_len = 37;
wall = 2.0;
/* [Filetage] */
thread_len = 7;
thread_pitch = 1.5;
thread_depth = 0.65;
thread_angle = 55;
thread_tol = 0.35;
/* [Bouchons] */
cap_wall = 2.0;
cap_skirt_extra= 0.7;
/* [Œillet porte-clé] */
ring_outer_d = 12;
ring_hole_d = 5.5;
ring_neck_h = 6.5;
ring_base_w = 12;
ring_top_w = 5;
/* [Qualité] */
$fn = 96;
/* [Affichage] */
show = "all"; // [all, body, cap_plain, cap_ring, assembled]
//show = "assembled";
// ---- Dérivés -------------------------------------------------------
body_inner_r = inner_d / 2;
thread_outer_d = inner_d + 2 * wall;
bore_clear_r = thread_outer_d / 2 + thread_tol;
cap_outer_r = bore_clear_r + cap_skirt_extra;
eps = 0.02;
// =====================================================================
// CORPS : tube + filet mâle aux deux extrémités
// =====================================================================
module body() {
total = inner_len + 2 * thread_len;
difference() {
union() {
// partie centrale
translate([0, 0, thread_len])
cylinder(h = inner_len, r = thread_outer_d / 2);
// filet bas
ScrewThread(
thread_outer_d,
thread_len,
pitch = thread_pitch,
tooth_angle = thread_angle,
tooth_height = thread_depth,
tolerance = 0
);
// filet haut inversé
translate([0, 0, total])
mirror([0, 0, 1])
ScrewThread(
thread_outer_d,
thread_len,
pitch = thread_pitch,
tooth_angle = thread_angle,
tooth_height = thread_depth,
tolerance = 0
);
}
// passage intérieur
translate([0, 0, -eps])
cylinder(h = total + 2 * eps, r = body_inner_r);
}
}
// =====================================================================
// BOUCHON : jupe moletée + taraudage femelle
// =====================================================================
module cap(with_ring=false) {
h_thread = thread_len + 0.8;
total_h = h_thread + cap_wall;
// rayon au fond du taraudage femelle
female_minor_r = thread_outer_d/2 - thread_depth + thread_tol;
difference() {
union() {
knurled_skirt(total_h, cap_outer_r);
// fond plein du bouchon
translate([0, 0, h_thread])
cylinder(h = cap_wall, r = cap_outer_r);
}
// 1) perçage au diamètre mineur
translate([0,0,-eps])
cylinder(h = h_thread + 2*eps, r = female_minor_r);
// 2) profil hélicoïdal pour former le taraudage
translate([0,0,-eps])
ScrewThread(
thread_outer_d + 2*thread_tol,
h_thread + 2*eps,
pitch = thread_pitch,
tooth_angle = thread_angle,
tooth_height = thread_depth,
tolerance = 0
);
// 3) léger chanfrein d'entrée
translate([0,0,-eps])
cylinder(
h = 0.8,
r1 = thread_outer_d/2 + thread_tol + 0.35,
r2 = female_minor_r
);
}
if (!with_ring) {
translate([0,0,total_h - eps])
cylinder(h = 0.6, r1 = cap_outer_r, r2 = cap_outer_r - 0.6);
}
if (with_ring) {
translate([0,0,total_h - 0.8])
keyring();
}
}
// =====================================================================
// MOLETAGE SIMPLE
// =====================================================================
module knurled_skirt(h, r) {
n = floor(2 * PI * r / 1.5);
union() {
cylinder(h = h, r = r);
for (i = [0 : n - 1]) {
rotate([0, 0, 360 * i / n])
translate([r, 0, 0])
cylinder(h = h, r = 0.45, $fn = 8);
}
}
}
// =====================================================================
// ŒILLET renforcé
// =====================================================================
module keyring() {
R = (ring_outer_d + ring_hole_d) / 4;
sr = (ring_outer_d - ring_hole_d) / 4;
eye_z = ring_neck_h + R;
union() {
// embase renforcée sur le bouchon
hull() {
translate([0, 0, 0.2])
cylinder(h = 0.4, r = ring_base_w / 2);
translate([0, 0, 1.8])
cylinder(h = 0.4, r = ring_base_w / 2 - 1.2);
}
// col arrondi
hull() {
for (sx = [-1, 1])
translate([sx * (ring_base_w / 2 - sr), 0, sr])
sphere(r = sr);
for (sx = [-1, 1])
translate([sx * (ring_top_w / 2 - sr), 0, ring_neck_h - sr])
sphere(r = sr);
}
// anneau torique
translate([0, 0, eye_z])
rotate([90, 0, 0])
rotate_extrude($fn = $fn)
translate([R, 0])
circle(r = sr);
}
}
// =====================================================================
// AFFICHAGE
// =====================================================================
spacing = cap_outer_r * 2 + 8;
if (show == "all") {
body();
translate([-spacing, 0, 0])
cap(true);
translate([spacing, 0, 0])
cap(false);
} else if (show == "body") {
body();
} else if (show == "cap_plain") {
cap(false);
} else if (show == "cap_ring") {
cap(true);
} else if (show == "assembled") {
total = inner_len + 2 * thread_len;
h_thread = thread_len + 0.8;
total_h = h_thread + cap_wall;
body();
// bouchon du haut : PAS de rotation
translate([0, 0, total - eps])
cap(false);
// bouchon du bas : retourné
translate([0, 0, eps])
rotate([180, 0, 0])
cap(true);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment