feat: modèle 3D OpenSCAD — squelette + 6 faces modulaires, paramétrique
This commit is contained in:
parent
95e3cb5c3b
commit
c341de345a
3 changed files with 806 additions and 0 deletions
72
3d-model/README.md
Normal file
72
3d-model/README.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Modèle 3D — Companion Cube
|
||||
|
||||
## Architecture : Squelette + 6 Faces Modulaires
|
||||
|
||||
```
|
||||
┌───────────────┐
|
||||
/│ /│
|
||||
/ │ Face 1 / │ Face 1 = Dessus (NFC)
|
||||
/ │ (NFC) / │ Face 2 = Avant
|
||||
┌───────────────┐ │ Face 3 = Droite
|
||||
│ │ │ │ Face 4 = Arrière
|
||||
│ │ Face 5 │ │ Face 3 Face 5 = Gauche
|
||||
│ │ (Gauche) │ │(Droite) Face 6 = Dessous (Qi)
|
||||
│ └───────────│───┘
|
||||
│ / Face 4 │ /
|
||||
│ / (Arrière) │ /
|
||||
│/ │/
|
||||
└───────────────┘
|
||||
Face 2 (Avant)
|
||||
Face 6 (Qi, dessous)
|
||||
```
|
||||
|
||||
## Fichiers
|
||||
|
||||
| Fichier | Description |
|
||||
|---------|-------------|
|
||||
| `cube-config.scad` | Paramètres dimensionnels (modifier ici pour ajuster) |
|
||||
| `cube-assembly.scad` | Modèle principal — ouvrir dans OpenSCAD |
|
||||
|
||||
## Utilisation
|
||||
|
||||
1. **Installer OpenSCAD** : https://openscad.org/
|
||||
2. **Ouvrir** `cube-assembly.scad`
|
||||
3. **Prévisualiser** : F5 (aperçu rapide) ou F6 (rendu complet)
|
||||
|
||||
### Contrôles de visualisation
|
||||
|
||||
Dans `cube-assembly.scad`, modifier les variables en haut du fichier :
|
||||
|
||||
```openscad
|
||||
SHOW_FRAME = true; // Squelette
|
||||
SHOW_FACE_TOP = true; // Face dessus (NFC)
|
||||
SHOW_ELECTRONICS = true; // Batterie + PCB central
|
||||
SHOW_SECTION = false; // Vue en coupe
|
||||
|
||||
EXPLODE = 0; // 0 = assemblé, 1 = vue éclatée
|
||||
```
|
||||
|
||||
### Export STL pour impression
|
||||
|
||||
1. Décommenter le module souhaité en bas de `cube-assembly.scad`
|
||||
2. Commenter `assembly()`
|
||||
3. F6 → File → Export as STL
|
||||
|
||||
### Pièces à imprimer
|
||||
|
||||
| Pièce | Quantité | Matériau | Notes |
|
||||
|-------|----------|----------|-------|
|
||||
| `frame` (squelette) | 1 | PLA/PETG opaque gris | Structurel |
|
||||
| `face-standard` | 4 | PETG translucide | Diffusion LED |
|
||||
| `face-nfc` | 1 | PETG translucide | Dessus, membrane fine NFC |
|
||||
| `face-qi` | 1 | PETG translucide | Dessous, aminci pour Qi |
|
||||
|
||||
## Paramètres clés
|
||||
|
||||
| Paramètre | Valeur | Impact |
|
||||
|-----------|--------|--------|
|
||||
| `CUBE_SIZE` | 120 mm | Taille globale |
|
||||
| `WALL_THICKNESS` | 2.5 mm | Solidité vs poids |
|
||||
| `FACE_MEMBRANE_T` | 1.0 mm | Sensibilité tactile |
|
||||
| `RING_SHROUD_HEIGHT` | 6 mm | Qualité de diffusion LED |
|
||||
| `PRINT_TOLERANCE` | 0.2 mm | Ajuster selon votre imprimante |
|
||||
648
3d-model/cube-assembly.scad
Normal file
648
3d-model/cube-assembly.scad
Normal file
|
|
@ -0,0 +1,648 @@
|
|||
// ============================================================================
|
||||
// Companion Cube — Modèle 3D Complet
|
||||
// Version : 0.2.0
|
||||
// Architecture : Squelette interne + 6 faces modulaires vissées
|
||||
// ============================================================================
|
||||
//
|
||||
// STRUCTURE :
|
||||
// 1. Squelette (frame) — Structure porteuse interne en forme de cube
|
||||
// 2. Face Standard (x4) — Module face : coque + shroud + emplacements PCB
|
||||
// 3. Face NFC (dessus) — Comme standard + logement PN532
|
||||
// 4. Face Qi (dessous) — Comme standard + logement bobine Qi
|
||||
// 5. Électronique — PCB central, batterie (visualisation)
|
||||
//
|
||||
// ASSEMBLAGE :
|
||||
// 1. Monter le PCB central + batterie dans le squelette
|
||||
// 2. Câbler les connecteurs JST vers chaque face
|
||||
// 3. Assembler chaque module face (PCB Anneau + PCB Bouchon dans la coque)
|
||||
// 4. Visser chaque module face sur le squelette (4x M3 par face)
|
||||
//
|
||||
// UTILISATION :
|
||||
// - Ouvrir dans OpenSCAD
|
||||
// - Variable `SHOW_*` pour afficher/masquer les pièces
|
||||
// - Variable `EXPLODE` pour la vue éclatée
|
||||
// - Modules individuels exportables en STL pour l'impression
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
include <cube-config.scad>
|
||||
|
||||
// --- Contrôle de l'affichage ------------------------------------------------
|
||||
SHOW_FRAME = true; // Squelette interne
|
||||
SHOW_FACE_TOP = true; // Face dessus (NFC)
|
||||
SHOW_FACE_BOTTOM = true; // Face dessous (Qi)
|
||||
SHOW_FACE_FRONT = true; // Face avant
|
||||
SHOW_FACE_BACK = true; // Face arrière
|
||||
SHOW_FACE_LEFT = true; // Face gauche
|
||||
SHOW_FACE_RIGHT = true; // Face droite
|
||||
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)
|
||||
|
||||
// Distance d'éclatement
|
||||
EXPLODE_DIST = 40 * EXPLODE;
|
||||
|
||||
// ============================================================================
|
||||
// MODULE : Squelette Interne (Frame)
|
||||
// ============================================================================
|
||||
// Le squelette est constitué des 12 arêtes d'un cube, avec des plots de
|
||||
// fixation M3 sur chaque face intérieure (4 par face = 24 total).
|
||||
// Il accueille le PCB central et la batterie en son centre.
|
||||
// ============================================================================
|
||||
|
||||
module frame() {
|
||||
half = CUBE_SIZE / 2;
|
||||
edge_w = FRAME_EDGE_WIDTH;
|
||||
edge_d = FRAME_EDGE_DEPTH;
|
||||
inner = CUBE_SIZE - 2 * edge_d;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// --- 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);
|
||||
}
|
||||
|
||||
// --- Plots de fixation (4 par face, 6 faces) ---
|
||||
// Face +Z (dessus) et -Z (dessous)
|
||||
for (z = [-1, 1]) {
|
||||
for (xy = [
|
||||
[ (half - edge_d - 10), (half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), (half - edge_d - 10)],
|
||||
[ (half - edge_d - 10), -(half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), -(half - edge_d - 10)]
|
||||
]) {
|
||||
translate([xy[0], xy[1], z * (half - edge_d)])
|
||||
_mount_post(z);
|
||||
}
|
||||
}
|
||||
// Face +Y (arrière) et -Y (avant)
|
||||
for (y_dir = [-1, 1]) {
|
||||
for (xz = [
|
||||
[ (half - edge_d - 10), (half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), (half - edge_d - 10)],
|
||||
[ (half - edge_d - 10), -(half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), -(half - edge_d - 10)]
|
||||
]) {
|
||||
translate([xz[0], y_dir * (half - edge_d), xz[1]])
|
||||
rotate([y_dir * 90, 0, 0])
|
||||
_mount_post(1);
|
||||
}
|
||||
}
|
||||
// Face +X (droite) et -X (gauche)
|
||||
for (x_dir = [-1, 1]) {
|
||||
for (yz = [
|
||||
[ (half - edge_d - 10), (half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), (half - edge_d - 10)],
|
||||
[ (half - edge_d - 10), -(half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), -(half - edge_d - 10)]
|
||||
]) {
|
||||
translate([x_dir * (half - edge_d), yz[0], yz[1]])
|
||||
rotate([0, x_dir * -90, 0])
|
||||
_mount_post(1);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Support batterie (berceau central) ---
|
||||
_battery_cradle();
|
||||
|
||||
// --- Support PCB central ---
|
||||
_central_pcb_mount();
|
||||
}
|
||||
|
||||
// --- Perçages des plots M3 ---
|
||||
_all_mount_holes();
|
||||
|
||||
// --- Passages de câbles (JST vers chaque face) ---
|
||||
_cable_channels();
|
||||
}
|
||||
}
|
||||
|
||||
// Plot de fixation cylindrique (s'élève vers la face)
|
||||
module _mount_post(direction) {
|
||||
post_h = 8;
|
||||
post_d = 7;
|
||||
translate([0, 0, direction > 0 ? 0 : -post_h])
|
||||
cylinder(d=post_d, h=post_h);
|
||||
}
|
||||
|
||||
// Berceau pour la batterie LiPo
|
||||
module _battery_cradle() {
|
||||
bw = BATT_WIDTH + 2 * BATT_TOLERANCE + 4; // +4 pour les parois
|
||||
bl = BATT_LENGTH + 2 * BATT_TOLERANCE + 4;
|
||||
bh = BATT_HEIGHT + BATT_TOLERANCE + 2;
|
||||
wall = 2;
|
||||
|
||||
// Position : centré, décalé vers le bas pour laisser de la place au PCB central au-dessus
|
||||
translate([0, 0, -10])
|
||||
difference() {
|
||||
cube([bl, bw, bh], center=true);
|
||||
translate([0, 0, wall])
|
||||
cube([bl - 2*wall, bw - 2*wall, bh], center=true);
|
||||
// Ouverture pour les fils
|
||||
translate([0, bw/2, 0])
|
||||
cube([20, wall*3, bh - wall], center=true);
|
||||
}
|
||||
}
|
||||
|
||||
// Supports pour le PCB central (4 entretoises)
|
||||
module _central_pcb_mount() {
|
||||
standoff_h = 5;
|
||||
standoff_d = 6;
|
||||
hole_d = 2.5; // Pour vis M2.5 ou insert
|
||||
|
||||
pcb_mount_offset = 8; // Au-dessus du centre (batterie en dessous)
|
||||
|
||||
for (x = [-1, 1], y = [-1, 1]) {
|
||||
translate([
|
||||
x * (CENTRAL_PCB_LENGTH/2 - 5),
|
||||
y * (CENTRAL_PCB_WIDTH/2 - 5),
|
||||
pcb_mount_offset
|
||||
])
|
||||
difference() {
|
||||
cylinder(d=standoff_d, h=standoff_h);
|
||||
cylinder(d=hole_d, h=standoff_h + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Perçage de tous les trous M3 (traversant les plots)
|
||||
module _all_mount_holes() {
|
||||
half = CUBE_SIZE / 2;
|
||||
edge_d = FRAME_EDGE_DEPTH;
|
||||
|
||||
// Face +Z et -Z
|
||||
for (z = [-1, 1]) {
|
||||
for (xy = [
|
||||
[ (half - edge_d - 10), (half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), (half - edge_d - 10)],
|
||||
[ (half - edge_d - 10), -(half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), -(half - edge_d - 10)]
|
||||
]) {
|
||||
translate([xy[0], xy[1], z * half])
|
||||
cylinder(d=FRAME_MOUNT_DIAM, h=20, center=true);
|
||||
}
|
||||
}
|
||||
// Face +Y et -Y
|
||||
for (y_dir = [-1, 1]) {
|
||||
for (xz = [
|
||||
[ (half - edge_d - 10), (half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), (half - edge_d - 10)],
|
||||
[ (half - edge_d - 10), -(half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), -(half - edge_d - 10)]
|
||||
]) {
|
||||
translate([xz[0], y_dir * half, xz[1]])
|
||||
rotate([90, 0, 0])
|
||||
cylinder(d=FRAME_MOUNT_DIAM, h=20, center=true);
|
||||
}
|
||||
}
|
||||
// Face +X et -X
|
||||
for (x_dir = [-1, 1]) {
|
||||
for (yz = [
|
||||
[ (half - edge_d - 10), (half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), (half - edge_d - 10)],
|
||||
[ (half - edge_d - 10), -(half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), -(half - edge_d - 10)]
|
||||
]) {
|
||||
translate([x_dir * half, yz[0], yz[1]])
|
||||
rotate([0, 90, 0])
|
||||
cylinder(d=FRAME_MOUNT_DIAM, h=20, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Canaux pour le passage des nappes/câbles JST vers chaque face
|
||||
module _cable_channels() {
|
||||
ch_w = 10; // Largeur du canal
|
||||
ch_h = 6; // Hauteur du canal
|
||||
half = CUBE_SIZE / 2;
|
||||
edge_d = FRAME_EDGE_DEPTH;
|
||||
|
||||
// Un canal par face, radial depuis le centre
|
||||
// +Z / -Z
|
||||
for (z = [-1, 1]) {
|
||||
translate([0, 0, z * (half - edge_d/2)])
|
||||
cube([ch_w, ch_h, edge_d + 2], center=true);
|
||||
}
|
||||
// +Y / -Y
|
||||
for (y = [-1, 1]) {
|
||||
translate([0, y * (half - edge_d/2), 0])
|
||||
cube([ch_w, edge_d + 2, ch_h], center=true);
|
||||
}
|
||||
// +X / -X
|
||||
for (x = [-1, 1]) {
|
||||
translate([x * (half - edge_d/2), 0, 0])
|
||||
cube([edge_d + 2, ch_w, ch_h], center=true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// MODULE : Face Standard
|
||||
// ============================================================================
|
||||
// Module face complet comprenant :
|
||||
// - Coque extérieure avec membrane tactile amincie au centre
|
||||
// - Rainure pour joint torique (étanchéité visuelle)
|
||||
// - Ring Shroud (chambre de diffusion LEDs)
|
||||
// - Emplacements PCB Anneau (étage B) et PCB Bouchon (étage A)
|
||||
// - Trous de fixation M3 (alignés avec les plots du squelette)
|
||||
// ============================================================================
|
||||
|
||||
module face_standard() {
|
||||
half = CUBE_SIZE / 2;
|
||||
edge_d = FRAME_EDGE_DEPTH;
|
||||
face_size = CUBE_SIZE - 2 * PRINT_TOLERANCE;
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
// --- Coque extérieure ---
|
||||
// Plaque principale
|
||||
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);
|
||||
}
|
||||
|
||||
// --- Membrane tactile (centre, amincie) ---
|
||||
cylinder(d=FACE_CENTER_DIAM + 10, h=FACE_MEMBRANE_T);
|
||||
|
||||
// --- Paroi extérieure pleine (face visible) ---
|
||||
translate([0, 0, 0])
|
||||
_face_outer_plate(face_size - 2*edge_d + 6);
|
||||
|
||||
// --- Ring Shroud (chambre de diffusion) ---
|
||||
translate([0, 0, WALL_THICKNESS])
|
||||
_ring_shroud();
|
||||
|
||||
// --- Oreilles de fixation M3 ---
|
||||
_face_mount_ears();
|
||||
}
|
||||
|
||||
// --- Zone tactile amincie (creuser pour ne garder que 1mm) ---
|
||||
translate([0, 0, FACE_MEMBRANE_T])
|
||||
cylinder(d=FACE_CENTER_DIAM, h=FACE_TOTAL_DEPTH);
|
||||
|
||||
// --- Rainure joint torique ---
|
||||
translate([0, 0, FACE_TOTAL_DEPTH - 1])
|
||||
_seal_groove(face_size - 2*edge_d + 2);
|
||||
|
||||
// --- Trous de fixation M3 ---
|
||||
_face_mount_holes();
|
||||
|
||||
// --- Ouverture d'air centrale (côté intérieur) ---
|
||||
translate([0, 0, WALL_THICKNESS])
|
||||
cylinder(d=AIR_HOLE_DIAM, h=FACE_TOTAL_DEPTH);
|
||||
}
|
||||
}
|
||||
|
||||
// Plaque extérieure de la face (la surface visible)
|
||||
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)
|
||||
square([size, size], center=true);
|
||||
}
|
||||
|
||||
// Chambre de diffusion annulaire pour les LEDs
|
||||
module _ring_shroud() {
|
||||
ext = LED_RING_DIAM_EXT + 2 * RING_SHROUD_WALL;
|
||||
int_ = LED_RING_DIAM_INT - 2 * RING_SHROUD_WALL;
|
||||
|
||||
difference() {
|
||||
cylinder(d=ext, h=RING_SHROUD_HEIGHT);
|
||||
translate([0, 0, -0.5])
|
||||
cylinder(d=int_, h=RING_SHROUD_HEIGHT + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Oreilles de fixation (dépassent pour atteindre les plots du squelette)
|
||||
module _face_mount_ears() {
|
||||
half = CUBE_SIZE / 2;
|
||||
edge_d = FRAME_EDGE_DEPTH;
|
||||
ear_size = 10;
|
||||
|
||||
for (xy = [
|
||||
[ (half - edge_d - 10), (half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), (half - edge_d - 10)],
|
||||
[ (half - edge_d - 10), -(half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), -(half - edge_d - 10)]
|
||||
]) {
|
||||
translate([xy[0], xy[1], FACE_TOTAL_DEPTH/2])
|
||||
cube([ear_size, ear_size, FACE_TOTAL_DEPTH], center=true);
|
||||
}
|
||||
}
|
||||
|
||||
// Trous de fixation dans les oreilles
|
||||
module _face_mount_holes() {
|
||||
half = CUBE_SIZE / 2;
|
||||
edge_d = FRAME_EDGE_DEPTH;
|
||||
|
||||
for (xy = [
|
||||
[ (half - edge_d - 10), (half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), (half - edge_d - 10)],
|
||||
[ (half - edge_d - 10), -(half - edge_d - 10)],
|
||||
[-(half - edge_d - 10), -(half - edge_d - 10)]
|
||||
]) {
|
||||
translate([xy[0], xy[1], -1])
|
||||
cylinder(d=FRAME_MOUNT_DIAM, h=FACE_TOTAL_DEPTH + 2);
|
||||
// Lamage tête de vis (côté extérieur)
|
||||
translate([xy[0], xy[1], -1])
|
||||
cylinder(d=FRAME_MOUNT_HEAD, h=FRAME_MOUNT_DEPTH + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Rainure pour joint torique périphérique
|
||||
module _seal_groove(size) {
|
||||
w = FACE_SEAL_GROOVE_W;
|
||||
d = FACE_SEAL_GROOVE_D;
|
||||
offset = size/2 - w - 1;
|
||||
|
||||
difference() {
|
||||
cube([size - 2, size - 2, d], center=true);
|
||||
cube([size - 2 - 2*w, size - 2 - 2*w, d + 1], center=true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// MODULE : Face NFC (Dessus)
|
||||
// ============================================================================
|
||||
// Identique à la face standard mais avec un logement pour le module PN532
|
||||
// à la place du simple PCB Bouchon.
|
||||
// ============================================================================
|
||||
|
||||
module face_nfc() {
|
||||
difference() {
|
||||
union() {
|
||||
face_standard();
|
||||
|
||||
// Logement renforcé pour le PN532 (plus grand que le bouchon standard)
|
||||
translate([0, 0, WALL_THICKNESS + RING_SHROUD_HEIGHT])
|
||||
_nfc_mount();
|
||||
}
|
||||
|
||||
// Ouverture pour l'antenne NFC (dans la membrane)
|
||||
// L'antenne doit être au plus près de la surface pour une bonne lecture
|
||||
translate([0, 0, -1])
|
||||
cylinder(d=NFC_ANTENNA_DIAM, h=FACE_MEMBRANE_T + 2);
|
||||
}
|
||||
}
|
||||
|
||||
module _nfc_mount() {
|
||||
// Support carré pour le module PN532
|
||||
wall = 1.5;
|
||||
size = NFC_PCB_SIZE + 2 * wall + 2 * PRINT_TOLERANCE;
|
||||
inner = NFC_PCB_SIZE + 2 * PRINT_TOLERANCE;
|
||||
|
||||
difference() {
|
||||
cube([size, size, NFC_PCB_HEIGHT + 2], center=true);
|
||||
cube([inner, inner, NFC_PCB_HEIGHT + 3], center=true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// MODULE : Face Qi (Dessous)
|
||||
// ============================================================================
|
||||
// Identique à la face standard mais avec un logement pour la bobine Qi
|
||||
// et son PCB récepteur.
|
||||
// ============================================================================
|
||||
|
||||
module face_qi() {
|
||||
difference() {
|
||||
union() {
|
||||
face_standard();
|
||||
|
||||
// Logement bobine Qi
|
||||
translate([0, 0, WALL_THICKNESS])
|
||||
_qi_mount();
|
||||
}
|
||||
|
||||
// La bobine Qi doit être au plus près de la surface extérieure
|
||||
// Amincissement supplémentaire au centre pour la bobine
|
||||
translate([0, 0, -0.5])
|
||||
cylinder(d=QI_COIL_DIAM + 4, h=WALL_THICKNESS - 0.8 + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
module _qi_mount() {
|
||||
wall = 1.5;
|
||||
// Anneau de maintien pour la bobine
|
||||
difference() {
|
||||
cylinder(d=QI_COIL_DIAM + 2*wall + 2*PRINT_TOLERANCE, h=QI_COIL_HEIGHT + 1);
|
||||
translate([0, 0, -0.5])
|
||||
cylinder(d=QI_COIL_DIAM + 2*PRINT_TOLERANCE, h=QI_COIL_HEIGHT + 2);
|
||||
}
|
||||
// Support PCB récepteur Qi (décalé)
|
||||
translate([0, QI_COIL_DIAM/2 + 5, 0])
|
||||
difference() {
|
||||
cube([QI_PCB_LENGTH + 2*wall, QI_PCB_WIDTH + 2*wall, QI_PCB_HEIGHT + 1], center=true);
|
||||
cube([QI_PCB_LENGTH + PRINT_TOLERANCE, QI_PCB_WIDTH + PRINT_TOLERANCE, QI_PCB_HEIGHT + 2], center=true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// MODULE : Électronique (Visualisation uniquement)
|
||||
// ============================================================================
|
||||
// Représentation simplifiée des composants pour vérifier l'encombrement.
|
||||
// Ne pas exporter en STL.
|
||||
// ============================================================================
|
||||
|
||||
module electronics() {
|
||||
// --- Batterie LiPo ---
|
||||
color(COLOR_BATTERY)
|
||||
translate([0, 0, -10])
|
||||
cube([BATT_LENGTH, BATT_WIDTH, BATT_HEIGHT], center=true);
|
||||
|
||||
// --- PCB Central ---
|
||||
color(COLOR_PCB)
|
||||
translate([0, 0, 8 + 5]) // Au-dessus de la batterie, sur les entretoises
|
||||
cube([CENTRAL_PCB_LENGTH, CENTRAL_PCB_WIDTH, CENTRAL_PCB_HEIGHT], center=true);
|
||||
|
||||
// --- ESP32-S3 module (sur le PCB central) ---
|
||||
color([0.15, 0.15, 0.15])
|
||||
translate([0, 0, 8 + 5 + CENTRAL_PCB_HEIGHT/2 + 1.5])
|
||||
cube([18, 18, 3], center=true);
|
||||
|
||||
// --- TP4056 (sur le PCB central) ---
|
||||
color(COLOR_PCB)
|
||||
translate([20, 0, 8 + 5 + CENTRAL_PCB_HEIGHT/2 + 1])
|
||||
cube([10, 8, 2], center=true);
|
||||
}
|
||||
|
||||
// PCB Anneau (visualisation, placé dans une face)
|
||||
module pcb_ring() {
|
||||
color(COLOR_PCB)
|
||||
difference() {
|
||||
cylinder(d=LED_RING_DIAM_EXT, h=LED_RING_HEIGHT);
|
||||
translate([0, 0, -0.5])
|
||||
cylinder(d=LED_RING_DIAM_INT, h=LED_RING_HEIGHT + 1);
|
||||
}
|
||||
|
||||
// LEDs WS2812B
|
||||
color(COLOR_LED)
|
||||
for (i = [0:LED_COUNT-1]) {
|
||||
angle = i * 360 / LED_COUNT;
|
||||
r = (LED_RING_DIAM_EXT + LED_RING_DIAM_INT) / 4;
|
||||
translate([r * cos(angle), r * sin(angle), LED_RING_HEIGHT])
|
||||
cube([5, 5, 1.5], center=true); // WS2812B = 5x5mm
|
||||
}
|
||||
}
|
||||
|
||||
// PCB Bouchon (visualisation, placé dans une face)
|
||||
module pcb_cap() {
|
||||
color(COLOR_PCB)
|
||||
cylinder(d=CAP_PCB_DIAM, h=CAP_PCB_HEIGHT);
|
||||
|
||||
// Pad capacitif (cuivre)
|
||||
color([0.8, 0.6, 0.2])
|
||||
translate([0, 0, CAP_PCB_HEIGHT])
|
||||
cylinder(d=CAP_PCB_DIAM - 5, h=0.1);
|
||||
}
|
||||
|
||||
// Module NFC PN532 (visualisation)
|
||||
module nfc_module() {
|
||||
color(COLOR_NFC) {
|
||||
cube([NFC_PCB_SIZE, NFC_PCB_SIZE, NFC_PCB_HEIGHT], center=true);
|
||||
// Antenne
|
||||
translate([0, 0, NFC_PCB_HEIGHT/2])
|
||||
cylinder(d=NFC_ANTENNA_DIAM, h=0.5);
|
||||
}
|
||||
}
|
||||
|
||||
// Bobine Qi (visualisation)
|
||||
module qi_coil() {
|
||||
color(COLOR_QI) {
|
||||
cylinder(d=QI_COIL_DIAM, h=QI_COIL_HEIGHT);
|
||||
// PCB récepteur
|
||||
translate([0, QI_COIL_DIAM/2 + 5, 0])
|
||||
cube([QI_PCB_LENGTH, QI_PCB_WIDTH, QI_PCB_HEIGHT], center=true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// ASSEMBLAGE PRINCIPAL
|
||||
// ============================================================================
|
||||
|
||||
module assembly() {
|
||||
half = CUBE_SIZE / 2;
|
||||
|
||||
// --- Squelette ---
|
||||
if (SHOW_FRAME)
|
||||
color(COLOR_FRAME) frame();
|
||||
|
||||
// --- Électronique interne ---
|
||||
if (SHOW_ELECTRONICS)
|
||||
electronics();
|
||||
|
||||
// --- Face Dessus (+Z) — NFC ---
|
||||
if (SHOW_FACE_TOP)
|
||||
translate([0, 0, half - FACE_TOTAL_DEPTH + EXPLODE_DIST])
|
||||
color(COLOR_FACE) face_nfc();
|
||||
|
||||
// --- Face Dessous (-Z) — Qi ---
|
||||
if (SHOW_FACE_BOTTOM)
|
||||
translate([0, 0, -(half - FACE_TOTAL_DEPTH) - EXPLODE_DIST])
|
||||
rotate([180, 0, 0])
|
||||
color(COLOR_FACE) face_qi();
|
||||
|
||||
// --- Face Avant (-Y) ---
|
||||
if (SHOW_FACE_FRONT)
|
||||
translate([0, -(half - FACE_TOTAL_DEPTH) - EXPLODE_DIST, 0])
|
||||
rotate([90, 0, 0])
|
||||
color(COLOR_FACE) face_standard();
|
||||
|
||||
// --- Face Arrière (+Y) ---
|
||||
if (SHOW_FACE_BACK)
|
||||
translate([0, (half - FACE_TOTAL_DEPTH) + EXPLODE_DIST, 0])
|
||||
rotate([-90, 0, 0])
|
||||
color(COLOR_FACE) face_standard();
|
||||
|
||||
// --- Face Gauche (-X) ---
|
||||
if (SHOW_FACE_LEFT)
|
||||
translate([-(half - FACE_TOTAL_DEPTH) - EXPLODE_DIST, 0, 0])
|
||||
rotate([0, -90, 0])
|
||||
color(COLOR_FACE) face_standard();
|
||||
|
||||
// --- Face Droite (+X) ---
|
||||
if (SHOW_FACE_RIGHT)
|
||||
translate([(half - FACE_TOTAL_DEPTH) + EXPLODE_DIST, 0, 0])
|
||||
rotate([0, 90, 0])
|
||||
color(COLOR_FACE) face_standard();
|
||||
|
||||
// --- PCBs dans les faces (visualisation) ---
|
||||
if (SHOW_PCBS) {
|
||||
// Anneau + bouchon dans chaque face (exemple face dessus)
|
||||
translate([0, 0, half - FACE_TOTAL_DEPTH + WALL_THICKNESS + RING_SHROUD_HEIGHT + EXPLODE_DIST]) {
|
||||
pcb_ring();
|
||||
translate([0, 0, LED_RING_HEIGHT + CAP_CONNECTOR_H])
|
||||
pcb_cap();
|
||||
}
|
||||
// NFC module (dessus)
|
||||
translate([0, 0, half - 8 + EXPLODE_DIST])
|
||||
nfc_module();
|
||||
// Qi coil (dessous)
|
||||
translate([0, 0, -(half - 4) - EXPLODE_DIST])
|
||||
qi_coil();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// RENDU
|
||||
// ============================================================================
|
||||
|
||||
if (SHOW_SECTION) {
|
||||
difference() {
|
||||
assembly();
|
||||
// Coupe en section (plan YZ, moitié +X)
|
||||
translate([CUBE_SIZE/2, 0, 0])
|
||||
cube([CUBE_SIZE, CUBE_SIZE * 2, CUBE_SIZE * 2], center=true);
|
||||
}
|
||||
} else {
|
||||
assembly();
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// MODULES D'EXPORT (décommenter pour exporter individuellement en STL)
|
||||
// ============================================================================
|
||||
|
||||
// Pour exporter une pièce : décommenter la ligne, commenter assembly(),
|
||||
// puis Exporter en STL (F6 → File → Export STL)
|
||||
|
||||
// frame(); // → frame.stl
|
||||
// face_standard(); // → face-standard.stl (x4)
|
||||
// face_nfc(); // → face-nfc.stl (x1, dessus)
|
||||
// face_qi(); // → face-qi.stl (x1, dessous)
|
||||
86
3d-model/cube-config.scad
Normal file
86
3d-model/cube-config.scad
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// ============================================================================
|
||||
// Companion Cube — Configuration Paramétrique
|
||||
// Version : 0.2.0
|
||||
// ============================================================================
|
||||
// Toutes les dimensions sont en millimètres.
|
||||
// Modifier ce fichier pour ajuster les dimensions sans toucher au modèle.
|
||||
// ============================================================================
|
||||
|
||||
// --- Dimensions Générales ---------------------------------------------------
|
||||
CUBE_SIZE = 120; // Arête extérieure du cube (mm)
|
||||
WALL_THICKNESS = 2.5; // Épaisseur des parois de la coque/face
|
||||
CORNER_RADIUS = 6; // Rayon des arrondis extérieurs
|
||||
CORNER_REINFORCE = 10; // Largeur des renforts de coins
|
||||
|
||||
// --- Squelette Interne (Frame) ----------------------------------------------
|
||||
FRAME_EDGE_WIDTH = 12; // Largeur des arêtes du squelette
|
||||
FRAME_EDGE_DEPTH = 12; // Profondeur des arêtes du squelette
|
||||
FRAME_FILLET = 2; // Congé sur les arêtes du squelette
|
||||
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
|
||||
|
||||
// --- 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
|
||||
|
||||
// --- LEDs (PCB Anneau — Étage B) --------------------------------------------
|
||||
LED_COUNT = 12; // Nombre de WS2812B par face
|
||||
LED_RING_DIAM_EXT = 70; // Diamètre extérieur de l'anneau LED
|
||||
LED_RING_DIAM_INT = 40; // Diamètre intérieur (ouverture d'air)
|
||||
LED_RING_HEIGHT = 1.6; // Épaisseur du PCB anneau
|
||||
RING_SHROUD_HEIGHT = 6; // Hauteur de la chambre de diffusion
|
||||
RING_SHROUD_WALL = 1.5; // Épaisseur paroi du shroud
|
||||
|
||||
// --- Capteur (PCB Bouchon — Étage A) ----------------------------------------
|
||||
CAP_PCB_DIAM = 35; // Diamètre du PCB bouchon
|
||||
CAP_PCB_HEIGHT = 1.6; // Épaisseur du PCB bouchon
|
||||
CAP_CONNECTOR_H = 4; // Hauteur des connecteurs 2.54mm
|
||||
|
||||
// --- NFC (Face du dessus uniquement) ----------------------------------------
|
||||
NFC_PCB_SIZE = 43; // Taille du module PN532 (carré)
|
||||
NFC_PCB_HEIGHT = 5; // Hauteur du module PN532 avec antenne
|
||||
NFC_ANTENNA_DIAM = 35; // Diamètre de l'antenne NFC
|
||||
|
||||
// --- Charge Qi (Face du dessous uniquement) ---------------------------------
|
||||
QI_COIL_DIAM = 50; // Diamètre de la bobine Qi réceptrice
|
||||
QI_COIL_HEIGHT = 3; // Épaisseur de la bobine Qi
|
||||
QI_PCB_WIDTH = 30; // Largeur du PCB récepteur Qi
|
||||
QI_PCB_LENGTH = 20; // Longueur du PCB récepteur Qi
|
||||
QI_PCB_HEIGHT = 2; // Épaisseur du PCB Qi
|
||||
|
||||
// --- Batterie ---------------------------------------------------------------
|
||||
BATT_LENGTH = 70; // Longueur batterie LiPo
|
||||
BATT_WIDTH = 50; // Largeur batterie LiPo
|
||||
BATT_HEIGHT = 10; // Épaisseur batterie LiPo (2500mAh ~)
|
||||
BATT_TOLERANCE = 1; // Jeu autour de la batterie
|
||||
|
||||
// --- PCB Central (Motherboard) ----------------------------------------------
|
||||
CENTRAL_PCB_WIDTH = 60; // Largeur du PCB central (ESP32-S3 + TP4056 + CW2015)
|
||||
CENTRAL_PCB_LENGTH = 60; // Longueur du PCB central
|
||||
CENTRAL_PCB_HEIGHT = 1.6; // Épaisseur du PCB
|
||||
CENTRAL_COMP_H = 8; // Hauteur composants (ESP32-S3 module)
|
||||
|
||||
// --- Aération ---------------------------------------------------------------
|
||||
AIR_HOLE_DIAM = 30; // Diamètre de l'ouverture d'air centrale (face intérieure)
|
||||
|
||||
// --- Tolérances d'Impression 3D -------------------------------------------
|
||||
PRINT_TOLERANCE = 0.2; // Jeu général pour emboîtement
|
||||
PRINT_LAYER_H = 0.2; // Hauteur de couche standard
|
||||
|
||||
// --- Rendu ------------------------------------------------------------------
|
||||
$fn = 60; // Résolution des cercles (augmenter pour le rendu final)
|
||||
|
||||
// --- Couleurs pour la visualisation ----------------------------------------
|
||||
COLOR_FRAME = [0.3, 0.3, 0.3]; // Gris foncé — squelette
|
||||
COLOR_FACE = [0.6, 0.6, 0.6, 0.85]; // Gris clair semi-transparent — faces
|
||||
COLOR_MEMBRANE = [0.8, 0.8, 0.8, 0.5]; // Blanc translucide — membrane tactile
|
||||
COLOR_PCB = [0.1, 0.5, 0.1]; // Vert — PCBs
|
||||
COLOR_LED = [1.0, 0.9, 0.3]; // Jaune — LEDs
|
||||
COLOR_BATTERY = [0.2, 0.2, 0.6]; // Bleu foncé — batterie
|
||||
COLOR_NFC = [0.6, 0.1, 0.1]; // Rouge — module NFC
|
||||
COLOR_QI = [0.8, 0.5, 0.1]; // Orange — bobine Qi
|
||||
Loading…
Reference in a new issue