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

Python Discussion :

[micropython] problème boucle infinie


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 41
    Par défaut [micropython] problème boucle infinie
    Bonjour,

    Je n'ai pas trouvé de forum consacré à l'utilisation de micropython, mais je n'ai peut être pas bien cherché...
    En vue de la prochaine rentrée scolaire, je me suis lancé dans la programmation de robots avec micropython (mu editor) et, sur les exemples que je lis, je vois beaucoup de programmes basés sur une boucle infinie
    Cela me perturbe car, jusqu'à maintenant, on m'avait toujours appris qu'il ne fallait jamais avoir une boucle dont on ne sort jamais (cas très classique de programme qui plante).

    J'ai essayé d'écrire des petits programmes en utilisant une boucle While qui s'arrête lorsqu'une condition est remplie. En voici un qui permet normalement de suivre une ligne noire jusqu'au premier carrefour rencontré.
    Le robot est piloté par une carte micro:bit. Il possède 2 capteurs de ligne espacés de près de 3 cm qui enjambent une ligne noire de 15 mm de largeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    from microbit import *
    import neopixel
     
    np = neopixel.NeoPixel(pin13, 12)
     
    moteurG = pin0
    moteurD = pin1
    ligneG = pin11
    ligneD = pin5
     
    def allumer(rouge, vert, bleu):
        for numero in range(0, 12):
            np[numero] = (rouge, vert, bleu)
        np.show()
     
    def avancer(vitesse):
        pin12.write_digital(0)      # moteur D marche avant
        pin8.write_digital(0)       # moteur G marche avant
        carrefour = False
        allumer(0, 0, 0)
        while not carrefour:
            gauche = ligneG.read_digital()
            droite = ligneD.read_digital()          # fond noir - blanc
            if ((gauche == 1)and(droite == 0)):     # tourner à gauche
                allumer(0, 50, 0)                   # allumer en vert
                moteurD.write_analog(vitesse)
                moteurG.write_analog(0)
                while ((ligneG.read_digital() == 1) and
                       (ligneD.read_digital() == 0)):
                    pass                            # fond blanc - noir
            elif ((gauche == 0)and(droite == 1)):   # tourner à droite
                allumer(0, 0, 50)                   # allumer en bleu
                moteurD.write_analog(0)
                moteurG.write_analog(vitesse)
                while ((ligneG.read_digital() == 0)and
                       (ligneD.read_digital() == 1)):
                    pass
            elif ((gauche == 0)and(droite == 0)):   # fond blanc - blanc
                allumer(50, 50, 50)                 # allumer en blanc
                moteurD.write_analog(vitesse)       # avancer tout droit
                moteurG.write_analog(vitesse)
                while ((ligneG.read_digital() == 0)and
                       (ligneD.read_digital() == 0)):
                    pass
            else:                                   # fond noir - noir
                carrefour = True
                allumer(0, 0, 0)
        moteurG.write_analog(0)
        moteurD.write_analog(0)
     
     
    avancer(300)
    allumer(50, 0, 50)       # allumer en violet
    Dans ce programme, le robot (Bit:Bot de 4Tronix) n'avance pas. Pourquoi ?
    En fait dès que j'allume le robot (après avoir flashé le programme dans sa mémoire), il reste immobile et les leds s'allument en violet. Autrement dit, il n'effectue pas la procédure "avancer" (ou il en sort immédiatement)

    J'ai essayé d'ajouter une instruction break, mais rien n'y fait. Je cherche depuis plus d'une semaine en vain. Merci de m'aider ou de me donner une piste.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par patrice rabiller Voir le message
    J'ai essayé d'ajouter une instruction break, mais rien n'y fait. Je cherche depuis plus d'une semaine en vain. Merci de m'aider ou de me donner une piste.
    Commencez par vous assurer que votre robot sait avancer "simplement" avant de vouloir lui faire faire des choses plus compliquées.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 41
    Par défaut
    Bien entendu, j'ai commencé par faire avancer mon robot, en avant, en arrière, en le faisant tourner ... J'ai aussi testé les capteurs (sonar, réflecteur de lignes) indépendamment des moteurs pour voir s'ils fonctionnent bien.
    En réalité, je ne démarre pas vraiment en programmation (10 ans de basic, 15 ans de turbo pascal et 15 ans de Delphi) mais je suis novice en python et là, quelque chose m'échappe.

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par patrice rabiller Voir le message
    mais je suis novice en python et là, quelque chose m'échappe.
    Votre code, c'est des commandes que vous expédiez à un robot et qu'on ne sait pas ce qu'elles sont supposées faire...
    Pour le reste, vous pouvez utiliser "print" pour afficher les différentes valeurs qui ont testées dans vos conditions/

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 41
    Par défaut
    Il est vrai que mon code n'est pas assez documenté concernant les commandes envoyées au robot. Cependant, j'ai quand même quelques questions concernant les variables booléennes en Python :

    1) Ma variable "carrefour" est une variable booléenne initialisée avec la valeur False. Est-il équivalent de dire
    • While not(carrefour):
    • While not carrefour:
    • While carrefour is False:
    • While (carrefour == False):

    2) Les variables "gauche" et "droite" sont des valeurs binaires (0 ou 1). Elles disent si le réflecteur voit un fond blanc (0) ou un fond noir (1). Peut-on les assimiler à des variables booléennes en écrivant "if (gauche and not(droite)):" au lieu de "if ((gauche == 1) and (droite == 0)):" ?
    3) On peut bien sortir d'une boucle "while not(carrefour)" en assignant, dans la boucle, la valeur True à la variable carrefour n'est-ce pas ? Doit-on utiliser break pour quitter la boucle While lorsque le robot arrive sur un carrefour ? Cela se produit lorsque les 2 capteurs gauche et droite se trouvent sur fond noir.

    Merci de m'avoir lu.

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Vous posez des questions basiques sur Python (micropython devrait être son cousin) pour lesquelles, vous auriez une réponse par vous même en lançant l'interpréteur Python et en tapant quelques instructions.
    C'est pas compliqué d'écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> v = False
    >>> while not(v):
    ...     v = not v
    ...     print('done?')
    ...
    done?
    >>>
    pour vérifier que...

    Cela se produit lorsque les 2 capteurs gauche et droite se trouvent sur fond noir.
    Il n'est pas si compliqué d'ajouter des "print" à votre code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        while not carrefour:
            gauche = ligneG.read_digital()
            droite = ligneD.read_digital()          # fond noir - blanc
            print (carrefour, gauche, droite)
            ... 
            else:   
                print ('noir/noir')                                # fond noir - noir
                carrefour = True
                allumer(0, 0, 0)
    pour visualiser ce qu'il se passe.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    j'y vais de ma petite contrib :

    Citation Envoyé par patrice rabiller Voir le message
    (...) sur les exemples que je lis, je vois beaucoup de programmes basés sur une boucle infinie
    Cela me perturbe car, jusqu'à maintenant, on m'avait toujours appris qu'il ne fallait jamais avoir une boucle dont on ne sort jamais (cas très classique de programme qui plante).
    un programme pris dans une boucle infinie ne plante pas, il s'exécute indéfiniment à moins qu'on le cut avec un signal ou qu'à l'intérieur de la boucle les opérations exécutées mènent à planter le programme (allocation mémoire/descripteurs/etc. par exemple)

    c'est très sain une boucle while True:, on peut gérer plus finement le flux d’exécution avec des mots-clés comme break ou continue, dans beaucoup de langages on trouve une tournue do {...} while (repeat ... until en Pascal) permettant d'exécuter une première fois le bloc avant d'évaluer la condition, en Python la seule façon de tourner proprement le code dans ce sens c'est de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while True:
       # traitements
       # ...
       if condition:
          break

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 41
    Par défaut
    Oui, je suis d'accord avec toi, BufferBob : les boucles infinies de type while True: sont bien pratiques.
    Cependant, je fais partie de la vieille génération qui a appris le précepte de finitude de Donald Knuth : "Un algorithme doit toujours se terminer après un nombre fini d'étapes".
    Donc, dans la mesure du possible, par principe, j'essaierai d'avoir toujours une instruction break permettant de sortir à coup sûr d'une boucle while True: Cette condition de sortie pourra être une durée à ne pas dépasser, une variable qui prend une valeur particulière et dont on est sûr qu'elle finira par se produire.

    @Jérôme Briot :
    Nos derniers messages ont dû se croiser et j'ai fait un programme analogue à celui que tu proposes.
    Ce matin, je vais approfondir la piste des lectures "aberrantes" qui pourraient se produire au niveau des capteurs. Si mon idée est juste, alors je pourrai résoudre mon problème ...

    Merci à tous. Je vous tiendrai informés si je trouve une solution.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 41
    Par défaut Boucle infinie : résolu partiellement
    J'ai trouvé un début de réponse.

    En faisant des tests de lecture des capteurs de ligne, j'ai constaté qu'au-dessous de 3000 lectures, il y avait 100% d'erreurs ! Mais si j'augmentais le nombre de lectures (4000 puis 5000 jusqu'à 10000) le nombre de lectures aberrantes diminuait progressivement (on tombe encore à 10% à 15% de mauvaises lectures lorsqu'on fait 10000 lectures). En réalité, ces erreurs étaient toujours obtenues lorsque les capteurs étaient sur un fond blanc. Sur un fond noir les données lues ne comportaient aucune erreur.
    J'en ai conclu que les erreurs de lecture se produisaient essentiellement au début de l'expérience, comme si les capteurs avaient besoin d'un temps de chauffe avant de fonctionner correctement.
    J'ai donc ajouté une instruction sleep avant de faire mes comptages.
    Bingo ! Il faut, au moins 2 secondes de latence au démarrage avant que les capteurs soient opérationnels.

    Maintenant, je sais pourquoi ma boucle "while not carrefour:" s'arrêtait tout de suite : au démarrage, les capteurs ne sont pas prêts et ils retournent systématiquement la valeur 1 (noir) même si on est sur fond blanc.

    J'espère pouvoir vous confirmer qu'on peut ainsi se passer d'une boucle "while True" dans mon programme.

  10. #10
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 196
    Billets dans le blog
    47
    Par défaut
    Bonjour,

    Citation Envoyé par patrice rabiller Voir le message
    J'espère pouvoir vous confirmer qu'on peut ainsi se passer d'une boucle "while True" dans mon programme.
    Un microcontrôleur ne fonctionne pas comme un "PC de bureau". Il n'exécute qu'un seul programme très spécialisé, il n'y a pas de système d'exploitation à qui "rendre la main" lorsque son programme se termine. Tant qu'il est allumé, on a donc intérêt à le conserver dans un état connu, celui qu'on a programmé

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 41
    Par défaut
    Voila : j'ai pu finir de développer ma routine. Il s'agissait de suivre une ligne noire jusqu'au prochain carrefour.
    Au départ, le robot enjambe une ligne noire. Les capteurs sont de part et d'autre de la ligne. Ils voient donc blanc/blanc.
    Si l'un des capteurs voit noir, (à gauche ou à droite) alors le robot tourne légèrement (à droite ou à gauche)
    Si les 2 capteurs voient noir, alors le robot est arrivé au carrefour et il s'arrête.
    Il est impossible de réaliser cette opération avec la boucle While ... True.
    Ce problème est très classique mais très mal documenté : il n'est mentionné nulle part que les capteurs ont besoin de 2 secondes pour être opérationnels.

    Une première routine pour faire bouger le robot en précisant les vitesses des roues à gauche et à droite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    def moteur(vGauche, vDroite):
        # Permet d'avancer ou de reculer avec des vitesses entre -100 et 100
        # Les vitesses positives font avancer, les négatives font reculer
     
        directG.write_digital(0)    # marche avant à gauche par défaut
        directD.write_digital(0)    # marche avant à droite par défaut
        if vGauche < 0:
            directG.write_digital(1)                # marche arrière à gauche
            moteurG.write_analog(1023 + 10.23 * vGauche)
        else:
            moteurG.write_analog(10.23 * vGauche)   # marche avant à gauche
        if vDroite < 0:
            directD.write_digital(1)                # marche arrière à droite
            moteurD.write_analog(1023 + 10.23 * vDroite)
        else:
            moteurD.write_analog(10.23 * vDroite)   # marche avant à droite
    Une seconde routine pour aller jusqu'au prochain carrefour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    def allerAuCarrefour(vitesse):
        carrefour = False
        allumer(0, 0, 0)
        while not(carrefour):
            gauche = ligneG.read_digital()
            droite = ligneD.read_digital()
            if (gauche and droite):                 # fond noir/noir
                carrefour = True
                allumer(0, 0, 0)
            elif (gauche and not droite):           # fond noir/blanc
                moteur(0, vitesse)                  # tourner à gauche
                allumer(0, 50, 0)                   # allumer en vert
                while (ligneG.read_digital() and
                       not ligneD.read_digital()):  # tant que noir/blanc
                    pass
            elif (not gauche and droite):           # fond blanc/noir
                moteur(vitesse, 0)                  # tourner à droite
                allumer(0, 0, 50)                   # allumer en bleu
                while (not ligneG.read_digital() and
                       ligneD.read_digital()):      # tant que blanc/noir
                    pass
            else:                                   # fond blanc/blanc
                moteur(vitesse, vitesse)            # tout droit
                allumer(50, 50, 50)                 # allumer en blanc
                while (not ligneG.read_digital() and
                       not ligneD.read_digital()):  # tant que blanc/blanc
                    pass
        moteur(0, 0)
    Évidemment, le programme principal, avant d'appeler la procédure "allerAuCarrefour", impose un délai d'attente de 2 secondes.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème boucle infinie bloquer comment bloquer outlook
    Par traersa dans le forum VBA Outlook
    Réponses: 2
    Dernier message: 09/03/2018, 11h03
  2. Problème boucle infinie
    Par Hafa10 dans le forum Langage
    Réponses: 9
    Dernier message: 16/05/2015, 19h01
  3. [XL-2007] Problème boucle infinie
    Par s.byczek dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 08/02/2012, 14h49
  4. [XL-2010] Problème boucle infini
    Par Zaelos dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 24/01/2012, 10h49
  5. problème boucle infinie
    Par hanou88 dans le forum C
    Réponses: 7
    Dernier message: 05/11/2010, 01h15

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