feat: coins arrondis (hull/spheres CORNER_RADIUS=6mm) + gorge joint O-ring normalisée

This commit is contained in:
Julien Holtzer 2026-02-08 12:45:10 +01:00
parent c341de345a
commit c976b7182e
2 changed files with 125 additions and 47 deletions

View file

@ -39,7 +39,7 @@ SHOW_ELECTRONICS = true; // PCB central + batterie (visualisation)
SHOW_PCBS = true; // PCBs anneau + bouchon dans les faces
SHOW_SECTION = false; // Coupe en section pour voir l'intérieur
EXPLODE = 0; // 0 = assemblé, 1 = vue éclatée (0 à 1 progressif)
EXPLODE = 1; // 0 = assemblé, 1 = vue éclatée (0 à 1 progressif)
// Distance d'éclatement
EXPLODE_DIST = 40 * EXPLODE;
@ -60,28 +60,11 @@ module frame() {
difference() {
union() {
// --- 12 arêtes du cube ---
// Arêtes selon X (4)
for (y = [-1, 1], z = [-1, 1]) {
translate([0, y * (half - edge_d/2), z * (half - edge_d/2)])
cube([CUBE_SIZE - 2*edge_d, edge_w, edge_d], center=true);
}
// Arêtes selon Y (4)
for (x = [-1, 1], z = [-1, 1]) {
translate([x * (half - edge_d/2), 0, z * (half - edge_d/2)])
cube([edge_d, CUBE_SIZE - 2*edge_d, edge_w], center=true);
}
// Arêtes selon Z (4)
for (x = [-1, 1], y = [-1, 1]) {
translate([x * (half - edge_d/2), y * (half - edge_d/2), 0])
cube([edge_d, edge_w, CUBE_SIZE - 2*edge_d], center=true);
}
// --- Squelette arrondi (12 arêtes + 8 coins sphériques) ---
_rounded_frame_skeleton();
// --- 8 coins ---
for (x = [-1, 1], y = [-1, 1], z = [-1, 1]) {
translate([x * (half - edge_d/2), y * (half - edge_d/2), z * (half - edge_d/2)])
cube([edge_d, edge_d, edge_d], center=true);
}
// --- Corniches de contact (surface plane pour joint O-ring) ---
_frame_contact_ledges();
// --- Plots de fixation (4 par face, 6 faces) ---
// Face +Z (dessus) et -Z (dessous)
@ -231,6 +214,91 @@ module _all_mount_holes() {
}
}
// Cube arrondi (hull de 8 sphères aux coins)
module _rounded_cube(size, r) {
hull() {
c = size/2 - r;
for (x = [-1, 1], y = [-1, 1], z = [-1, 1])
translate([x*c, y*c, z*c])
sphere(r=r);
}
}
// Squelette arrondi : coque arrondie évidée + ouvertures pour les 6 faces
module _rounded_frame_skeleton() {
half = CUBE_SIZE / 2;
r = CORNER_RADIUS;
edge_d = FRAME_EDGE_DEPTH;
opening = CUBE_SIZE - 2 * edge_d;
difference() {
// Coque extérieure arrondie
_rounded_cube(CUBE_SIZE, r);
// Évidement intérieur
cube([opening, opening, opening], center=true);
// Ouvertures pour les 6 faces (traversées)
cube([opening, opening, CUBE_SIZE + 2], center=true); // ±Z
cube([CUBE_SIZE + 2, opening, opening], center=true); // ±X
cube([opening, CUBE_SIZE + 2, opening], center=true); // ±Y
}
}
// Corniches plates sur chaque face du squelette
// Surface de contact plane pour l'assise du joint O-ring et la fixation
module _frame_contact_ledges() {
half = CUBE_SIZE / 2;
edge_d = FRAME_EDGE_DEPTH;
lw = FRAME_LEDGE_WIDTH;
lh = FRAME_LEDGE_HEIGHT;
opening = CUBE_SIZE - 2 * edge_d;
outer = opening + 2 * lw;
// Corniche sur chaque face : anneau plat (outer - opening)
// +Z et -Z
for (z = [-1, 1]) {
translate([0, 0, z * (half - edge_d + (z > 0 ? 0 : -lh))])
difference() {
linear_extrude(lh)
offset(r=CORNER_RADIUS)
offset(delta=-CORNER_RADIUS)
square([outer, outer], center=true);
translate([0, 0, -0.5])
linear_extrude(lh + 1)
square([opening, opening], center=true);
}
}
// +Y et -Y
for (y_dir = [-1, 1]) {
translate([0, y_dir * (half - edge_d + (y_dir > 0 ? 0 : -lh)), 0])
rotate([90, 0, 0])
difference() {
linear_extrude(lh)
offset(r=CORNER_RADIUS)
offset(delta=-CORNER_RADIUS)
square([outer, outer], center=true);
translate([0, 0, -0.5])
linear_extrude(lh + 1)
square([opening, opening], center=true);
}
}
// +X et -X
for (x_dir = [-1, 1]) {
translate([x_dir * (half - edge_d + (x_dir > 0 ? 0 : -lh)), 0, 0])
rotate([0, 90, 0])
difference() {
linear_extrude(lh)
offset(r=CORNER_RADIUS)
offset(delta=-CORNER_RADIUS)
square([outer, outer], center=true);
translate([0, 0, -0.5])
linear_extrude(lh + 1)
square([opening, opening], center=true);
}
}
}
// Canaux pour le passage des nappes/câbles JST vers chaque face
module _cable_channels() {
ch_w = 10; // Largeur du canal
@ -275,18 +343,20 @@ module face_standard() {
difference() {
union() {
// --- Coque extérieure ---
// Plaque principale
// --- Coque extérieure (coins arrondis) ---
difference() {
// Plaque pleine
translate([0, 0, FACE_TOTAL_DEPTH / 2])
cube([face_size - 2*edge_d + 6, face_size - 2*edge_d + 6, FACE_TOTAL_DEPTH], center=true);
// Évidement intérieur (laisser les parois)
translate([0, 0, FACE_TOTAL_DEPTH / 2 + WALL_THICKNESS])
cube([face_size - 2*edge_d + 6 - 2*WALL_THICKNESS,
face_size - 2*edge_d + 6 - 2*WALL_THICKNESS,
FACE_TOTAL_DEPTH], center=true);
// Parois extérieures avec coins arrondis
linear_extrude(FACE_TOTAL_DEPTH)
offset(r=CORNER_RADIUS)
offset(delta=-CORNER_RADIUS)
square([face_size - 2*edge_d + 6, face_size - 2*edge_d + 6], center=true);
// Évidement intérieur
translate([0, 0, WALL_THICKNESS])
linear_extrude(FACE_TOTAL_DEPTH)
offset(r=max(0.5, CORNER_RADIUS - WALL_THICKNESS))
offset(delta=-max(0.5, CORNER_RADIUS - WALL_THICKNESS))
square([face_size - 2*edge_d + 6 - 2*WALL_THICKNESS,
face_size - 2*edge_d + 6 - 2*WALL_THICKNESS], center=true);
}
// --- Membrane tactile (centre, amincie) ---
@ -321,15 +391,11 @@ module face_standard() {
}
}
// Plaque extérieure de la face (la surface visible)
// Plaque extérieure de la face (surface visible, coins arrondis)
module _face_outer_plate(size) {
// Plaque pleine, épaisseur = WALL_THICKNESS, avec le centre aminci
difference() {
cube([size, size, WALL_THICKNESS], center=true);
// Le centre sera aminci séparément
}
translate([0, 0, -WALL_THICKNESS/2])
linear_extrude(WALL_THICKNESS)
offset(r=CORNER_RADIUS)
offset(delta=-CORNER_RADIUS)
square([size, size], center=true);
}
@ -381,15 +447,24 @@ module _face_mount_holes() {
}
}
// Rainure pour joint torique périphérique
// Rainure pour joint torique O-ring
// Gorge rectangulaire continue suivant le contour arrondi de la face
// Dimensions selon norme : largeur ~1.4ר cordon, profondeur ~0.7ר cordon
module _seal_groove(size) {
w = FACE_SEAL_GROOVE_W;
d = FACE_SEAL_GROOVE_D;
offset = size/2 - w - 1;
inset = 3; // Retrait depuis le bord extérieur
linear_extrude(d + 0.1)
difference() {
cube([size - 2, size - 2, d], center=true);
cube([size - 2 - 2*w, size - 2 - 2*w, d + 1], center=true);
// Contour extérieur de la gorge (suit l'arrondi des coins)
offset(r=CORNER_RADIUS - inset)
offset(delta=-(CORNER_RADIUS - inset))
square([size - 2*inset, size - 2*inset], center=true);
// Contour intérieur de la gorge
offset(r=max(0.5, CORNER_RADIUS - inset - w))
offset(delta=-max(0.5, CORNER_RADIUS - inset - w))
square([size - 2*inset - 2*w, size - 2*inset - 2*w], center=true);
}
}

View file

@ -20,13 +20,16 @@ FRAME_MOUNT_DIAM = 3.2; // Diamètre des trous de fixation M3
FRAME_MOUNT_HEAD = 5.8; // Diamètre de la tête de vis M3
FRAME_MOUNT_DEPTH = 3; // Profondeur du lamage tête de vis
FRAME_SCREWS_PER_FACE = 4; // Nombre de vis par face
FRAME_LEDGE_WIDTH = 5; // Largeur corniche de contact (face squelette)
FRAME_LEDGE_HEIGHT = 3; // Épaisseur de la corniche plate
// --- Faces ------------------------------------------------------------------
FACE_TOTAL_DEPTH = 14; // Profondeur totale d'un module face (du bord ext.)
FACE_CENTER_DIAM = 40; // Diamètre de la zone tactile centrale
FACE_MEMBRANE_T = 1.0; // Épaisseur de la membrane tactile (centre)
FACE_SEAL_GROOVE_W = 1.5; // Largeur de la rainure joint torique
FACE_SEAL_GROOVE_D = 1.5; // Profondeur de la rainure joint torique
SEAL_CORD_DIAM = 2.0; // Diamètre du cordon torique (joint O-ring)
FACE_SEAL_GROOVE_W = 2.8; // Largeur rainure = ~1.4 × cordon
FACE_SEAL_GROOVE_D = 1.4; // Profondeur rainure = ~0.7 × cordon
// --- LEDs (PCB Anneau Étage B) --------------------------------------------
LED_COUNT = 12; // Nombre de WS2812B par face