Octoprint / Octopi
Octoprint est un logiciel pour piloter une imprimante 3D. Avec Octopi , une distribution Raspbian pour Raspberry Pi avec Octoprint pré-installé, c'est le compagnon idéal d'une imprimante. L'IHM web fournit des contrôles des différents axes, une visualisation sous forme de graphe des températures ainsi que d'afficher la webcam. Le plugin Octoprint du slicer Cura permet, une fois la préparation des paramètres de hauteur de couche, nombre de mur, taux de remplissage etc… sélectionnés, de lancer directement l'impression via le Wifi. Pratique lorsque l'imprimante est dans une autre pièce .
Boîtier
De nombreux boîtiers permettant de fixer un Raspberry Pi sur une imprimante existe, la plupart se fixent sur les rails métalliques extrudés. J'en ai choisi un qui permet de loger le Pi sous l'écran LCD de l'imprimante. Je l'ai modifié pour dégager le bas du boitier pour faciliter la circulation d'air et reduire les supports nécessaire à l'impression. J'ai également légèrement agrandi les trous pour insérer le Raspberry.
Pour alimenter le Pi, j'ai utilisé l'alimentation de l'imprimante mais celle-ci produit du 24 V alors qu'il ne faut que du 5 V. Pour diminuer la tension, j'ai utilisé un module à base LM2596. Ce montage à déjà fait ses preuves dans mes projets de réception d'images satellites ou pour la webcam à oiseaux : il ne chauffe pas beaucoup et est très stable. J'ai intégré au boitier un support pour cette pièce juste en dessous des grilles d'aération. Le branchement coté Raspberry Pi s'effectue via les pins +5V et GND du port GPIO, cela permet de gagner de la place.
Boutons
J'ai ajouté 2 boutons poussoirs sur l'imprimante : un premier permet de lancer la préchauffe du hotend et du bed, le 2e permet d'annuler une impression en cours.
Le modèle utilisé mesure 15 mm de diamètre environ et possède 2 connecteurs à souder ainsi qu'un pas de vis :
Bouton de préchauffe
Ce bouton permet de lancer la préchauffe du lit et hotend sans devoir naviguer dans le menu de l'imprimante ni aller sur un ordinateur sur l'interface d'Octoprint. En fin d'impression, la chauffe de toute ces éléments est coupée, le temps d'aller à l'imprimante et enlever la pièce du plateau, le plateau se refroidit. Ainsi avec ce bouton, je relance la chauffe le temps d'enlever la pièce en cours et de nettoyer le plateau.
J'ai percé un trou sur le coté droit du boîtier contenant le Pi pour fixer un bouton poussoir (en bleu sur la photo ci dessous) relié au GPIO et l'ai branché au port GPIO16
d'un coté et au 5V
de l'autre.
Coté Octoprint, j'ai installé le plugin "Physical Button" afin d'associer une action d'envoi de gcode à l'appui sur le bouton :
M117
: affiche un message sur l'écran de l'imprimanteM140
: chauffe du lit à 45°CM104
: chauffe du hotend à 210°C
Bouton d'annulation
L'objectif de ce bouton est de pouvoir annuler une impression sans devoir le faire sur Octoprint à partir d'un ordinateur. Néanmoins, il ne faut pas qu'un appui intenpestif soit pris en compte. J'ai alors écrit un script python qui écoute le bouton et qui n'annule l'impression que s'il est appuyé plus 3 secondes. Pour avoir un feedback visuel, j'ai mis une led multicolore qui se met à clignoter lorsque le bouton est appuyé et lorsque l'ordre d'arrêt est envoyé.
J'ai dessiné un boîtier qui se glisse dans un des rails de l'imprimante et qui possède une ouverture pour le bouton et la led.
La led utilisée possède 4 pattes :
- 1 pour l'anode (positif)
- 3 cathodes, une pour le rouge, le vert et le bleu.
Le branchement du bouton + led sur les GPIO est le suivant :
Connexion | N° GPIO |
---|---|
bouton | 17 |
led bleue | 13 |
led rouge | 19 |
led verte | 26 |
Voici le script python correspondant :
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import RPi.GPIO as GPIO from time import sleep import json import requests time_long_press=20 def blink(color): GPIO.output(color, GPIO.HIGH) sleep(0.2) GPIO.output(color, GPIO.LOW) def button_callback(channel): GPIO.output(blue, GPIO.HIGH) for i in range (1,time_long_press + 1): val = GPIO.input(channel) if val != 0: break sleep(0.1) if i == time_long_press / 2: GPIO.output(blue, GPIO.LOW) GPIO.output(green, GPIO.HIGH) GPIO.output(blue, GPIO.LOW) GPIO.output(green, GPIO.LOW) if i == time_long_press: GPIO.output(red, GPIO.HIGH) start_stop_job() GPIO.output(red, GPIO.LOW) for j in range (0, 3): blink(blue) blink(green) blink(red) def start_stop_job(): url = 'http://%s/api/job' % octopi_hostname headers={'X-Api-Key': API,"Content-Type":"application/json"} r = json.loads((requests.get(url, headers=headers)).content)["state"] print(r) if r == "Printing": print("Stopping printing") contents = json.dumps({"command":"cancel"}) else: print("Starting printing") contents = json.dumps({"command":"start"}) print(requests.post(url, data=contents, headers=headers)) API = '<API KEY>' octopi_hostname = '127.0.0.1' button = 17 blue = 13 red = 19 green = 26 GPIO.setwarnings(False) # Ignore warning for now GPIO.setmode(GPIO.BCM) GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Set pin 10 to be an input pin and set initial value to be pulled low (off) GPIO.add_event_detect(button,GPIO.FALLING,callback=button_callback) # Setup event on pin 10 rising edge GPIO.setup(red, GPIO.OUT) GPIO.output(red, GPIO.LOW) GPIO.setup(blue, GPIO.OUT) GPIO.output(blue, GPIO.LOW) GPIO.setup(green, GPIO.OUT) GPIO.output(green, GPIO.LOW) print("Waiting for button") try: while True: sleep(0.1) finally: GPIO.cleanup() # Clean up
La séquence de clignotement est la suivante :
- bleu / vert tant que le bouton est appuyé moins de 3 secondes ;
- rouge lorsque le temps d'attente est dépassé, la led est allumée en rouge pendant l'appel à Octoprint ;
- la led s'arrête de clignoter dès que le bouton est relaché.
Voici une photo de l'ensemble monté :
Webcam
La webcam permet de suivre l'impression de la pièce depuis soit un ordinateur, soit un smartphone. Super pratique, inutile donc indispensable
Matériel
J'ai ressorti de mes caisses un vieux modèle : une Logitech Quickcam E1000 offrant une résolution de… 640×480 !!
Le positionnement de la caméra est important ainsi que l'éclairage. J'ai testé plusieurs positions de celle-ci : sur la planche de bois verticale à droite de l'imprimante. L'image était correcte mais la webcam se prenait des coups car les outils les plus fréquement utilisés sont placés juste au dessus. La fixation de la webcam est réalisée à l'aide d'un ensemble de support s'emboitant les uns dans les autres ainsi qu'un adaptateur pour mon modéle de caméra : cet ensemble est très modulaire et stable.
J'ai alors changé sa position en la fixant sur le rail de l'imprimante.
Désormais, elle ne gène plus le passage vers les outils et offre une meilleure visibilité sur les impressions basses.
Logiciel
La webcam est dans une pièce sombre et produisait initialement des images presque noires. Pour améliorer cela, j'ai désactivé la correction automatique de l'exposition avec v4l2-ctl
, l'image devient alors plus claire et exploitable.
Pour commencer, installer le paquet v4l-utils
:
sudo apt-get install v4l-utils
Puis configurer la webcam et vérifier dans octoprint le rendu :
v4l2-ctl --set-ctrl exposure_auto=1
v4l2-ctl --set-ctrl exposure_absolute=3
Avant :
Après :
Enfin, pour l'activiter au démarrage, ajouter la ligne suivante en fin du fichier /etc/rc.local
:
- /etc/rc.local
... nohup bash -c "sleep 30; v4l2-ctl --set-ctrl exposure_absolute=1; sleep 1; v4l2-ctl --set-ctrl exposure_auto=3" & ...
Cette commande permet de configurer la webcam 30 secondes après la fin du boot du Raspberry Pi.
Préchauffe automatique
Avant de lancer une impression, j'attends toujours une dizaine de minutes afin que la chaleur se diffuse bien sur le plateau et soit stabilisée. Pour ne pas oublier cette préchauffe et gagner un peu de temps entre l'allumage de l'imprimante et ce temps d'attente, cette opération est réalisée automatiquement au démarrage du Pi à l'aide du script suivant. Le lit est chauffé à 45°C et le hotend à 210°C :
- /home/pi/pre-heat.sh
#!/bin/bash -e API_KEY="<TOKEN OCTOPRINT>" HEAD_TEMP=210 BED_TEMP=45 # head curl -X POST -H "X-Api-Key: ${API_KEY}" -H "Content-Type: application/json" --data '{"commands": ["M117 Pre heating"] }' http://localhost/api/printer/command curl -X POST -H "X-Api-Key: ${API_KEY}" -H "Content-Type: application/json" --data '{"command": "target", "targets": { "tool0": '"${HEAD_TEMP}"' } }' http://localhost/api/printer/tool curl -X POST -H "X-Api-Key: ${API_KEY}" -H "Content-Type: application/json" --data '{"command": "target", "target": '"${BED_TEMP}"' }' http://localhost/api/printer/bed
Il est appelé par le script /etc/rc.local
comme pour la webcam :
- /etc/rc.local
... nohup bash -c "sleep 30; /home/pi/heatup.sh" & ...
Temps de démarrage d'OctoPi
J'ai apporté quelques modifications à l'installation de base d'Octopi (distribution Raspbian avec Octoprint pré-installé) pour diminuer le temps de démarrage, changer la luminosité de la webcam et lancer la pré-chauffe de l'imprimante dès le démarrage.
En désactivant plusieurs services non utilisés, j'ai gagné 20 secondes au boot :
sudo systemctl disable hciuart.service # bluetooth sudo systemctl disable apt-daily-upgrade.timer # vérification des mises à jours automatique sudo systemctl disable apt-daily.timer # vérification des mises à jours automatique sudo systemctl disable rpi-display-backlight.service # rétro éclairage de l'éventuel écran sudo systemctl disable rsync.service # service de synchronisation sudo systemctl disable alsa-restore.service # son sudo systemctl disable alsa-state.service # son sudo systemctl disable alsa-utils.service # son sudo systemctl disable man-db.timer # mise à jour de la base de données des pages de manuels sudo systemctl disable triggerhappy.service # boutons périphérique sudo systemctl disable triggerhappy.socket # boutons périphérique