S'équiper

Vous voulez participer au financement du blog. C’est simple, suivez les liens commerciaux pour faire vos achats. Quelques pourcents qui font toute la différence. Merci à vous !

Débuter
S'équiper
Matériel recommandé

Vous voulez participer au financement du blog. C’est simple, suivez les liens commerciaux pour faire vos achats. Quelques pourcents qui font toute la différence. Merci à vous !

Kit raspberry pi 4 8GB
Kit Raspberry Pi 4 - 8GB
kit raspberry pi 4
Kit Raspberry Pi 4 - 4GB
raspberry pi 4 2019
Raspberry Pi 4 - 4GB
Cartes micro-SD SDHC v90
Kit Retrogaming Nespi
Kit Retrogaming

Piloter un moteur pas à pas Nema 17 avec la librairie RpiMotorLib Python pour A4988

drive nema motor raspberrypi a4899 python flask hmtl interface
Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram
logo github

Code source

La librairie RpiMotorLib pour Python 3 permet de piloter très simplement les moteurs pas à pas (pilote ULN2003,  L298N, A4988, DRV8825, A3967 ou TB6612FNG) et les moteurs à courant continu via le GPIO du Raspberry Pi. Les moteurs pas à pas sont très largement utilisés pour réaliser les mouvements des axes des imprimantes 3D, des graveurs laser et commandes numériques (CNC).

 

Pour ce tutoriel, nous allons utiliser un moteur pas à pas Nema 17 (précisément 17HS4401) piloté par un micro-contrôleur A4988, deux composants très largement employés dans les imprimantes 3D et CNC à assembler soi-même.

Installer les librairies RpiMotorLib et Flask

Pour pouvoir fonctionner, la librairie RpiMotorLib nécessite Python 3.5 ou supérieur. La version Desktop de Raspberry Pi OS est installée avec les versions 2.7 et 3.7 ou ultérieures. Pour vérifier que la version 3 est bien installée, exécutez la commande suivante dans un Terminal.

Si Python3 est correctement installé, vous devez obtenir le numéro de version en réponse.

python3 --version
Python 3.7.3

Pour installer les librairies Python, on aura besoin du script pip3. Pour vérifier qu’il est bien installé, exécuter cette commande qui doit vous renvoyer le chemin vers le script

pip3 --version

Si pip3 n’est pas installé, exécuter

sudo apt install python3-pip

Maintenant, on peut installer les librairies

sudo pip3 install rpimotorlib
python3 -m pip install Flask

Que peut-on piloter avec la librairie RpiMotorLib ?

La librairie développée par Gavin Lyons permet de piloter des moteurs pas à pas (stepper motors), des servo-moteurs et moteurs à courant continu. Pour chaque type de mouvement, plusieurs contrôleurs sont pris en charge. Voici la liste avec le renvoi vers la documentation en ligne pour le câblage et un petit exemple de code.

Moteurs pas à pas (Stepper motors)

Moteur Contrôleur Circuit et exemple
Unipolaire 28BYJ-48

28BYJ-48 motor

ULN2003 Consulter
Bipolaire Nema

moteur nema bipolaire

L298N H-Bridge Consulter
A4988 Stepper Driver Carrier Consulter
DRV8825 Pont en H simple Consulter
A3967 Stepper Driver aussi connu sous le nom “easy driver v4.4” Consulter
TB6612FNG, pilote 1 ou 2 moteurs Consulter

Moteurs à courant continu (DC Motor)

Contrôleurs supportés par la librairie pour piloter les moteurs à courant continu

Contrôleur Circuit et exemple
L298N L298N Consulter
transistor Transistor Consulter
L9110S L9110S Consulter
DRV8833 DRV8833 Pont en H simple Consulter
TB6612FNG TB6612FNG Consulter

Liste des fonctions proposées par la librairie

Les fonctions proposées par la librairie varient en fonction de contrôleur utilisé et du type de moteur.

Classe Fonction Paramètres
Code source du fichier RpiMotorLib.py
BYJMotor print_cursor_spin Fonction dépréciée
motor_run(gpiopins, wait=.001, steps=512, ccwise=False, verbose=False, steptype=”half”, initdelay=.001
)
GPIOPins type liste de 4 entiers longs. Broches du GPIO sur lesquels sont connectées le contrôleur.

wait type float, temps d’attente (en secondes) entre chaque pas (steps)

steps. type int. Nombre de séquences d’étapes exécuter. La valeur par défaut est une révolution, 512 pour le 28BYJ-48.

ccwise sens antihoraire par défaut. True pour inverser le sens

verbose True pour activer la mise au point

steptype type string. half par défaut. Type de pilote. 3 options : full (fullstep), half (half step), wave (wave drive)

initdelay type float, 1ms par défaut. Délai d’attente après l’initialisation avant de lancer le mouvement.

A4988

Contrôleurs supportés

A4988

DRV8825

motor_go(clockwise=False, steptype=“Full”,steps=200, stepdelay=.005, verbose=False, initdelay=.05) clockwise sens de rotation dans le sens des aiguilles d’une montre par défaut. True pour inverser

steptype chaîne, par défaut Full. Type de moteur pas à pas. 5 options Full, Half, 1/4, 1/8, 1/16, 1/32

steps entier. Nombre de pas à exécuter, 200 par défaut

stepdelay type float, par défault 0.05 seconde. Temps d’attente entre chaque pas.

verbose True pour activer les messages de mise au point

initdelay type float, 0.05 s par défaut. Délai d’attente après l’initialisation avant de lancer le mouvement.

Code source du fichier rpi_dc_lib.py
L298NMDc

DRV8833NmDc

initialisation(pin_one, pin_two, freq=50, verbose=False, name=”DCMotorY”) pin_one type int, broche de direction connectée à IN1 ou IN3

pin_two type  int, broche PWM du GPIO pour la vitesse connectée à IN2 ou IN4

Freq fréquence en Hz par défaut 50

verbose True pour activer les messages de mise au point

Name aucune utilité

forward(duty_cycle=50) Marche avant
backward(duty_cycle=50) Marche arrière
stop(duty_cycle=0) Arrête le moteur
brake(duty_cycle=100) Freine le moteur
cleanup(clean_up=False) Libère le GPIO. A utiliser en cas de problème de communication
TranDc initialisation(pin, freq=50, verbose=False) Classe pour contrôler un moteur à courant continu via un transistor

pin type  int, broche PWM du GPIO pour la vitesse connectée à IN2 ou IN4

Freq fréquence en Hz par défaut 50

verbose True pour activer les messages de mise au point

TB6612FNGDc initialisation(pin_one, pin_two, pwm_pin, freq=50, verbose=False, name=”DCMotorY”) pin_one Broche GPIO connectée à AI1 ou BI1

pin_two Broche GPIO connectée à AI2 ou BI2

pwm_pin Broche GPIO connectée à PWA ou PWB

Freq fréquence en Hz par défaut 50

verbose True pour activer les messages de mise au point

Name aucune utilité

standby(standby_pin, standby_on=True)
standby_pin Broche GPIO connectée à la broche standby du TB661FNG

Active / désactive le mode veille du contrôleur TB661FNG

forward(duty_cycle=50) Marche avant
backward(duty_cycle=50) Marche arrière
stop(duty_cycle=0) Arrête le moteur
brake(duty_cycle=100) Freine le moteur
cleanup(clean_up=False) Libère le GPIO. A utiliser en cas de problème de communication

Remarque concernant l’arrêt des mouvements des moteurs pas à pas

Le librairie RpiMotorLib n’offre aucune méthode pour stopper le mouvement en cours un pour les moteurs pas à pas.

On ne pourra pas arrêter en cas d’urgence ou manuellement les mouvements gérés par les micro-contrôleurs BYJMotor, A4988 et DRV8825.
Attention également à ne pas débrancher les broches durant un mouvement. Cela peut endommager le GPIO du Raspberry Pi ou du micro-contrôleur.

Circuit

Le GPIO du Raspberry Pi (quelque soit le modèle et la génération) ne délivre pas suffisamment de puissance pour alimenter directement un moteur Nema (ou n’importe quel autre moteur d’ailleurs).

La contrôleur A4988 dispose d’une entrée 12V qu’il suffira d’alimenter à l’aide d’une batterie ou sur le secteur. L’A4988 doit également être alimenté en 5V. Si vous n’avez qu’un seul accessoire connecté au GPIO, le Raspberry Pi peut délivrer suffisamment de puissance.

Il existe des cartes d’alimentation multi-tension permettant de délivrer suffisamment de puissance pour ce type de montage.

N’oubliez pas de connecter les broches Reset et Sleep à l’aide d’un jumper sinon le micro-contrôleur reste en veille. La librairie RpiMotorLib ne permet pas de gérer la sortie de veille uniquement lorsqu’un mouvement est demandé. Cela signifie que le moteur reste sous tension en permanence.

Voici le repérage des broches en détail

Alimentation 12V Broche A4988
+12V de la batterie ou de l’alimentation secteur VMOT
GND de la batterie ou de l’alimentation secteur GND
GPIO du Raspberry Pi (toute version)
5V du Raspberry Pi VDD
GND du Raspberry Pi GND
GPIO 21 STP
GPIO 20 DIR
Vers le moteur pas à pas

Généralement le moteur est livré avec un câble 4 broches  muni d’un connecteur au pas de 2,54mm. Si le déplacement est inversé, inverser le connecteur ou modifiez le code Python

1A, 1B, 2A, 2B
GPIO 14 MS1
GPIO 15 MS2
GPIO 18 MS3
Connecter les broches RESET et SLEEP ensembles

Schéma de câblage du circuit

A4988 Nema 17 raspberry pi python circuit

Exemple de projet Python permettant de déplacer un Moteur Nema 17

Ouvrez l’éditeur de code Thonny Python IDE accessible depuis le menu Programmation. 

raspberry pi os thonny python ide

Coller le code Python ci-dessous

#! /usr/bin/python
# -*- coding:utf-8 -*-
from RpiMotorLib import RpiMotorLib
from flask import Flask, render_template_string, redirect, request

#define GPIO pins
GPIO_pins = (14, 15, 18)    # Microstep Resolution MS1-MS3 -> GPIO Pin
direction= 20               # Direction Pin, 
step = 21                   # Step Pin
distance = 80               # Default move 1mm => 80 steps per mm


# Declare an named instance of class pass GPIO pins numbers
mymotortest = RpiMotorLib.A4988Nema(direction, step, GPIO_pins, "A4988")

app = Flask(__name__)

#HTML Code 

TPL = '''
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

        <title>Stepper Motor Controller</title>
    </head>
    <body>
      <div class="container">
        <div class="row" style="padding:10">
          <div class="col-sm-1">
            <form method="POST" action="up" class="center-block">
                <button type="submit" class="btn btn-primary">Up</button>
            </form>
          </div>
          <div class="col-sm-1">
            <form method="POST" action="down" class="center-block">
                <button type="submit" class="btn btn-primary">Down</button>
            </form>
          </div> 
        </div>   
            <form method="POST" action="setdistance">
                <div class="btn-group" role="group" >
                  <button name="distance" type="submit" class="btn btn-secondary" value="8">0.1 mm</button>
                  <button name="distance" type="submit" class="btn btn-secondary" value="80">1 mm</button>
                  <button name="distance" type="submit" class="btn btn-secondary" value="800">10 mm</button>
                </div>
            </form>  
        
      </div>   
    </body>
</html>

'''
 
@app.route("/")
def home():
    return render_template_string(TPL)

@app.route("/setdistance", methods=["POST"])
def setdistance():
    global distance
    global distance
    distance = int(request.form["distance"])
    print("set distance to", distance)
    return redirect(request.referrer)
     
@app.route("/up", methods=["POST"])
def up():
    global distance
    print("Move up,", distance, "steps")
    mymotortest.motor_go(False, "Full" , distance, 0.01 , False, .05)
    return redirect(request.referrer)

@app.route("/down", methods=["POST"])
def down():
    global distance
    print("Move down,", distance, "steps")
    mymotortest.motor_go(True, "Full" , distance, 0.01 , False, .05)
    return redirect(request.referrer)
 
# Run the app on the local development server
if __name__ == "__main__":
    app.run()

Cliquer sur la flèche verte pour lancer le script

thonny python ide start script

Ouvrir Chromium et saisir l’adresse http://127.0.0.1:5000 dans la barre d’adresse.

drive nema stepper motor rapsberry pi python rpimotorlib a4988

Utiliser le sélecteur pour choisir le déplacement à effectuer : 0.1mm, 1mm ou 10mm

Puis la direction du mouvement :

  • UP pour  monter
  • DOWN pour descendre

Voici une petite vidéo de démonstration

Code d’initialisation du contrôleur

Comme nous l’avons vu au paragraphe précédent, on doit attribuer 5 broches au micro-contrôleur A4988. MS1, MS2, MS3, step et inversion de direction.

On créé ensuite un objet RpiMotorLib.A4988Nema que l’on pourra ensuite utiliser dans le code du projet

GPIO_pins = (14, 15, 18)    # Microstep Resolution MS1-MS3 -> GPIO Pin
direction= 20               # Direction Pin,
step = 21 # Step Pin 
mymotortest = RpiMotorLib.A4988Nema(direction, step, GPIO_pins, "A4988")

Explication du code

Nous allons créer une interface Web pour piloter le moteur Nema à l’aide de la librairie Flask.

from flask import Flask, render_template_string, redirect, request

Ici la page HTML est stocké directement dans la chaîne TPL. On importe la feuille de style Bootstrap 4.0 directement depuis internet. Pour changer de version, rendez-vous ici.

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

Avec Flask, il suffit de quelques lignes de code pour créer un serveur Web

app = Flask(__name__)
if __name__ == "__main__":
  app.run()

Comme la plupart des framework HTML, Flask gère des points de sortie (endpoint), l’adresse de la page Web. Par défaut lorsqu’on arrive sur un site internet (la racine), la page se par /

On créé donc une route pour chaque page et chaque action soumise submit par un formulaire.

Le décorateur @ permet de spécifier un endpoint et la fonction (immédiatement après) à exécuter dès que la page est appelée par l’utilisateur. La méthode home renvoie la page principale dont le code source est stocké dans la chaine TPL au début du projet.

@app.route("/")
def home():
    return render_template_string(TPL)

Le rendu des pages Web peut être fait de 3 manières

  • Renvoyer directement le code HTML sous la forme d’une chaîne.
return "<h1>Hello World</h1>"
  • Le code HTML est stocké dans une chaîne de caractères.  Dans ce cas, on utilise la méthode render_template_string pour réaliser le rendu. C’est la solution utilisée dans le projet.
  • A partir d’un fichier HTML stocké dans un fichier séparé à l’aide de la méthode render_template

On envoi les commandes au code Python à l’aide de requêtes HTTP de type POST. Pour cela, il suffit de placer les commandes (les boutons en l’occurence) dans un Formulaire.

Ici, le code du bouton UP qui permet de lancer le déplacement du moteur vers le haut.

<form method="POST" action="up" class="center-block">
  <button type="submit" class="btn btn-primary">Up</button>
</form>

Lorsqu’on souhaite envoyer des paramètres au serveur, on peut par exemple utiliser l’argument value.

La méthode request.form([“name”]) permet de récupérer la valeur de l’argument coté serveur

distance = int(request.form["distance"])

On créé une nouvelle route /up qui accepte la méthode HTTP Post.

La distance à parcourir est stockée dans un variable globale distance. Pour récupérer la valeur de celle-ci dans la méthode up(), il faut faire précédé le nom de la variable par l’argument global afin d’indiquer à l’interpréteur Python qu’on souhaite accéder à la variable globale.

On utilise la méthode motor_go de la librairie RpiMotorLib pour exécuter le déplacement.  Voici les paramètres nécessaires

  • False indique le sens de rotation
  • “Full” type de moteur
  • Distance nombre de pas (step) à faire
  • 0.01 délai d’attente entre chaque pas
  • False exécution silencieuse de la fonction
  • 0.05 secondes délai d’attente avant de lancer le mouvement
Rappel, la librairie RpiMotorLib ne propose aucune fonction pour arrêter la rotation du moteur

Inutile ici de redessiner la page HTML, on renvoi simplement l’utilisateur sur la page d’origine à l’aide de la méthode redirect(request.referrer).

@app.route("/up", methods=["POST"])
def up():
    global distance
    print("Move up,", distance, "steps")
    mymotortest.motor_go(False, "Full" , distance, 0.01 , False, .05)
    return redirect(request.referrer)

Comment calculer le nombre de pas par millimètre parcouru ?

C’est un problème récurrent en impression 3D et CNC. Heureusement, on trouve de nombreux outils pour nous aider. Tout d’abord ce résumé posté par J-Max sur le forum du site lesimprimantes3d.fr nous donne quelques bons conseils

  • Transmission directe à courroie : steps_per_mm = (pas_moteur_par_tour * nb_de_micropas_driver) / (pas_courroie * nombre_de_dents_de_la_poulie)
  • Transmission directe à vis : steps_per_mm = (pas_moteur_par_tour * nb_de_micropas_driver) / pas_du_filetage
  • Extrudeur à entrainement direct (direct drive) : steps_per_mm = (pas_moteur_par_tour * nb_de_micropas_driver) / (diamètre_effectif_galet * pi)
  • Extrudeur à réduction (geared) : steps_per_mm = (pas_moteur_par_tour * nb_de_micropas_driver) * (Nb_dents_plateau / nb_dents_pignon) / (diamètre_effectif_galet * pi)

Vous pouvez également utiliser ces calculateurs en ligne proposés par Prusa, le fabricant d’imprimantes 3D Espagnol bien connu

calculator step per mm leadscrew driven

Mises à jour

20/10/2020 Publication de l’article

English version

 

 

Avez-vous aimé cet article ?
[Total: 0 Moyenne: 0]
Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

Vous rencontrez un problème avec ce sujet ?

Peut-être que quelqu’un a déjà trouvé la solution, visitez le forum avant de poser votre question

Vous avez aimé ce projet ? Ne manquez plus aucun projet en vous abonnant à notre lettre d’information hebdomadaire!

Nous serions ravis de connaître votre avis

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Sondage

Vous avez la parole. Quels sont les thèmes qui vous intéressent en 2021.

Résultats du sondage début janvier.

Merci pour votre confiance. Prenez soin de vous et passez de bonnes fêtes !

Jusqu’à 8 réponses possibles. Vous pouvez faire d’autres propositions. 

Les thèmes qui vous intéressent en 2021
  • Proposer une autre réponse

Utiliser la flèche rouge pour déplier tous les choix.

Publicité
Partager
Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

Table des matières

À Lire aussi
Publicité
Domotique et objets connectés à faire soi-même
Vous avez aimé ce tutoriel

Ne manquez plus les prochains projets

Recevez chaque semaine le récapitulatif des tutoriels et projets.

Vous pouvez vous désabonner à tout moment.