Les moteurs pas-à-pas sont souvent utilisés lorsqu’une bonne précision est désirée en boucle ouverte notamment dans les systèmes de positionnement tels que les imprimantes 3D. Nous allons voir, dans cet article, comment programmer la carte Raspberry Pi pour pouvoir piloter un moteur pas-à-pas.
Prérequis: Programmez avec Raspberry Pi
Matériel
- Écran
- HDMI câble
- Clavier
- Raspberry PI 3 (avec OS sur micro SD)
- Souris
- Chargeur micro USB B
- ULN2003APG x1
- Moteur pas-à-pas
Moteur Pas-à-pas
Les moteurs pas-à-pas possèdent différentes phases qui permettent d’orienter la position du rotor. On peut donc transformer une séquence d’impulsions sur les différentes phases en déplacement angulaire. Comme la séquence à envoyer pour obtenir un certain déplacement est connue, on peut connaitre la position sans capteur supplémentaire et donc piloter le moteur précisément en boucle ouverte.
Ils existent deux types principaux de moteur pas-à-pas unipolaire (5 ou 6 fils) et bipolaire (4 fils) avec des caractéristiques pouvant varier comme le nombre de pas par révolution. Ces différences entrainent des modifications sur les paramètres de pilotage notamment sur le nombre de sorties nécessaires pour piloter le moteur. Afin de piloter correctement votre moteur, il est impératif d’avoir ces informations.
Transistor
Les moteurs pas-à-pas, comme leur nom l’indique, se pilotent pas à pas en appliquant la puissance électrique par séquence d’impulsions aux différentes phases du moteur. Pour les moteurs unipolaires, on utilise un réseau de transistor, comme le ULN2003A qui possèdent un réseau de 7 transistors.
Pour les moteurs bipolaires, nous utilisons un pont en H, SN754410NE, qui peut piloter les deux bobines indépendantes du moteur.
Schéma de connexion
Le moteur se pilote via le module de pilotage ULN2003A. Les entrées du module de 1 à 4 se connectent aux broches 18,22,24,26 (GPIO24,GPIO25,GPIO8,GPIO7) respectivement. Les bornes + et – du module se connectent aux broches 5V et masse du Raspberry Pi.
Selon la puissance du moteur utilisé, il peut s’alimenter par la borne 5V de la carte Raspberry Pi mais il est fortement conseillé d’utiliser une source de puissance extérieur afin de protéger le microcontrôleur.
Pour rappel, voici la description des broches du Raspberry Pi 3.
Code de base pour le contrôle d’un moteur pas-à-pas
Pour piloter le moteur pas-à-pas, nous définissons une séquence d’activation des phases du moteur qui va permettre au rotor de tourner. Le nombre de pas par révolution permet de connaître l’angle parcouru pour un pas (dans notre cas 2048).
Ce code permet de faire fonctionner le stepper 28BYJ-48 130061869. Les moteurs pas-à-pas peuvent être assez différents, il vous faut donc vérifier votre matériel avant de pouvoir le piloter.
#!/usr/bin/env python # -*- coding: utf-8 -*- # libraries import time import RPi.GPIO as GPIO # Use BCM GPIO references # Instead of physical pin numbers GPIO.setmode(GPIO.BCM) # Define GPIO signals to use Pins 18,22,24,26 GPIO24,GPIO25,GPIO8,GPIO7 StepPins = [24,25,8,7] # Set all pins as output for pin in StepPins: print("Setup pins") GPIO.setup(pin,GPIO.OUT) GPIO.output(pin, False) # Define time delay between steps WaitTime = 0.005 #set speed # Define simple sequence StepCount1 = 4 Seq1 = [] Seq1 = [i for i in range(0, StepCount1)] Seq1[0] = [1,0,0,0] Seq1[1] = [0,1,0,0] Seq1[2] = [0,0,1,0] Seq1[3] = [0,0,0,1] # Define advanced half-step sequence StepCount2 = 8 Seq2 = [] Seq2 = [i for i in range(0, StepCount2)] Seq2[0] = [1,0,0,0] Seq2[1] = [1,1,0,0] Seq2[2] = [0,1,0,0] Seq2[3] = [0,1,1,0] Seq2[4] = [0,0,1,0] Seq2[5] = [0,0,1,1] Seq2[6] = [0,0,0,1] Seq2[7] = [1,0,0,1] # Choose a sequence to use Seq = Seq2 StepCount = StepCount2 def steps(nb): StepCounter = 0 if nb<0: sign=-1 else: sign=1 nb=sign*nb*2 #times 2 because half-step print("nbsteps {} and sign {}".format(nb,sign)) for i in range(nb): for pin in range(4): xpin = StepPins[pin] if Seq[StepCounter][pin]!=0: GPIO.output(xpin, True) else: GPIO.output(xpin, False) StepCounter += sign # If we reach the end of the sequence # start again if (StepCounter==StepCount): StepCounter = 0 if (StepCounter<0): StepCounter = StepCount-1 # Wait before moving on time.sleep(WaitTime) # Start main loop nbStepsPerRev=2048 if __name__ == '__main__' : hasRun=False while not hasRun: steps(nbStepsPerRev)# parcourt un tour dans le sens horaire time.sleep(1) steps(-nbStepsPerRev)# parcourt un tour dans le sens anti-horaire time.sleep(1) hasRun=True print("Stop motor") for pin in StepPins: GPIO.output(pin, False)
N.B.: Faites attention aux indentations lorsque vous écrivez ou recopiez un code. Vous risqueriez d’avoir des erreurs de compilation.
Sources
- La THE référence https://www.raspberrypi.org/help/
- Programmez avec Raspberry Pi
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie
ça ne fonctionne pas avec mon raspberry 3B+
Pouvez-vous être plus précis qu’est-ce qui ne fonctionne pas? quel moteur utilisez-vous? le moteur ne réagit pas du tout?
Bonjour Xukyo,
J’ai un Raspberry 3B+ sur lequel j’ai installé Ubuntu mate et geany pour lire et faire tourner le code python.
J’ai un moteur 28BYJ-48 5V DC 20005852, relié à un transistor ULN2003 A lui même relié au raspberry selon le schéma indiqué ci-dessous.
Après avoir copier/coller le code dans geany et fait tourner j’ai les messages suivant :
Setup pins
test_focuser.py:14: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
GPIO.setup(pin,GPIO.OUT)
Setup pins
Setup pins
Setup pins
nbsteps -4096 and sign -1
nbsteps -4096 and sign 1
Stop motor
——————
(program exited with code: 0)
Press return to continue
Et le moteur n’a pas bougé d’un pouce …
Bonjour, il semble qu’il y ait une erreur avec le code. Pouvez-vous essayer la modification suivante?
if nb<0: sign=-1
else: sign=1
Bonjours je comprend pas que qui ne fontionne pas. il code est identique a celui indiquer et jai lu les commentaire mais il semble que tu a deja corriger le code donc je voit pas ce qui coche? Peut tu aidez?
Setup pins
mstep.py:17: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
GPIO.setup(pin,GPIO.OUT)
Setup pins
Setup pins
Setup pins
nbsteps 4096 and sign 1
nbsteps 4096 and sign -1
Stop motor
jai trouver et ca marche jai mal copiez le code desolé
pas de soucis. content que tu aies trouvé la solution!
Bonjour, le programme ne fonctionne pas j’au une erreur ‘StepCount1’ is not defined.
En debug, il demande de vérifier les lignes 24, 25, 32 33, 44 , 52 et 53.
Et je ne perçois pas l’origine de l’erreur.
Peux-tu me donner un coup de main.
Sorry, Erreur trouvée. Recopie imparfaite. Cela fonctionne… 🙂
Nickel!
J’ai rajouté un GPiO.cleanup pour chaque pin en fin de programme et ça change rien.
J’ai acheté mon matériel là :
https://www.amazon.fr/gp/product/B07PPKS7GZ/ref=ppx_yo_dt_b_asin_title_o09_s01?ie=UTF8&psc=1
Autre chose :
quand je met un print Range(nb) juste avant fir i in range(nb) il m’affiche ( ).
Et qand le met un print StepCounter juste après StepCounter += sign il m’affiche rien du tout.
Il se passe rien car il a pas l’air de rentrer dans la boucle for i in range(nb) ….
Excellent Xukyo, j’ai fait la modif sur le sign que tu as indiqué plus haut et ça marche ! Merci beaucoup 🙂
Bonne nouvelle! merci à toi d’avoir testé le code
Derniere question rapide, sais tu quelle roue dentée s’adapte au petit axe qui tourne de ce moteur qui a une forme particulière ??
Il faut mesurer le diamètre de l’axe et regarder pignon en nylon ou acier. Tu peux aussi l’imprimer en 3D.
A quoi sert la variable i ???
Bonsoir, elle sert simplement à créer la boucle « for » sur le nombre de pas demandé.
Bonjour, je dois déplacer un robot qui dessine, j’utilise un uln 2803A pour piloter 2 moteurs 28BYJ-48 en même temps, aurait tu un bout de code pour déplacer les 2 moteurs en même temps ?
Pour piloter deux stepper en parallèle, je te conseille d’utiliser la librairie threading.
t1=threading.Thread(target=Stepper1.moveAngle,args=(-(qR[0]-angN1[0])*180/math.pi))
t2=threading.Thread(target=Stepper2.moveAngle,args=((qR[1]-angN1[1])*180/math.pi))
t1.start()
t2.start()
t1.join()
t2.join()
Bonjour, je souhaite jouer sur la vitesse de rotation mais après avoir bidouiller la plupart des variables je n’arrive pas à savoir laquelle me permet de le faire !
Est-il possible de m’éclairer?
Merci d’avance
Bonjour,
Pour changer la vitesse vous pouvez modifier ce gain
WaitTime = 0.005 #set speed