Aller au contenu

GO Print

Re-synchroniser automatiquement 2 moteurs Z branchés sur le même pilote


Messages recommandés

Ceci n'est pas un tutoriel, mais le compte rendu détaillé d'un bricolage qui me rend un grand service.

Lorsque ma Discovery est éteinte les moteurs de l'axe Z tournent librement.
Sous le poids de l'axe X (moteur, tête, barres de guidage), les deux moteurs Z tournent mais pas autant l'un que l'autre et cela dérègle légèrement le parallélisme de l'axe X avec le plateau d'impression.
La répartition des masses y est pour quelque chose puisqu'au repos le moteur X et la tête se trouvent du même côté de l'axe X ; sur la gauche.
Du coup la première couche, de manière aléatoire, après la mise sous tension de l'imprimante peut être ratée et imposer de re-régler l'imprimante.
J'ai mis longtemps à comprendre ce qui se passait.
Par hasard je suis tombé sur un "post" où l’on synchronisait mécaniquement les deux axes Z avec une courroie, c'est ce qui m'a fait comprendre d’où venait mon problème.

Ci-dessous j'ai déréglé volontairement et fortement l'horizontalité de l'axe X pour que le défaut (et la correction !) soit bien visible à l’œil nu.

zsync5.gif.b8b1e878a922799067c58aab81bd0463.gif

Une solution simple et radicale est de changer la carte contrôleur de l'imprimante pour avoir un pilote et un end-stop par moteur Z et de resynchroniser les deux axes Z à l’allumage de l'imprimante, mais étant plutôt dans l'optique de faire avec ce que j'avais déjà sous la main j'ai exploré une autre voie. Voici mon idée et sa mise en œuvre.

L'idée : Après un G28 sur les trois axes, mesurer avec la fonction "PROBE" de klipper et mon bl-touch la distance entre la tête et le plateau tout à gauche de l'axe X, faire de même tout à droite, calculer l'écart entre ces deux mesures, l'affiner en fonction du mesh décrivant les déformations du lit d'impression, ramener la tête au milieu de l'axe X, inverser le câblage d'un des moteurs de l'axe Z, bouger la tête le long de z de la moitié de l'écart calculé juste avant, de sorte que le milieu de l'axe X reste immobile mais que les extrémités se déplacent en sens opposés pour compenser l'inclinaison, remettre le câblage dans le bon sens, terminer par un nouveau G28 en z seulement. Tous ça automatiquement à l'aide d'une macro dans klipper et d'un module 4 relais (que j'ai sous la main) pour inverser le câblage. (C'est la séquence que montre le gif animé ci-dessus. Aux possesseurs de discovery ou discoeasy, mon home sur l'axe Y s'y fait à l'opposer des imprimantes livrées par Dagoma)

Il y a sans doute des solutions plus économes en nombre de relais. Je me suis arrêté ,pour le moment, à cette solution automatique qui marche sans me graisser les doigts à chaque début d'impression. Ceux qui composent avec ce défaut savent de quoi je parle (imprimer une jupe ou une bordure, autour des pièces, suffisamment large pour avoir le temps d'intervenir au début de l'impression en tournant à la main une des tiges de l'axe Z (d'ou la graisse sur les mains) pendant l'impression de la jupe/bordure avant que l'impression des pièces ne soit véritablement commencée)

Je ne suis pas électro-mécanicien ni électronicien alors je fais certaines choses au « feeling ». J'ai dans l'idée que d’intervertir les fils d'alimentations d'un moteur lorsqu'il est sous tension ce n'est pas très bon pour la longévité du pilote voire du moteur lui-même à cause des courants transitoires que les bobines du moteur ne vont pas manquer de créer.
Alors la macro klipper coupera les moteurs z avant tous changements d'état des relais. J'ai mis également un délai un peu au pifomètre entre la coupure du courant et la bascule des relais.

L'imprimeur attentif n'aura pas manqué de relevé l'incohérence 🤪qu'il y a à vouloir corriger un problème dû à l'arrêt de l'alimentation des moteurs quand l'imprimante est au repos, en coupant l'alimentation de ces moteurs en plein milieu de la procédure de correction ! L'expérience tranchera...

Voici le câblage original des moteurs sur les drivers de ma melzi (diapo dagoma issue du manuel de montage)

cablage.jpg.2e8944564b85d5ab6867b60772231a75.jpg

On y remarque que
- les moteurs z sont branchés en série sur le même driver, du coup, débrancher l'un des moteurs empêche l'autre de fonctionner, il va falloir faire plus subtile...
On remarque aussi que
- le câblage de l'extrudeur est inversé par rapport aux autres moteurs, de fait, il ne tourne pas dans le même sens.
Je remercie Dagoma d'avoir inversé le câblage de l'extrudeur plutôt que d'avoir inversé le sens de rotation du moteur dans le firmware 😉 car cela m'indique comment câbler un moteur step pour le faire tourner à l'envers !

Voici donc ce que j’ai fait
module 4 relais au repos

relaisoff.jpg.1dbbf06cbd0736f24b4ec901d9459a19.jpg

module 4 relais activés : inversion des paires de fils (vert, rouge) et (gris, jaune)

relaison.jpg.dab8a3780fb518b41532f9569f2089d1.jpg

En fait je pense que cela pourrait marcher tout aussi bien si les moteurs étaient branchés en parallèle plutôt qu'en série.

Voici mon module à 4 relais avec les câbles de branchement.

relais.jpg.77fcb9094961097481813703263f4623.jpg

En bas à gauche on trouve branchés les trois fils qui alimentent et commandent la carte :
le noir (gnd) le blanc (signal) le violet +5V (vcc). Ils sont branchés sur des pins de la carte contrôleur de l'imprimante.
Côté droit les deux groupes de 4 fils qui permettent d’insérer ce module sur la nappe qui va à l'un des moteurs de l'axe Z.

Voici comment sont câblées les choses.

cablageRelais.jpg.8745e819e18ce4ed7a8a1da730f38881.jpg

En fait (vers moteur) et (vers pilote) sont interchangeables.
Le câblage est fait de sorte que lorsque les relais sont au repos il n'y ait pas d’inversion.
Les quatre entrées in1..in4 sont connectées entre elles, car les relais ne sont pas pilotés individuellement, ils basculent tous en même temps, un seul fil de commande (blanc) est nécessaire.
En bas vcc et jdvcc sont reliés entre eux, cela signifie que la carte relais (y compris les électroaimants) est alimentée par la carte de l'imprimante (fil noir gnd et fil violet +5vcc).

Pour piloter les relais depuis klipper, il faut choisir un pin disponible sur la carte de l'imprimante et la configurer dans le fichier printer.cfg de klipper.
C'est sur ce pin que je branche mon fil blanc (signal), je l'ai nommé "croiser_z" dans le fichier de conf. Les pins qui servent à alimenter la carte relais n'ont pas besoin d'y être configurées.

Sur ma melzi j'avais choisi A3 (fil noir sur la photo ci-dessous) et pour alimenter la carte relais les pins marqués vcc et gnd du bloc "ISP", les pins courbés servaient à mon bl-touch.

pinmelzi.jpg.b757122fb2ef85f5009915d61ea7b2a9.jpg

La section correspondante dans le fichier de configuration de Klipper :

[output_pin croiser_z]
pin: !PA3
pwm: False
#   Set if the output pin should be capable of pulse-width-modulation.
#   If this is true, the value fields should be between 0 and 1; if it
#   is false the value fields should be either 0 or 1. The default is
#   False.
#static_value:
#   If this is set, then the pin is assigned to this value at startup
#   and the pin can not be changed during runtime. A static pin uses
#   slightly less ram in the micro-controller. The default is to use
#   runtime configuration of pins.
value: 0
#   The value to initially set the pin to during MCU configuration.
#   The default is 0 (for low voltage).
shutdown_value: 0
#   The value to set the pin to on an MCU shutdown event. The default
#   is 0 (for low voltage).

 Sur ma toute nouvelle skr1.4 turbo j'ai choisi P1.0

[output_pin croiser_z]
pin: !P1.0
pwm: False
#static_value:
value: 0
shutdown_value: 0

Le "!" devant le nom physique du pin (PA3 ou P1.0), c'est pour inverser sa logique, car mon module relais fonctionne de la façon suivante :
- signal haut : + 5V; les relais sont au repos les bobines des électro-aimants ne sont pas alimentées les bornes COM (common) et NC (normaly close je crois) sont connectées entre elles et laissent passer le courant tandis que NO (normaly open je crois) n'est reliée à aucune autre borne.
- signal bas : 0V; les relais sont activés (les electro-aiments sont alimentés) les bornes NO et COM sont connectées entre elles et NC n'est plus reliée a rien.

Tous les pins VCC 5v ne font pas l'affaire sur la skr1.4 turbo.
A mon premier essai avec la skr j'avais choisi d'alimenter en +5V la carte relais avec le pin "NPWR" du bloc "neopixel" qui peut alimenter un bandeau led du même nom (flèche la plus basse sur l'image ci-dessous), hé bien mauvaise pioche : 2 "clacs" à la mise sous tension et idem à la mise hors tension.
A mon deuxième essai j'alimente la carte relais avec le "5v" du bloc "PWRDET" (flèche la plus à droite) et là tous fonctionne correctement, à la mise sous tension et hors tension de l'imprimante les relais ne bougent pas.

pinskr1.4turbo.thumb.jpg.2fbf1ca88e9e569a2366ab12081c7da3.jpg

Ce qui m’intéresse au plus haut point c'est que les relais ne basculent pas de manière intempestive hors du contexte de ma macro de synchronisation des axes Z, en particulier à la mise sous tension de l'imprimante et lors de son arrêt. Le but étant de ne jamais risquer d'inverser le câblage alors que les moteurs Z seraient sous tension.
Il faut que le signal de contrôle (+5V) soit disponible le plus tôt possible sur l'entrée de la carte relais pour qu'a la mise sous tension de cette carte les relais n'aient pas le temps de basculer.
Hors visiblement au démarrage de la skr certains pins vcc 5v délivrent leur tension avant que klipper n'ait le temps d'envoyer les 5v sur le pin P1.0 (avant que l'imprimante ne soit complètement initialisée ?) du coup les relais ont le temps de se coller avant de recevoir l'ordre de ne pas le faire. On entend alors distinctement deux "clacs" qui témoignent des deux changements d'états non souhaités des relais. Un phénomène du même ordre se produit à la mise hors tension de l'imprimante.
Pour remédier à ce problème le mieux serait d'utiliser des relais dont la logique de commande serait à l'inverse de ceux que j'utilise (en High-Level-Trigger plutôt que Low-Level-Trigger) et d'enlever le "!" qui inverse la logique.

Partie logiciel : la macro klipper
Klipper dispose d'un mécanisme de "templating" qui permet de créer ses propres macros. L'évaluation d'une macro produit typiquement une séquence de gcode, de commandes klipper ainsi que d'appels à d'autres macros qui feront elles aussi l'objet d'une évaluation. Des boucles de traitement, des tests, des évaluations d'expressions sont possibles, l’accès au fichier de configuration et à l'état interne de l'imprimante est possible.
Ce mécanisme n'est pas du tous facile à utiliser pour faire des choses un peu complexe, mais a l'immense intérêt d'exister !
La difficulté principale vient du mécanisme d'évaluation. Il faut, à chaque fois qu'une opération dans une macro modifie l'état interne de l'imprimante, si l'on veut exploiter le résultat de ce changement appeler une autre macro. Il n'y a donc pas une seule macro mais plusieurs, à la fin de la première on appellera la seconde qui appellera à son tour une troisième et ainsi de suite.

Il y a, en l'état, beaucoup de prérequis pour que mes macros fonctionnent, mais rien de très exotiques je pense :
- cinématique de l'imprimante : cartésienne
- configurer et utiliser un mesh pour le "bed leveling" section [mesh_bed]
- utiliser une sonde en lieu et place d'un end-stop pour l'axe Z (bl-touch, capacitive, inductive, servo...) qui se déplace avec la tête. Section [bltouch] ou [probe] avec des valeurs pour "x_offset" et "y_offset" qui sont lues par la macro.
- avoir défini une section [safe_z_home] avec des valeurs pour "z_hop", "z_hop_speed", "home_xy_position" et "speed" qui sont lues par la macro
- avoir défini une section [respond] pour activer le gcode M118.

Mes macros dans le fichier de configuration de klipper :

# Cette macro n a pas de gcode, sont evaluation ne produit pas d instruction
# mais j y regroupe des variables que je peux consulter depuis d autres macro
[gcode_macro tas]
variable_ecartref: 0.0
variable_mesureagauche: 0.0
variable_mesureadroite: 0.0
gcode:

# pas foncierement utile me permet d ecrire
# set VARIABLE=ecartref VALUE={ecartreference}
# plutot que
# SET_GCODE_VARIABLE MACRO=tas VARIABLE={params.VARIABLE} VALUE={params.VALUE}
[gcode_macro set]
gcode:
  SET_GCODE_VARIABLE MACRO=tas VARIABLE={params.VARIABLE} VALUE={params.VALUE}

# corrige l inclinaison de l axe X
# le plateau doit etre vide. A faire avant l impression
# les instructions entre {% %} sont des instructions propres au systeme de templating
# les expressions entre { } sont remplacees par leurs evaluations et peuvent parametrer des gcodes
[gcode_macro zsync]
gcode:
  SAVE_GCODE_STATE NAME=etat_sauve
  {% block b %}
    # recuperer dans une variable "px" accessibe dans cette macro seulement
    # la largeur du mesh en nombre de points (sur l axe X)
    {% set px=printer.bed_mesh.mesh_matrix[0]|count %}
    # recuperer la profondeur du mesh en nombre de point (sur l axe Y)
    {% set py=printer.bed_mesh.mesh_matrix|count %}
    # recuperer depuis le fichier de configuration de klipper la valeur de
    # "z_hop" dans la section "safe_z_home"
    {% set zhope=printer.configfile.config["safe_z_home"]["z_hop"]|int %}
    {% set zhopespeed=printer.configfile.config["safe_z_home"]["z_hop_speed"]|int * 60 %}
    # calculer l ecart en hauteur, a mi-profonduer du lit (en Y), de la tete au lit entre la gauche et a la droite du lit 
    # a partir des valeurs du mesh actif
    {% set ecartreference=printer.bed_mesh.mesh_matrix[(py/2)|int][0] - printer.bed_mesh.mesh_matrix[(py/2)|int][px-1] %}
    
    # le gcoge M118 affiche dans le terminal et l onglet klipper d octoprint le message qui le suit
    M118 zsync
    M118 mesh {px}*{py} ptG({(py/2)|int},0):{printer.bed_mesh.mesh_matrix[(py/2)|int][0]}, ptD({(py/2)|int},{px-1}):{printer.bed_mesh.mesh_matrix[(py/2)|int][px-1]} 
    # la il y a un piege "set" n est pas comme dans les lignes precedantes une instruction du langauge de "templating"
    # il n est pas entre {% %} c est le nom de la macro que j ai defini precedemment
    # j invoque cette macro pour memoriser la valeur de la variable "ecartreference" dans une autre varible : "ecartref"
    # dont la portee n est pas limitee a cette macro mais pourra etre utilisee partout
    set VARIABLE=ecartref VALUE={ecartreference}
    G28 
    # appele de macro
    mesureagauche
    # gcode parametre avec des variables
    G1 Z{zhope} F{zhopespeed}
    mesureadroite
    G1 Z{zhope} F{zhopespeed}
    suite1
  {% endblock %}
  # fin des gcodes generes par la macro zsync
  # cependant elle appele d autres macros qui
  # produisent aussi du gcode

[gcode_macro mesureagauche]
gcode:
  {% block b1 %}
    {% set xmin=printer.bed_mesh.mesh_min[0] %}
    {% set ymin=printer.bed_mesh.mesh_min[1] %}
    {% set ymax=printer.bed_mesh.mesh_max[1] %}
    # utiliser "probe" à la place de "bltouch" si necessaire...
    {% set y_offset=printer.configfile.config["bltouch"]["y_offset"]|float %}
    {% set x_offset=printer.configfile.config["bltouch"]["x_offset"]|float %}
    {% set speed=printer.configfile.config["safe_z_home"]["speed"]|int * 60  %}

    # je deplace la tete sur la gauche a l endroit qui (je crois) correspond a la mesure extraite du mesh pour la gauche du lit 
    G1 X{xmin + (-1* x_offset)} Y{ ((ymax-ymin)/2) + ymin + (-1 * y_offset) |round(6)} F{speed}
    # instruction de klipper qui utilise le sonde pour evaluer la distance au plateau
    PROBE 
    mesureagauchesuite
  {% endblock %}

[gcode_macro mesureagauchesuite]
gcode:
  # je memorise la hauteur a laquelle la sonde c est declanchee
  set VARIABLE=mesureagauche VALUE={ printer.toolhead.position.z }

[gcode_macro mesureadroite]
gcode:
  {% block b1 %}
    {% set xmax=printer.bed_mesh.mesh_max[0] %}
    {% set x_offset=printer.configfile.config["bltouch"]["x_offset"]|float %}
    {% set speed=printer.configfile.config["safe_z_home"]["speed"]|int * 60  %}

    G1 X{xmax + (-1* x_offset) } F{speed}
    PROBE
    mesureadroitesuite
  {% endblock %}

[gcode_macro mesureadroitesuite]
gcode:
  set VARIABLE=mesureadroite VALUE={ printer.toolhead.position.z }

[gcode_macro suite1]
gcode:
  {% block b2 %}
    # a partir des mesures faites precedemment je calcule la correction
    {% set ecartmesure=printer["gcode_macro tas"].mesureagauche|float - printer["gcode_macro tas"].mesureadroite|float %}
    {% set ecartreel=ecartmesure  - printer["gcode_macro tas"].ecartref|float %}

    {% set xsafehome=printer.configfile.config["safe_z_home"]["home_xy_position"].split(',')[0] %}
    {% set speedsafehome=printer.configfile.config["safe_z_home"]["speed"]|int * 60 %}
    {% set zhopespeedsafehome=printer.configfile.config["safe_z_home"]["z_hop_speed"]|int * 60 / 4 %}

    # message 
    M118 ecartMesh : {printer["gcode_macro tas"].ecartref|float}
    M118 ecartMesure : {ecartmesure}
    M118 ecartReel (ecartMesure - ecartMesh) : {ecartreel}

    # correction
    G90
    G1 X{xsafehome} F{speedsafehome}
    opposerZ
    G91
    M118 deplacement de (ecartreel/2) >>>> G1 Z{(ecartreel / 2)|round(6)}
    G1 Z{ (ecartreel/2)|round(6) } F{zhopespeedsafehome}
    retablirZ
    G28 Z

    # c est fini
    RESTORE_GCODE_STATE NAME=etat_sauve
  {% endblock %}


[gcode_macro opposerZ]
gcode:
  M118 opposerZ
  # couper l alimentation des moteurs Z
  SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=0
  # attendre 0.5s
  G4 P500
  # changer la valeur du pin de controle sur lequel est branche la carte relai
  SET_PIN PIN=croiser_z VALUE=1
  # attendre 0.1s que les relais aient eu le temps de bouger
  G4 P100
  # retablir l alimentation des moteurs Z
  SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1

[gcode_macro retablirZ]
gcode:
  M118 retablirZ
  SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=0
  G4 P500
  SET_PIN PIN=croiser_z VALUE=0
  G4 P100
  SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1

Il me suffit de taper "zsync" dans le terminal pour lancer la macro ou de l’insérer dans le gcode de démarrage de mon slicer.

Voilà le retour de la macro :

Send: zsync
Recv: // zsync
Recv: // mesh 15*15 ptG(7,0):-0.034375, ptD(7,14):-0.004375
Recv: // probe at 2.000,75.988 is z=5.365000
Recv: // Result is z=5.365000
Recv: // probe at 205.975,75.988 is z=3.495000
Recv: // Result is z=3.495000
Recv: // ecartMesh : -0.03
Recv: // ecartMesure : 1.87
Recv: // ecartReel (ecartMesure - ecartMesh) : 1.9
Recv: // opposerZ
Recv: // deplacement de (ecartreel/2) >>>> G1 Z0.95
Recv: // retablirZ
Recv: ok

Cela marche plutôt bien.
Pas parfaitement néanmoins, pour le moment je lance plusieurs fois de suite la macro, pour arriver à une correction qui permet une première couche impeccable.
Les exécutions successives améliorent la correction, mais ne la dégradent pas. Quatre exécutions me permettent d'avoir une première couches parfaite.
Au-delà les corrections oscillent sans améliorer ou dégrader significativement les choses (on est alors proche d'un écart entre la gauche et la droite du plateau de l'ordre de la précision de la sonde).

Une série de mesures :

[...]Recv: // deplacement de (ecartreel/2) >>>> G1 Z0.95
[...]Recv: // deplacement de (ecartreel/2) >>>> G1 Z0.222187
[...]Recv: // deplacement de (ecartreel/2) >>>> G1 Z0.05375
[...]Recv: // deplacement de (ecartreel/2) >>>> G1 Z0.004688
[...]Recv: // deplacement de (ecartreel/2) >>>> G1 Z-0.01375
[...]Recv: // deplacement de (ecartreel/2) >>>> G1 Z0.005
[...]Recv: // deplacement de (ecartreel/2) >>>> G1 Z0.004062

Pourquoi cela ne marche pas du premier coup ?
Plusieurs hypothèses me viennent :
- lorsque la macro coupe l'alimentation sur Z, il est bien possible que les moteurs tournent sous le poids de l'axe X, les microsteps, à coups sûrs, sont perdus.
- il y a peut être un bug dans ma macro. Je ne suis pas sûr en particulier que je positionne la tête au bon endroit lorsque je fais le "probe" sur la gauche et sur le droite du plateau par rapport aux valeurs que j'extrais du mesh pour corriger ces mesures.

Coté amélioration, j'ai tellement tâtonné pour câbler la sortie des relais, que j'ai maintenant la certitude que 4 relais c'est luxe ! On peut faire avec moins.
Par exemple, plutôt que d'inverser l'alimentation des bobines avec 2 relais par bobine, il me paraît possible de bloquer un moteur en déroutant le courant de ces bobines vers de simples résistances avec deux relais, un seul par bobine. Il est peut être même possible de bloquer un moteur en agissant sur une seule de ses bobines avec un seul relais !
Une fois que l'on sait bloquer un moteur il suffit de changer la macro pour corriger l'inclinaison en bougeant un seul moteur et non les deux.
C'est plus classe de voire les extrémités de l'axe X bouger en sens opposés (j'adore dérégler l'imprimante juste pour le plaisir de la voire se re-régler toute seule !) que de voir une seule extrémité bouger lors de la correction, mais ce n'est sans doute pas plus opérationnel.

Le mieux, ennemi du bien ? J'ai commencé ce montage avec ma bonne vieille melziV2 et je l'ai fini sur un skr 1.4 turbo... Car j'ai grillé la melzi en voulant raffiner la solution.
Je sais que le bl-touch est très sensible à la tension d'alimentation : 4.9V c'est le minimum et 5.1V le maximum. Aussi j'ai voulu éviter d'alimenter le module relais avec les 5V de la melzi, en l'alimentant avec une source externe (ne plus relier jdvcc et vcc). Mais voilà, un mauvais branchement en 12V pour alimenter le module a eu raison de la melzi.
Une melzi ce n'est pas cher, mais il faut 3 semaines pour la faire venir de Chine, alors je l'ai remplacée par une carte bien plus onéreuse (et puissante) disponible sous 3 jours : une skr1.4 turbo.
Je n'ai pas perdu au change, mais j'ai l'impression d'avoir mis un moteur fusé sur un Solex ! Et c'est un comble pour moi qui ne voulais pas changer pour une carte avec un pilote par moteur alors que précisément cette skr dispose d'un pilote en rab (pour un deuxième extrudeur).

a+

  • J'aime 1
  • Merci ! 1
Lien vers le commentaire
Partager sur d’autres sites

Le 29/01/2021 at 22:56, r2d2 a dit :

En fait je pense que cela pourrait marcher tout aussi bien si les moteurs étaient branchés en parallèle plutôt qu'en série.

J'ai un doute dans le cas d'un montage parallèle le courant nécessaire pour faire fonctionner les deux moteurs sera doublé. Je ne suis pas certain que la sortie puisse fournir un tel courant.

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
  • Sur cette page :   0 membre est en ligne

    • Aucun utilisateur enregistré regarde cette page.
  • YouTube / Les Imprimantes 3D .fr

×
×
  • Créer...