J’ai une idée qui me trotte dans la tête depuis un moment, c’est de réaliser une « poursuite » de satellite pilotée par un Raspberry Pi. L’idée c’est de faire tourner le programme Gpredict sur le Pi, de récupérer les coordonnées et de piloter un duo de moteurs pas à pas pour diriger une (petite) antenne vers un satellite. La première étape est de piloter un moteur pas à pas à partir du Raspberry Pi.
Au sommaire :
Article présenté aux JMRAF 2022
En direct le 16 avril. Je présente cette application du Raspberry Pi vers 18h30 (H de Paris). Vous pouvez gagner mon livre « Raspberry Pi 4 » offert par les Editions ENI.
Commander un moteur pas à pas avec le Raspberry Pi
Le synoptique du montage est le suivant :
Le Raspberry Pi envoie au driver A4988 une direction (sens horaire CW, ou anti horaire CCW) et sur un autre GPIO on sort des impulsions qui provoqueront chacune une avance d’un pas.
Le nombre de pas par tour est déterminé par les entrées MS1 à MS3. Par d&f&ut le moteur PaP fait un tour en 200 pas (de 1,8°) mais on peut modifier le nombre de micro-pas fournis par le driver pour affiner le déplacement.
Le montage tel qu’il sera réalisé est présenté ici avec Fritzing. Le module supporte une alimentation de puissance pour le moteur comprise entre 8 et 35 volts. Ici j’ai opté pour une alimentation 12 volts, suffisante pour fournir le courant souhaité au moteur.
La câblage une fois réalisé donne ceci. J’ai muni le moteur PaP d’une flèche en impression 3D pour vérifier que ses déplacements sont conformes à ce qui est attendu
Ici le module A4988 avant la pose du radiateur sur le circuit de commande. La potentiomètre sert à régler le courant qui circule dans les bobines du moteur car le moteur est alimenté en courant, pas en tension. C’est le module qui va limiter le courant envoyé dans les bobines du moteur. Ne pas oublier que tant que le montage est alimenté le moteur est maintenu en position par le courant qui circule dans les bobines… Donc… il chauffe. Vous pouvez consulter la notice du A4988 en cliquant sur ce lien.
Détecteur de zéro
Le moteur pas à pas n’a pas de repère lors de sa mise sous tension. Sur les imprimantes 3D par exemple, on utilise
Un switch optique
« Fourchette » optique utilisée comme détecteur. D’un côté une LED envoie un faisceau lumineux, de l’autre un phototransistor le reçoit. Quand le faisceau est interrompu, la sortie change d’état.
Dans le monde des makers, on retrouve ce genre de détecteur sur les imprimantes 3D, par exemple. Ici une Anycubic Viper.
Le détecteur optique utilisé ici, lors des tests. Une LED s’éteint quand le faisceau est interrompu.
Premiers essais sur la barre fixée au moteur PaP.
Un switch mécanique
Switch mécanique, ici un swicth équipé d’un rouleau.
Exemple d’utilisation du switch mécanique (sur mon imprimante 3D). Lorsque le chariot appuie sur le switch, la carte mère considère que c’est la position Zero. Il y a un switch sur chacun des 3 axes.
Les programmes
Programme de démo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#!/usr/bin/python3 # Pour exécuter le prog. en ligne de commande from time import sleep # Importer la bibliothèque de gestion du temps import RPi.GPIO as GPIO # Importer la bibliothèque de gestion des GPIO STEP = 14 # La commande de pas est reliée au GPIO 14 DIR = 15 # La commande de direction est reliée au GPIO 15 vitesse = 0.0005 GPIO.setmode(GPIO.BCM) # Paramétrage de la numérotation des GPIO en mode BCM GPIO.setwarnings(False) # Ne pas tenir comte des alertes GPIO.setup(STEP, GPIO.OUT) # GPIO STEP configuré en sortie GPIO.setup(DIR, GPIO.OUT) # GPIO DIR configuré en sortie # Tourner d'un nombre de pas en CW ou CCW def tourne(pas, sens, vitesse): # Sens de rotation if (sens == "CW"): GPIO.output(DIR, GPIO.HIGH) else: GPIO.output(DIR, GPIO.LOW) # Avancer du nombre de pas for x in range(pas): GPIO.output(STEP, GPIO.HIGH) sleep(vitesse) GPIO.output(STEP, GPIO.LOW) sleep(vitesse) while True: # On travaille en 1/16 de pas soit 3200 micropas par tour for x in range(3200): GPIO.output(STEP, GPIO.HIGH) sleep(vitesse) GPIO.output(STEP, GPIO.LOW) sleep(vitesse) sleep(1) GPIO.output(DIR, GPIO.LOW) for x in range(3200): GPIO.output(STEP, GPIO.HIGH) sleep(vitesse) GPIO.output(STEP, GPIO.LOW) sleep(vitesse) sleep(1) tourne(1600, "CW", vitesse) sleep(0.5) tourne(1600, "CCW", vitesse) sleep(1) tourne(800, "CW", vitesse) sleep(0.5) tourne(800, "CW", vitesse) sleep(0.5) tourne(800, "CW", vitesse) sleep(0.5) tourne(800, "CW", vitesse) sleep(1) |
Commande du moteur au clavier
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#!/usr/bin/python3 # Pour exécuter le prog. en ligne de commande from pynput import keyboard # Bibliothèque de gestion clavier from time import sleep # Bibliothèque de gestion du temps import RPi.GPIO as GPIO # Bibliothèque de gestion des GPIO STEP = 14 # La commande d'avance d'un pas est connectée à GPIO14 DIR = 15 # La commande du sens de rotation est connectée à GPIO15 vitesse = 0.0005 # Temps d'attente entre les pas : règle la vitesse GPIO.setmode(GPIO.BCM) # Utiliser la numérotation BCM pour les GPIO GPIO.setwarnings(False) # Ne pas afficher les alertes GPIO.setup(STEP, GPIO.OUT) # Paramétrer GPIO14 en sortie GPIO.setup(DIR, GPIO.OUT) # Paramétrer GPIO15 en sortie # Tourner d'un nombre de pas en CW ou CCW à une vitesse donnée def tourne(pas, sens, vitesse): # Sens de rotation if (sens == "CW"): GPIO.output(DIR, GPIO.HIGH) else: GPIO.output(DIR, GPIO.LOW) # Avancer du nombre de pas for x in range(pas): GPIO.output(14, GPIO.HIGH) sleep(vitesse) GPIO.output(14, GPIO.LOW) sleep(vitesse) # Fonction appelée quand une touche est appuyée def appui(key): try: print('Touche alphanumérique : {0} '.format( key.char)) except AttributeError: print('Touche spéciale : {0}'.format( key)) # Touche flèche gauche - Sens inverse des aiguilles d'une montre - 10 pas if (key == keyboard.Key.left): sens = "CCW" tourne(10,sens,vitesse) # Touche flèche droite - Sens des aiguilles d'une montre - 10 pas elif (key == keyboard.Key.right): sens = "CW" tourne(10,sens,vitesse) # Touche flèche haute - Sens inverse des aiguilles d'une montre - 100 pas elif (key == keyboard.Key.up): sens = "CCW" tourne(100,sens,vitesse) # Touche flèche basse - Sens des aiguilles d'une montre - 100 pas elif (key == keyboard.Key.down): sens = "CW" tourne(100,sens,vitesse) # Touche page haute - Sens inverse des aiguilles d'une montre - 800 pas = 1/4 de tour elif (key == keyboard.Key.page_up): sens = "CCW" tourne(800,sens,vitesse/10) # Touche page basse - Sens des aiguilles d'une montre - 800 pas = 1/4 de tour elif (key == keyboard.Key.page_down): sens = "CW" tourne(800,sens,vitesse/10) # Fonction exécutée quand une touche est relachée def relache(key): print('Key released: {0}'.format( key)) # Si c'est la touche ESC on sort du programme if key == keyboard.Key.esc: # Stop listener print("Sortie du programme") GPIO.cleanup() return False # Le listener collecte les événements et appelle les fonctions en callback with keyboard.Listener( on_press = appui, on_release = relache) as listener: listener.join() |
Et après ?
L’étape suivante sera de récupérer l’azimut d’un satellite dans Gpredict pour piloter le moteurs d’azimut. Actuellement j’ai testé plusieurs serveurs TCP (puisqu’on passe par un socket IP) dont celui de F6BVP. Mais après un moment Gpredict affiche une erreur de lecture de ca que renvoie le serveur et coupe la communication. Je n’ai pas trouvé comment maintenir la liaison… SI vous avez une solution, je suis preneur.
Vidéo
Programmes sur Github
https://github.com/framboise314/RasPi_PaP
Un coup de main SVP [RESOLU]
Merci à Frédéric qui a déverminé le dialogue entre Gpredict et le serveur TCP. Ça fonctionne maintenant. Le serveur est sur Github en version Py2 et Py3.
Le souci était que la fonction de Gpredict qui reçoit la réponse de rotctl (en fait ici le serveur TCP maison) zappe les 4 premiers caractères de la chaîne. Il faut donc renvoyer « xxxx0 » pour que ça fonctionne sans planter au bout de quelques erreurs…
BESOIN D’AIDE GPREDICT sur RASPI :
Suite à la présentation de la commande d’un moteur pas à pas avec le Raspberry Pi lors des #jmraf2022, j’essaye vainement de récupérer les infos d’azimut depuis #Gpredict sur #RaspberryPi. J’utilise un serveur tcp minimum sur le raspberry pi. J’en ai trouvé plusieurs, très semblables mais aucun ne fonctionne correctement. Je ne vois pas ce que je fais comme conn… bêtise.
Je lance Gpredict, choix d’un satellite visible, mise en route du contrôleur de rotor d’antenne.
Dans une fenêtre de terminal, lancement du mini serveur TCP
J’engage le suivi sur Gpredict => connexion ok au serveur tcp
Je lance le tracking sur le contrôleur de rotor de Gpredict. Les infos azimut+elevation arrivent bien au serveur mini tcp, qui renvoie les mêmes valeurs en réponse. Mais au bout d’un (court) moment Gpredict signale une erreur de reception des données, et le serveur annonce avoir reçu S\n et met fin à la liaison.
J’ai essayé en python 2 et python 3, en fr_fr et en GB pour les locales (à cause du problème possible de . ou de , dans les nombres flottants mais c’est pareil
J’ai testé avec les serveurs tcp trouvés ici (très proches les uns des autres).
Exemple serveur TCP : https://adventurist.me/posts/0136
Programme de F6BVP :
https://radiotelescopelavillette.wordpress.com/interface-rotor/
Après c’est possible qu’ils aient testé avec une autre version de Gpredict, sur un PC Windows… il y a peu d’infos là dessus.
Si quelqu’un a fait fonctionner cette liaison en interne sur RasPi, je suis preneur de toute info.
j’ai ouvert une page github ou toutes les infos seront publiées (avec le nom de tous les participants bien entendu) https://github.com/framboise314/RasPi_PaP
Sources
Lire touches clavier :
https://www.delftstack.com/fr/howto/python/python-detect-keypress/
Communication socket Python : https://info.blaisepascal.fr/nsi-sockets-python
Exemple serveur TCP : https://adventurist.me/posts/0136
Programme de F6BVP : https://radiotelescopelavillette.wordpress.com/interface-rotor/
http://radiotelescope.over-blog.com/2020/09/mise-en-place-de-la-poursuite-en-azimut-et-elevation-avec-gpredict.html
Protocole rotctld : http://manpages.ubuntu.com/manpages/trusty/man8/rotctld.8.html
Gérer les threads : http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_parallelisation/thread.html
Encore un super truc
décidément vous n’arrêtez pas
Merci Christian 🙂
Ping : Piloter un moteur pas à pas avec un Raspberry Pi et un driver A4988 - TUTO3D