Octoprint / Octopi

03/2019 J'ai installé Octoprint sur un Raspberry Pi 3 B+ à coté de mon imprimante Creality Ender 3 dans le garage.

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 8-).

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.

Boitier
Boitier

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.

Raspberry Pi dans le boitier

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 poussoir

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.

Bouton de préchauffage

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'imprimante
  • M140 : chauffe du lit à 45°C
  • M104 : chauffe du hotend à 210°C
Configuration de Octoprint

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.

Bouton d'annulation
Vue intérieur du bouton d'annulation

La led utilisée possède 4 pattes :

  • 1 pour l'anode (positif)
  • 3 cathodes, une pour le rouge, le vert et le bleu.
Led multicolore

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é :

Bouton d'annulation monté

La webcam permet de suivre l'impression de la pièce depuis soit un ordinateur, soit un smartphone. Super pratique, inutile donc indispensable ;-)

J'ai ressorti de mes caisses un vieux modèle : une Logitech Quickcam E1000 offrant une résolution de… 640×480 !!

Logitech Quickcam E1000

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.

Webcam à droite

J'ai alors changé sa position en la fixant sur le rail de l'imprimante.

Webcam fixée sur l'imprimante

Désormais, elle ne gène plus le passage vers les outils et offre une meilleure visibilité sur les impressions basses.

Vue de la webcam

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 :

Vue de la webcam avant, l'image est sombre

Après :

Vue de la webcam après les réglages, l'image est plus claire

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.

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" &
...

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
  • realisations/raspberry/octopi.txt
  • Dernière modification: 2023/12/30 22:36
  • par admin