Je m'essaie doucement à OpenSCAD. Si vous ne connaissez pas encore, c'est un logiciel de conception 3D paramétrique pour les gars qui ont au moins 25mm de barbe (ou les filles qui ont un minimum de 5mm de poils aux pattes). Comparé à SolidWorks auquel je suis assez habitué, c'est... du roots! Pour modéliser une pièce, il faut écrire un programme.

Il y a les formes de base, comme cube() ou cylinder(), des fonctions booléennes comme union() ou difference(), des fonctions de transformation, comme translate() ou rotate(). Et bien sûr beaucoup d'autres fonctionnalités que je n'ai pas testées, pour faire des révolutions, des extrusions en suivant un chemin et plein d'autres.

Vous vous souvenez de mon coupleur 5/8mm? Hé bien je l'ai refait dans OpenSCAD pour le rendre paramétrable à souhait et utilisable dans le module Customizer de Thingiverse (https://www.thingiverse.com/thing:299663).

Résultat fini

image

Classe, non ? Et concis, parce que le programme ne fait que 122 lignes (formaté et tout).

Après plusieurs expérimentations d'OpenSCAD, je me suis rendu compte qu'il était TRES important de travailler par modules. C'est l'équivalent des fonctions dans n'importe quel langage de programmation. Ca paermet de structurer le code, et d'éviter de se répéter (la règle fondamentale du DRY -> Don't Repeat Yourself).

Nous allons écrire le premier module, qui va simplement dessiner le...

Cylindre principal

[php] //crée le cylindre principal module main_cylinder(d) { cylinder(h=height, r=d/2, center=false, $fn=resolution); } [/php]

Facile. Dans ce module, nous appelons la fonction native cylinder(), en lui passant des paramètres nommés : h, r, center et $fn.

h est la hauteur du cylindre r est son rayon center indique si le cylindre doit être centré sur l'axe Z $fn est la résolution, c'est à dire le nombre de segments qui composent le cylindre.

Pour appeler ce module, nous devrons fournir le diamètre. La hauteur et la résolution sont fixées dans des variables globales au début du programme (ils deviendront des paramètres dans le customizer de Thingiverse).

Si on appelle main_cylinder(24), nous obtenons le résultat suivant :

image

On peut voir que notre cylindre est automatiquement centré en X et Y, et que sa base est sur le plan Z=0.

Voici le programme complet. Comme je l'ai mis sur Thingiverse, j'ai fait les commentaires en anglais, et comme je suis une grosse feignasse, je ne les traduirai pas!

[php] // The outer diameter of the coupler outer_diameter = 24;

// The total height of the coupler height = 35;

// The cylinder and holes resolution resolution = 20;

module main_cylinder(d) { cylinder(h=height, r=d/2, center=false, $fn=resolution); }

main_cylinder(outer_diameter); [/php]

Un cylindre, c'est bien beau mais ça ne fait pas tout; il va falloir le percer. Nous allons pour cela utiliser la fonction booléenne difference().

Perçage du cylindre principal

Créons un deuxième cylindre, de diamètre plus petit et de la même hauteur que notre cylindre principal : [codesyntax lang="php"]

module hole(d) {
     cylinder(h=height, r=d/2, center=false, $fn=resolution);
}

[/codesyntax]

Si on appelle successivement

[php] main_cylinder(outer_diameter); hole(8); [/php]

on verra toujours seulement notre cylindre principal. Le petit est "dedans". En revanche, si on écrit :

[php] difference() { main_cylinder(outer_diameter); hole(8); } [/php]

image

Voilà qui devient intéressant! Par contre on peut voir au niveau du trou que c'est assez bizarre:

imageCe zigouigoui est causé par une épaisseur nulle, et ça peut poser des problèmes par la suite, lors du tranchage de l'objet (facettes fantômes, normales inversées... que du bonheur...) Alors pour éviter ça, on va juste rallonger le 2ème cylindre de 1mm en haut et en bas, et ça va aller tout de suite mieux. En plus, ça va nous permettre d'utiliser la fonction translate(), car doit rallonger la hauteur du cylindre de 2mm, et le décaler vers le bas de 1mm. Voici le programme complet: [php] // The outer diameter of the coupler outer_diameter = 24;

// The total height of the coupler height = 35;

// The cylinder and holes resolution resolution = 20;

ozp = 1; //offset to avoid zero thickness planes

module main_cylinder(d) { cylinder(h=height, r=d/2, center=false, $fn=resolution); }

module hole(d) { //décalage en Z de -1mm translate([0,0,-ozp]) { cylinder(h=height + 2*ozp, r=d/2, center=false, $fn=resolution); } }

// Routine principale difference() { main_cylinder(outer_diameter); hole(8); } [/php]

J'appelle cette constante ozp (offset-zero-planes), et nous allons l'utiliser à plusieurs endroits par la suite. C'est une bonne chose de prévoir ceci dès le début, comme ça on n'aura pas de surprises avec le STL par la suite.

Ce qui nous donne :

image

Cool! Propre et tout :)

Maintenant c'est pas le tout, mais nous voulons deux diamètres pour notre trou central. Nous allons écrire deux modules, qui prennent en paramètre les diamètres respectifs et qui vont percer le cylindre en haut et en bas. On va aussi créer un module main() dans lequel les opérations de différence sont faites, ce qui nous donne le programme suivant:

[php] // The outer diameter of the coupler outer_diameter = 24;

// The total height of the coupler height = 35;

// The cylinder and holes resolution resolution = 20;

ozp = 1; //offset to avoid zero thickness planes

module main_cylinder(d) { cylinder(h=height, r=d/2, center=false, $fn=resolution); }

module top_hole(d) { translate([0,0,height/2 - ozp]) { cylinder(h=height/2 + 2*ozp, r=d/2, center=false, $fn=resolution); } }

module bottom_hole(d) { translate([0,0,-ozp]) { cylinder(h=height/2 + ozp, r=d/2, center=false, $fn=resolution); } }

// Routine principale module main() { difference() { main_cylinder(outer_diameter); top_hole(8); bottom_hole(5); } }

main(); [/php]

Et voici le résultat (dans une vue fil de fer par en dessous, pour bien voir le décalage à l'intérieur)

image

Ouvertures latérales

Occupons nous maintenant de l'ouverture du côté des vis de serrage (avec dans l'idée que sa largeur devra être paramétrable dans le customizer thingiverse).

Nous allons pour cela définir un parallélépipède rectangle avec la fonction cube(), en lui donnant ses 3 dimensions. Et nous allons décaler ce cube avec translate() pour qu'il vienne se positionner au bon endroit. On n'oublie pas le paramètre ozp pour éviter les facettes fantômes, et nous créons un nouveau paramètre opening_width (largeur de l'ouverture). [php] module opening_left() { translate([-opening_width/2,-outer_diameter/2,-ozp]) { cube(size=[opening_width, outer_diameter / 2, height + 2*ozp], center=false); } } [/php]

Nous allons dans la foulée réaliser la rainure en face, qui est composée d'un cylindre et d'un pavé. Nous ajoutons le paramètre articulation_thickness, qui correspond à l'épaisseur de matière qui relie les deux parties du coupleur.

[php] module opening_right() {

y_offset = (diameter_top/2) + opening_width/2 + articulation_thickness;
translate([0, y_offset, -ozp]) {
    cylinder(h=height + 2*ozp, r=opening_width/2, center=false, $fn=20);
}

translate([-opening_width/2,y_offset,-ozp]) {
    cube(size=[opening_width, outer_diameter / 2, height + 2*ozp], center=false);
}

} [/php]

On ajoute ces deux modules dans le module main(), on sort encore quelques paramètres et voici le programme complet: [php] // The outer diameter of the coupler outer_diameter = 24;

// The total height of the coupler height = 35;

// Diameter of the bottom axis (the smallest) diameter_bottom = 5;

// Diameter of the top axis (the biggest) diameter_top = 8;

// The aperture width opening_width = 2;

// The y-thickness of the contact between the coupler's two parts articulation_thickness = 1.5;

// The cylinder and holes resolution resolution = 20;

ozp = 1; //offset to avoid zero thickness planes

module main_cylinder(d) { cylinder(h=height, r=d/2, center=false, $fn=resolution); }

module top_hole(d) { translate([0,0,height/2 - ozp]) { cylinder(h=height/2 + 2*ozp, r=d/2, center=false, $fn=resolution); } }

module bottom_hole(d) { translate([0,0,-ozp]) { cylinder(h=height/2 + ozp, r=d/2, center=false, $fn=resolution); } }

module opening_left() { translate([-opening_width/2,-outer_diameter/2,-ozp]) { cube(size=[opening_width, outer_diameter / 2, height + 2*ozp], center=false); } }

module opening_right() {

y_offset = (diameter_top/2) + opening_width/2 + articulation_thickness;
translate([0, y_offset, -ozp]) {
    cylinder(h=height + 2*ozp, r=opening_width/2, center=false, $fn=20);
}

translate([-opening_width/2,y_offset,-ozp]) {
    cube(size=[opening_width, outer_diameter / 2, height + 2*ozp], center=false);
}

}

// Routine principale module main() { difference() { main_cylinder(outer_diameter); top_hole(diameter_top); bottom_hole(diameter_bottom); opening_left(); opening_right(); } }

main(); [/php]

image

Bien! Maintenant, passons aux...

Emplacements des boulons de serrage

Pour les trous des boulons, nous allons écrire un module qui prend en paramètre la hauteur (z), et qui crée une empreinte de boulon. On calcule un offset Y pour que l'empreinte tombe au milieu de la partie pleine du coupleur. Puis on perce le trou principal (diamètre: bolt_diameter), l'empreinte de l'écrou (nut_diameter, avec une résolution de 6 segments... futé :), et enfin l'empreinte de la rondelle ou de la tête de la vis (washer_diameter).

[php] module bolt_hole(z) {

y_offset_bolt = -((outer_diameter-diameter_top)/4 + (diameter_top/2));

//main hole:
translate([0,y_offset_bolt,z]){
    rotate([0,90,0]) {
        cylinder(h=outer_diameter, r=bolt_diameter/2, center=true, $fn=resolution);
    }
}

//nut:
translate([(opening_width/2) + pressure_point_thickness, y_offset_bolt, z]) {
    rotate([0,90,0]) {
        cylinder(h=outer_diameter, r=nut_diameter/2, center=false, $fn=6);
    }
}

//washer:
translate([-outer_diameter - (opening_width/2) - pressure_point_thickness, y_offset_bolt, z]) {
    rotate([0,90,0]) {
        cylinder(h=outer_diameter, r=washer_diameter/2, center=false, $fn=resolution);
    }
}

} [/php]

Le module main() devient :

[php] module main() { difference() { main_cylinder(outer_diameter, height); bottom_hole(diameter_bottom); top_hole(diameter_top);
opening_left();
opening_right(); bolt_hole(height 1/4); bolt_hole(height 3/4); } } [/php]

Résultat

image

Pour aller plus loin, jetez vous sur le tutoriel de RepRapide.fr!

Article précédent Article suivant