IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation multimédia/Jeux Python Discussion :

Python – Raspberry pi - Multithreading – Robotique – Thread interompant un autre thread


Sujet :

Programmation multimédia/Jeux Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Homme Profil pro
    Vivre
    Inscrit en
    Mai 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Vivre

    Informations forums :
    Inscription : Mai 2018
    Messages : 4
    Par défaut Python – Raspberry pi - Multithreading – Robotique – Thread interompant un autre thread
    Bonjour à tous !

    Je me suis mis à la robotique il y a quelques temps et je commence à avoir un joli robot qui gigote bien via un des fameux Raspberry pi 3.
    Seulement, des soucis se posent lors de l'émission et la réception des données pour le contrôler.
    Google ne m'a pa aidé :'(

    Contexte de la question :

    Le robot est constitué de 4 jambes avec :
    - 2 moteurs sur chaque jambe.
    - 2 capteurs de rotation (1 par moteur)
    - 2 capteurs de fin de course (à droite et à gauche)
    -
    Mon but est de concevoir un programme me permettant de contrôler le robot (étonnant, je sais -_- ).

    Pour ce faire, j’ai créé deux threads, un de lecture des données (provenant des capteurs de vitesse et fin de course) et un d’envoi de données (pour commander les moteurs).

    Le but est d’avoir ces deux threads qui tournent en continu en background pendant que le programme fait ses petits calculs pour définir quand un moteur doit tourner ou non.


    Explication légèrement plus aprofondie :

    Pour envoyer et recevoir les données, j’utilise des registres à décalage 16 bits.

    Au cas où, j’explique :
    L’envoi des données se fait via un registre a décalage « Série Parallele 16 Bit » (composant 74hc595) qui comporte 3 broches :
    - « Entrée série » (SER) ou les bits a afficher en sortie seront envoyés 1 a 1
    - « horloge » (CLK) qui permet l’enregistrement du bit en cours et le passage au suivant
    - « horloge de registre » (RCLK) qui permet de charger toutes les données vers les sorties pour les afficher d’un coup
    -
    Le fonctionnement est simple :
    0) Les bits de données à envoyer sont définis par le programme
    1) Le premier bit est chargé à l’entrée série
    2) Un front montant est donné sur l’entrée CLK
    3) Le bit suivant est chargé sur l’entrée série
    4) Un front montant est donné sur l’entrée CLK
    5) Etc.
    6) On répète l’opération pour tous les bits (16x au total, donc)
    7) Un front descendant est envoyé sur RCLK pour charger toutes les données sur les sorties du registre d’un coup
    8) Tadaaa, les moteurs tournent comme on leurs a demandé 😊


    La réception des données se fait via un autre registre à décalage, mais « Parallèle vers série 16 bit » (composant 74hc165) avec aussi 3 broches, 2 entrées et une sortie :
    - La broche de « chargement des données » (PL) permettant de charger l’intégralité des données parallèles dans le registre,
    - la broche « Série » (SER) ou les bits sont lisibles un par un,
    - l’entrée « horloge » (CLK) qui permet de passer au bit suivant.

    Le fonctionnement n’a rien de compliqué non plus :
    1) Un front est envoyé sur PL (actif à l’état bas) qui fait charger les données présentes en entrée des 16 bit dans le registre (tout est sauvegardé d’un coup)
    2) Le dernier bit est immédiatement disponible sur la sortie SER (la lecture se fait à l’envers, du dernier vers le 1er)
    3) On lit le bit
    4) Un front sur l’entrée CLK permet de charger le bit suivant
    5) On lit le bit suivant
    6) Front sur CLK
    7) Etc
    8) On répète les actions 16x au total
    9)
    Donc, ces deux threads vont passer leur temps à envoyer de données pour l’un et recevoir des données pour l’autre.

    Normalement, je peux atteindre une fréquence avoisinant les 70Khz, ce qui est amplement suffisant pour lire les données des capteurs de vitesse des moteurs (ça ne tourne pas trop vite), mais la lecture des ces capteurs semblait complètement fausse…

    Du coup, j’ai dégainé mon oscilloscope (pas d’inquiétude, tout sera expliqué) et je me suis branché sur les entrées CLK et PL du registre à décalage…

    Lors de la réception des données, j’ai pu remarquer que le thread de lecture n’est exécuté que la moitié du temps (grosso merdo) via ceci :

    Nom : P1230604.JPG
Affichages : 226
Taille : 234,2 Ko

    On visualise le chargement des 16 bit :
    - en bas, l'entrée PL qui permet de charger les 16 bit dans le registre,
    - puis en haut les 16 fronts d'horloge pour lire les 16 bit (du dernier vers le 1er)

    Nom : P1230607.JPG
Affichages : 222
Taille : 231,6 Ko

    Ici, en augmentant l’échelle de temps, on voie que l’opération est répétée plusieurs fois d’affilée, c’est joli…

    Si on regarde de façon bien plus large en augmentant l’échelle de temps, on remarque ceci :

    Nom : P1230611.JPG
Affichages : 224
Taille : 245,1 Ko

    On retrouve bien nos fronts sur PL et CLK tout du long, mais avec un gap d’environ 3.5ms de temps a autres ce qui n’est pas acceptable (l’écran d’oscillo arrête pas de sauter, j’ai fait de mon mieux pour vous faire une belle image)

    J’ai donc fait mes petites investigations… Il se trouve que si j’arrête l’exécution du thread envoyant les données sur le robot, il n’y a plus ces interruptions de lecture des signaux… J’imagine facilement que l’exécution de ce thread d’écriture perturbe l’exécution du thread de lecture.

    Je n’ai aucune idée de ce qui pourrait arranger les choses, j’ai essayé de « vider » le thread en mettant tout le programme en commentaire, rien n’y fait…
    Vous trouverez ci-joint mon code (d’ailleurs, si je peux me passer de ces déclarations de variable globales à la chaine, ça m’arrangerai 😉 )

    Les parties vous intéressant sont les classes « writing » (L. 173) et « Reading »(L.221).

    Modifiez l'extension du fichier ".txt" en ".py" pour pouvoir le lire ;)
    4 Legs - Full Threading V01.1.txt

    Comme vous le constaterez, ces codes sont relativement basiques et je les veux le plus court possible pour des raisons de performances.

    Quelques idées de ce qui pourrait poser problème ?

    Merci d’avance 😉

  2. #2
    Membre à l'essai
    Homme Profil pro
    Vivre
    Inscrit en
    Mai 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Vivre

    Informations forums :
    Inscription : Mai 2018
    Messages : 4
    Par défaut
    J'ai changé ce soir les déclarations de variables globales pour des listes globales et un accès direct aux données des listes plutôt que les variable seules.
    C'est beaucoup plus clair, mais je ne peu pas donner de joli petit noms a chaque variable :-/

    J'ai aussi ajouté un "time.sleep(0.05) dans le thread d'envoi des données, pour donner du temps au système pour respirer, ca semble grandement améliorer les choses, je vais continuer de travailler dans cette direction

    En revanche, je ne peut pas ajouter de "time.sleep" dans le thread de lecture des données car même un "time.sleep(0)" dure une bonne demie milliseconde (je dis ça de tête, mon oscilloscope a complétement grillé alors que j 'écrivais ce message :'( ) et non 0 secondes comme demandé.
    Au même titre, les print() créent des interruptions de 5ms :-/ (j'ai donc créé un thread d'affichage pour gérer ça ;p )

    Les données que je veux capter changent quand même assez fréquemment due aux capteurs de vitesse (système d'optocoupleurs avec roue codeuse), j'ai donc besoin d'un maximum de performances au niveau de la lecture.

    Voici la dernière version quasiment fonctionnelle du programme :
    Quasiment car la lecture de vitesse des moteurs n'est pas stable pour l'instant...

    4 Legs - Full Threading V01.3.txt

    Les 2 threads sont maintenant a la ligne 124 et 156

    Work in progress

    zepeu

Discussions similaires

  1. Threads. Peut-on appeler la méthode d'un thread depuis un autre thread ?
    Par Pierre8r dans le forum Concurrence et multi-thread
    Réponses: 4
    Dernier message: 05/12/2008, 11h48
  2. Réponses: 3
    Dernier message: 19/03/2008, 09h38
  3. thread dans un autre thread
    Par lolo le belge dans le forum MFC
    Réponses: 2
    Dernier message: 13/01/2008, 20h57
  4. [Thread] Reveiller un thread a partir d'un autre thread d'une autre classe
    Par arnolpourri dans le forum Concurrence et multi-thread
    Réponses: 18
    Dernier message: 11/04/2007, 15h18
  5. [Thread]thread principal et autres thread.
    Par david06600 dans le forum Concurrence et multi-thread
    Réponses: 5
    Dernier message: 19/12/2006, 15h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo