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

Arduino Discussion :

Problème de script python pour piloter un arduino


Sujet :

Arduino

  1. #1
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut Problème de script python pour piloter un arduino
    Bonjour à tous !

    Je suis débutant dans le monde de l’Arduino et de la programmation. J’ai comme objectif de réaliser un bras robotisé constitué de trois servo pour mettre en place ou retirer un couvercle de télescope afin d’automatiser les prises de vues nocturne.
    A l’aide de mBlock et divers morceaux de programme glanés sur le net, j’ai réussi à écrire une petite application fonctionnelle pour l’arduino qui me permet de piloter la fonction d’ouverture et fermeture en local à l’aide de deux boutons poussoir ou par l’intermédiaire de commandes envoyées sur le port série via la prise usb.
    Voici le programme Arduino:

    Code arduino : 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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
     
    #include <Arduino.h>
    #include <Servo.h>
     
     
    Servo ServoCapot;
    Servo ServoRotation;
    Servo ServoTranslation;
    const int boutonfermeture2 = 2;
    const int boutonouverture3 = 3;
    String commande;
    int AngleServoCapot;
    int AngleServoRotation;
    int AngleServoTranslation;
    int reception;
     
     
     
     
    void setup()
    {
        Serial.begin(115200);
        Serial.flush();
        ServoCapot.attach(10, 500, 2475); // init pin
        ServoRotation.attach(9, 500, 2475); // init pin
        ServoTranslation.attach(8, 500, 2475); // init pin
        pinMode(boutonfermeture2,INPUT);
        pinMode(boutonouverture3,INPUT);
        ServoCapot.write(0); // write to servo
        ServoRotation.write(137); // write to servo
        ServoTranslation.write(47); // write to servo
        AngleServoCapot = 0;
        AngleServoRotation = 137;
        AngleServoTranslation = 47;
     
    }
     
     
    void loop() 
    {             // put your main code here, to run repeatedly:
     
       while (Serial.available() > 0)
      {
        reception = Serial.read();
        commande += char(reception);
        delay(5);
      }
     
      if (commande != "")
      {
        traitementserial(); // Appel de la fonction
      }
       if(digitalRead(2) == HIGH)
        {
           fermeture(); // Appel de la fonction
        }
        if(digitalRead(3) == HIGH)
        {
           ouverture(); // Appel de la fonction
        }
    }
     
    // Fonctions
     
    void ouverture() // Fonction de traitement de l'ouverture
    { 
            while(!(((AngleServoTranslation)==(137))))
            {
                _loop();
                ServoTranslation.write((AngleServoTranslation) + (1)); // write to servo
                AngleServoTranslation += 1;
                _delay(0.02);
            }
            _delay(1);
            while(!(((AngleServoCapot)==(180))))
            {
                _loop();
                ServoCapot.write((AngleServoCapot) + (1)); // write to servo
                AngleServoCapot += 1;
                _delay(0.02);
            }
            _delay(1);
            while(!(((AngleServoRotation)==(47))))
            {
                _loop();
                ServoRotation.write((AngleServoRotation) - (1)); // write to servo
                AngleServoRotation += -1;
                _delay(0.02);
            }
     }
     
     void fermeture() // Fonction de traitement de la fermeture
      { 
       while(!(((AngleServoRotation)==(137))))
            {
                _loop();
                ServoRotation.write((AngleServoRotation) + (1)); // write to servo
                AngleServoRotation += 1;
                _delay(0.02);
            }
            _delay(1);
            while(!(((AngleServoCapot)==(0))))
            {
                _loop();
                ServoCapot.write((AngleServoCapot) - (1)); // write to servo
                AngleServoCapot += -1;
                _delay(0.02);
            }
            _delay(1);
            while(!(((AngleServoTranslation)==(47))))
            {
                _loop();
                ServoTranslation.write((AngleServoTranslation) - (1)); // write to servo
                AngleServoTranslation += -1;
                _delay(0.02);
            }
        }
     
     void traitementserial() // Fonction de traitement de la commande
    {
      if (commande == "ouverture")
      {
        ouverture();
      }
      else if (commande == "fermeture")
      {
        fermeture();
      }
        else
      {
        Serial.print("Commande '" + commande + "' inconnue : ");// Traitement de la commande inconnue.
      }
     
      if ((AngleServoTranslation)==(47))
      {
        Serial.println("Capot fermé");
      }
      if ((AngleServoTranslation)==(137))
      {
        Serial.println("Capot ouvert");
      }
        commande = "";
    }
     void _delay(float seconds){
        long endTime = millis() + seconds * 1000;
        while(millis() < endTime)_loop();
    }
     
     void _loop(){
     
    }

    J’ai ensuite adapté un petit programme python que j’ai trouvé sur le très intéressant tutoriel « Piloter Arduino depuis un PC avec Python et Boa Constructor » à l’adresse suivante :
    https://herve-troadec.developpez.com...-boa/#LVII-B-5

    Ce programme me permet d’envoyer les commandes nécessaires à l’Arduino pour ouvrir et fermer le couvercle.
    Voici le programme python:

    Code Python version 1 : 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
     
    #!/usr/bin/python
    # coding: utf8
     
    import serial
    import time
     
    print("Initialisation du port")
    portCom = serial.Serial()
    portCom.port = "/dev/cu.usbserial-1420"
    portCom.baudrate = 115200
     
    print("Ouverture du port...")
    try:
      portCom.open()
    except serial.SerialException:
      print("Un problème s'est produit à l'ouverture du port.\n"
        "Vérifiez que le port utilisé par la carte Arduino est\n"
        "bien '/dev/cu.usbserial-1420'. Si ce n'est pas le cas, modifiez\n"
          "le script Python en conséquence.")
      saisie = ""
      while saisie != "q":
          saisie = str(raw_input("Entrer 'q' pour quitter: "))
     
    while portCom.is_open:
      commande = str(raw_input("Saisir une commande ('q' pour quitter): "))
      if commande != "q":
        portCom.write(commande)    
        time.sleep(10)
        nbCar = portCom.in_waiting
        retour = portCom.read(nbCar)
        print(retour)
        portCom.reset_input_buffer()
      else:
        portCom.close()

    Mais mes connaissances en programmation ne me permettent pas de modifier ce programme comme j’aimerais qu’il soit.
    En fait, j’aimerais le simplifier au maximum. L’idée est de garder la possibilité de le quitter si il rencontre des difficultés à se connecter au port série de l’arduino mais j’aimerais ne pas avoir à écrire la commande d’ouverture ou de fermeture. Je voudrais avoir deux scripts, un pour l’ouverture et un autre pour la fermeture. Ces scripts envoient juste la commande à l’arduino, vérifient que la commande a bien été envoyée et si oui, il quitte ou si non, un message « erreur » s’écrit.
    J’ai essayé ceci mais cela ne marche pas bien. Le programme s’arrête comme si la condition « if retour == "Capot ouvert »: » ne fonctionnait pas
    Voici le programme python modifié:

    Code python version 2 : 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
     
    #!/usr/bin/python
    # coding: utf8
     
    import serial
    import time
     
    print("Initialisation du port")
    portCom = serial.Serial()
    portCom.port = "/dev/cu.usbserial-1420"
    portCom.baudrate = 115200
     
    commande = "ouverture"
     
    print("Ouverture du port...")
    try:
      portCom.open()
    except serial.SerialException:
      print("Un problème s'est produit à l'ouverture du port.\n"
        "Vérifiez que le port utilisé par la carte Arduino est\n"
        "bien '/dev/cu.usbserial-1420'. Si ce n'est pas le cas, modifiez\n"
          "le script Python en conséquence.")
      saisie = ""
      while saisie != "q":
          saisie = str(raw_input("Entrer 'q' pour quitter: "))
     
    while portCom.is_open:
        portCom.write(commande)    
        time.sleep(10)
        nbCar = portCom.in_waiting
        retour = portCom.read(nbCar)
        if retour == "Capot ouvert":
            print(retour)
            portCom.reset_input_buffer()
            portCom.close()
        else:
            print("erreur")
            portCom.close()

    Si certains d’entre vous peuvent m’aiguiller, ce serait super cool !

    L’idée, au finale, est de faire deux scripts exécutables à l’aide de py2app.

    Merci par avance…

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Tu met ton print(retour) à l'intérieur de la condition donc, si elle n'est pas vraie, tu ne peux pas savoir pourquoi.

  3. #3
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Salut,

    Tu met ton print(retour) à l'intérieur de la condition donc, si elle n'est pas vraie, tu ne peux pas savoir pourquoi.
    Oui, effectivement. Je l'ai donc placé avant la condition et je l'ai mis aussi comme message d'erreur.
    mais rien ne s'écrit, donc la commande venant de l'arduino n'est pas lu. Pourquoi, alors que le script précédant fonctionne très bien avec la même fonction de lecture du port série.
    Comme ci la boucle "while portCom.is_open:" fonctionnait mal.

    Bon, en même temps, je suis vraiment nul en programmation.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 276
    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 276
    Points : 36 761
    Points
    36 761
    Par défaut
    Salut,

    Citation Envoyé par astrofab Voir le message
    Comme ci la boucle "while portCom.is_open:" fonctionnait mal.
    La boucle ne sert à rien: quelque soit le cas, vous faites un port.close()...

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

  5. #5
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Citation Envoyé par astrofab Voir le message
    Oui, effectivement. Je l'ai donc placé avant la condition
    Non, tu l'as placé dans la condition, donc inutile et dans le else tu print simplement "erreur".

    Pas plus utile ça.

  6. #6
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,



    La boucle ne sert à rien: quelque soit le cas, vous faites un port.close()...

    - W
    Oui, mais dans un cas, ça devarit me dit que la fonction a bien été exécutée, dans l'autre je devrais avoir un message d'erreur. Or, rien ne s'écrit.
    Apres, oui, dans les deux cas le programme quitte. C'est voulu.

  7. #7
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Non, tu l'as placé dans la condition, donc inutile et dans le else tu print simplement "erreur".

    Pas plus utile ça.
    Quand j'écris "je l'ai donc placé" je voulais dire que j'ai essayé de le mettre avant et à la place du message d'erreur pour être sur de voir ce qui arrive de l'arduino.
    Comme rien ne s'écrit, j'en déduit que le programme n'arrive pas à lire la commande venant de l'arduino.
    Pourtant, il y arrive très bien avec le programme python version 1

    C'est pour cette raison que je demande de l'aide parce que je ne vois pas pourquoi.

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


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

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12 596
    Points : 56 689
    Points
    56 689
    Billets dans le blog
    40
    Par défaut
    Salut,

    Essaie en rajoutant un time.sleep(3) juste après l'ouverture du port COM. Explications ici.

  9. #9
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par f-leb Voir le message
    Salut,

    Essaie en rajoutant un time.sleep(3) juste après l'ouverture du port COM. Explications ici.
    Merci f-leb !

    Effectivement, c'est un détail important.
    Grace à cette astuce, j'ai pu faire un petit programme python fonctionnel.

    Code Ouverture simple.py : 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
     
    #!/usr/bin/python
    # coding: utf8
     
    import serial
    import time
    import sys
     
    portCom = serial.Serial()
    portCom.port = "/dev/cu.usbserial-1420" # nom du port serie utilisé par l'arduino
    portCom.baudrate = 115200
     
    portCom.open()  # ouverture du port série
    time.sleep(3) # Delais pour l'ouverture du port
     
    portCom.write("ouverture") # envoie de la commande 'ouverture' à l'arduino
    print("ouverture")
    time.sleep(10) # Delais pour que les servos aient le temps d'aller au bout de leur course.
     
    nbCar = portCom.in_waiting # lecture du port serie du retour d'information de l'arduino
    retour = portCom.read(nbCar) # 'retour' étant la variable enregistrant cette information
    print(retour) # affichage du contenu de cette variable
     
    portCom.close()

    Cependant, il me reste un petit problème avec la version du programme plus sophistiqué qui vérifie si le port série de l'arduino est le bon, que la commande effectuée soit la bonne ou si non afficher "erreur". A chaque fois, je reçois le message "erreur" alors que la commande reçu "Capot ouvert" est bonne.
    J'ai un problème dans la boucle ou avec la condition "if" et "else" mais je n'arrive pas à le régler.

    Code test-serial-2ter.py : 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
     
    #!/usr/bin/python
    # coding: utf8
     
    import serial
    import time
     
    print("Initialisation du port")
    portCom = serial.Serial()
    portCom.port = "/dev/cu.usbserial-1420" # nom du port serie utilisé par l'arduino
    portCom.baudrate = 115200
     
    commande = "ouverture"
     
    print("Ouverture du port...") # Affiche que le programme essaie d'ouvrir le port
    try:
        portCom.open()                  # Ouverture du port
        time.sleep(3)                   # Delais d'attente de l'ouverture du port
    except serial.SerialException:      # Si j'ai bien compris: si le port ne s'ouvre pas, alors "print"
        print("Un problème s'est produit à l'ouverture du port.\n"
        "Vérifiez que le port utilisé par la carte Arduino est\n"
        "bien '/dev/cu.usbserial-1420'. Si ce n'est pas le cas, modifiez\n"
        "le script Python en conséquence.\n"
        "Entrer 'q' pour quitter: ")
        saisie = ""
        if saisie == "q":               # Si l'entrée = 'q' alors:
          portCom.close()               # quitter
     
    while portCom.is_open:              # tant que le port serie est ouvert :
        portCom.write(commande)         # Envoyer commande (ouverture)
        print(commande)                 # afficher la commande (ouverture)
        time.sleep(10)                  # Délais d'attente pour que les trois servo aillent à leur position
        nbCar = portCom.in_waiting      # Attend un retour d'information de l'arduino et l'enregistre dans(nbCar)
        retour = portCom.read(nbCar)    # Enregistre le retour d'information de l'arduino dans la variable (retour)
        time.sleep(3)                   # Delais
        print(retour)                   # afficher le retour d'information de l'arduino (Capot ouvert) pour vérifier qu'on a bien reçu l'information
        if retour == "Capot ouvert":    # Si retour = 'Capot ouvert' alors
            print(retour)               # Afficher la réponse de l'arduino
            portCom.close()             # Quitter
        else:                           # Si la réponse de l'arduino n'est pas = a 'Capot ouvert' alors:
            print("erreur")             # Afficher erreur
            portCom.close()             # Quitter

    Nom : Capture d’écran 2019-04-19 à 13.56.54.png
Affichages : 323
Taille : 40,2 Ko

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 276
    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 276
    Points : 36 761
    Points
    36 761
    Par défaut
    Citation Envoyé par astrofab Voir le message
    A chaque fois, je reçois le message "erreur" alors que la commande reçu "Capot ouvert" est bonne.
    J'ai un problème dans la boucle ou avec la condition "if" et "else" mais je n'arrive pas à le régler.
    Je vous ai déjà dit que votre if...else... faisait toujours un port.close.
    Ce qui rend la boucle while portCom.is_open inutile... sauf qu'entre le moment où s'exécute le .close et celui ou .is_open devient False, il y a un petit délai... qui vous fout dedans.

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

  11. #11
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Essaye ceci if retour == "Capot ouvert\n"

  12. #12
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Je vous ai déjà dit que votre if...else... faisait toujours un port.close.
    Ce qui rend la boucle while portCom.is_open inutile... sauf qu'entre le moment où s'exécute le .close et celui ou .is_open devient False, il y a un petit délai... qui vous fout dedans.

    - W
    Oui, j'ai bien compris mais comment puis-je rendre cette boucle utile. De toute les façons, à la fin des conditions le programme doit s'arrêter.
    Soit le retour de l'arduino est = (Capot ouvert) alors on affiche (Capot ouvert) puis on quitte.
    Soit le retour de l'arduino est différent de (Capot ouvert) alors on affiche (erreur) puis on quitte

    Or mon programme fait les deux. Comment puis-je rendre cette condition fonctionnelle ?

    Merci d'avance

  13. #13
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Essaye ceci if retour == "Capot ouvert\n"
    Merci ! Mais cela ne marche pas mieux.

  14. #14
    Rédacteur

    Avatar de naute
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2009
    Messages
    708
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2009
    Messages : 708
    Points : 2 924
    Points
    2 924
    Par défaut
    Bonjour à tous .

    Citation Envoyé par f-leb Voir le message
    Essaie en rajoutant un time.sleep(3) juste après l'ouverture du port COM.
    Chez moi, sleep(2) suffit mais pas sleep(1).

    @astrofab

    Je te propose les deux petits scripts qui suivent :
    ouverture.py
    Code python : 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
     
    #!/usr/bin/python
    # coding: utf8
     
    import serial
    import time
     
    print("Initialisation du port")
    portCom = serial.Serial()
    portCom.port = "/dev/ttyUSB0"
    portCom.baudrate = 115200
     
    print("Ouverture du port...")
    try:
      portCom.open()
    except serial.SerialException:
      print("Un problème s'est produit à l'ouverture du port.\n"
        "Vérifiez que le port utilisé par la carte Arduino est\n"
        "bien '/dev/cu.usbserial-1420'. Si ce n'est pas le cas, modifiez\n"
          "le script Python en conséquence.")
      saisie = ""
      while saisie != "q":
          saisie = str(raw_input("Entrer 'q' pour quitter: "))
    if portCom.is_open: 
    	time.sleep(2)
    	portCom.write("ouverture")
    	print("Commande <ouverture> envoyée : processus (10 secondes) en cours...")
    	time.sleep(10)
    	nbCar = portCom.in_waiting
    	retour = portCom.read(nbCar)
    	print(retour)
    	time.sleep(3)
    	portCom.close()
    et fermeture.py
    Code python : 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
     
    #!/usr/bin/python
    # coding: utf8
     
    import serial
    import time
     
    print("Initialisation du port")
    portCom = serial.Serial()
    portCom.port = "/dev/ttyUSB0"
    portCom.baudrate = 115200
     
    print("Ouverture du port...")
    try:
      portCom.open()
    except serial.SerialException:
      print("Un problème s'est produit à l'ouverture du port.\n"
        "Vérifiez que le port utilisé par la carte Arduino est\n"
        "bien '/dev/cu.usbserial-1420'. Si ce n'est pas le cas, modifiez\n"
          "le script Python en conséquence.")
      saisie = ""
      while saisie != "q":
          saisie = str(raw_input("Entrer 'q' pour quitter: "))
    if portCom.is_open: 
    	time.sleep(2)
    	portCom.write("fermeture")
    	print("Commande <fermeture> envoyée : processus (10 secondes) en cours...")
    	time.sleep(10)
    	nbCar = portCom.in_waiting
    	retour = portCom.read(nbCar)
    	print(retour)
    	time.sleep(3)
    	portCom.close()
    et quelques modifications mineures de ton sketch Arduino :
    Code arduino : 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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
     
    //********** MODIF **************** 
    //#include <Arduino.h>
    //****** FIN MODIF ***************
     
    #include <Servo.h>
     
     
    Servo ServoCapot;
    Servo ServoRotation;
    Servo ServoTranslation;
    const int boutonfermeture2 = 2;
    const int boutonouverture3 = 3;
    String commande;
    //********** MODIF ****************
    //int AngleServoCapot;
    //int AngleServoRotation;
    //int AngleServoTranslation;
    int AngleServoCapot = 0;
    int AngleServoRotation = 137;
    int AngleServoTranslation = 47;
    //****** FIN MODIF ***************
    int reception;
     
     
     
     
    void setup()
    {
        Serial.begin(115200);
        Serial.flush();
        ServoCapot.attach(10, 500, 2475); // init pin
        ServoRotation.attach(9, 500, 2475); // init pin
        ServoTranslation.attach(8, 500, 2475); // init pin
        pinMode(boutonfermeture2,INPUT);
        pinMode(boutonouverture3,INPUT);
     
    //********** MODIF ****************    
    //    ServoCapot.write(0); // write to servo
    //    ServoRotation.write(137); // write to servo
    //    ServoTranslation.write(47); // write to servo
    //    AngleServoCapot = 0;
    //    AngleServoRotation = 137;
    //    AngleServoTranslation = 47;
        ServoCapot.write(AngleServoCapot);
        ServoRotation.write(AngleServoRotation);
        ServoTranslation.write(AngleServoTranslation);
    //****** FIN MODIF ***************
     
    }
     
     
    void loop() 
    {           
     
       while (Serial.available() > 0)
      {
        reception = Serial.read();
        commande += char(reception);
        delay(5);
      }
     
      if (commande != "")
      {
        traitementserial();
      }
       if(digitalRead(2) == HIGH)
        {
           fermeture(); 
        }
        if(digitalRead(3) == HIGH)
        {
           ouverture(); 
        }
    }
     
     
     
    void ouverture() 
    { 
            while(!(((AngleServoTranslation)==(137))))
            {
                //********** MODIF ****************
                //_loop();
                //****** FIN MODIF ***************
                ServoTranslation.write((AngleServoTranslation) + (1)); 
                AngleServoTranslation += 1;
                //********** MODIF ****************
                delay(20);//_delay(0.02);
                //****** FIN MODIF ***************
            }
            //********** MODIF ****************
            delay(1000);//_delay(1);
            //****** FIN MODIF ***************
            while(!(((AngleServoCapot)==(180))))
            {
                //********** MODIF ****************
                //_loop();
                //****** FIN MODIF ***************
                ServoCapot.write((AngleServoCapot) + (1)); 
                AngleServoCapot += 1;
                //********** MODIF ****************
                delay(20);//_delay(0.02);
                //****** FIN MODIF ***************
            }
            //********** MODIF ****************
            delay(1000);//_delay(1);
            //****** FIN MODIF ***************
            while(!(((AngleServoRotation)==(47))))
            {
                //********** MODIF ****************
                // _loop();
                //****** FIN MODIF ***************
                ServoRotation.write((AngleServoRotation) - (1)); 
                AngleServoRotation += -1;
                //********** MODIF ****************
                delay(20);//_delay(0.02);
                //****** FIN MODIF ***************
            }
     }
     
     void fermeture() 
      { 
       while(!(((AngleServoRotation)==(137))))
            {
                //********** MODIF ****************
                // _loop();
                //****** FIN MODIF ***************
                ServoRotation.write((AngleServoRotation) + (1)); 
                AngleServoRotation += 1;
                //********** MODIF ****************
                 delay(20);// _delay(0.02);
                //****** FIN MODIF ***************
            }
            //********** MODIF ****************
            delay(1000);//_delay(1);
            //****** FIN MODIF ***************
            while(!(((AngleServoCapot)==(0))))
            {
                //********** MODIF ****************
                // _loop();
                //****** FIN MODIF ***************
                ServoCapot.write((AngleServoCapot) - (1));
                AngleServoCapot += -1;
                //********** MODIF ****************
                delay(20);// _delay(0.02);
                //****** FIN MODIF ***************
            }
            //********** MODIF ****************
            delay(1000);//_delay(1);
            //****** FIN MODIF ***************
            while(!(((AngleServoTranslation)==(47))))
            {
                //********** MODIF ****************
                // _loop();
                //****** FIN MODIF ***************
                ServoTranslation.write((AngleServoTranslation) - (1));
                AngleServoTranslation += -1;
                //********** MODIF ****************
                delay(20);// _delay(0.02);
                //****** FIN MODIF ***************
            }
        }
     
     void traitementserial()
    {
      if (commande == "ouverture")
      {
        ouverture();
      }
      else if (commande == "fermeture")
      {
        fermeture();
      }
    //********** MODIF ****************
    //    else
    //  {
    //    Serial.print("Commande '" + commande + "' inconnue : ");
    //  }
    //****** FIN MODIF ***************
     
      if ((AngleServoTranslation)==(47))
      {
        Serial.println("Capot fermé");
      }
      if ((AngleServoTranslation)==(137))
      {
        Serial.println("Capot ouvert");
      }
        commande = "";
    }
    //********** MODIF ****************
    // void _delay(float seconds){
    //    long endTime = millis() + seconds * 1000;
    //    while(millis() < endTime)_loop();
    //}
    // 
    // void _loop(){
    // 
    //}
    //****** FIN MODIF ***************
    dans lequel j'ai supprimé quelques lignes inutiles, et remplacé les procédures locales _delay() et _loop() par la procédure Arduino delay() qui fait la même chose (bloquantes toutes les deux), mis à part les unités et le type utilisés comme paramètre. J'ai mis en commentaire les lignes à supprimer et délimité chaque modification pour qu'elle soit facile à repérer. Cela dit, ton sketch fonctionne sans problème .

    Mais tu vas avoir un problème insoluble par voie logiciel : le reset systématique de la carte à chaque nouvelle connexion. Ce reset est destiné à faciliter le téléversement des sketchs mais entraîne ce type de désagrément. Si tu lances le script d'ouverture, le travail va se faire correctement, et la fermeture de la console suivra l'accusé réception. Par contre, quand tu vas lancer le script de fermeture, qui est un copier/coller de l'autre avec modification des paramètres ad hoc, comme la carte va effectuer un reset, tes servos vont retourner à la position d'origine avant même d'en avoir reçu l'ordre. On pourrait dire que le résultat est le même, mais pas tout à fait : la position finale sera la même mais la vitesse de déplacement, non, et cela risque de poser un problème mécanique.
    Une solution est celle indiquée ICI par f-leb. Une autre, si tu bricoles, consiste à te faire ta propre carte contrôleur, qui n'a besoin, en plus de l'ATmega328P, que d'une alimentation 5 V, un quartz et deux condensateurs. C'est très simple à faire sur une platine de prototypage. Tu utiliseras ta carte UNO pour programmer le micro-contrôleur et tester le sketch, puis tu n'auras plus qu'à transférer le circuit intégré sur ton montage.
    Si tu utilises des servos puissants, tu auras peut-être intérêt à les alimenter à part, la platine Arduino UNO étant limitée en courant.

    Amicalement,
    naute

  15. #15
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 276
    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 276
    Points : 36 761
    Points
    36 761
    Par défaut
    Salut,

    Citation Envoyé par astrofab Voir le message
    Soit le retour de l'arduino est = (Capot ouvert) alors on affiche (Capot ouvert) puis on quitte.
    Soit le retour de l'arduino est différent de (Capot ouvert) alors on affiche (erreur) puis on quitte
    Donc la boucle ne sert à rien.
    Cöté code, vous pouvez reprendre celui d'ouverture simple.py et y ajouter le try...except... autour du portCom.open()

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

  16. #16
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Merci Mister Naute !

    Ca marche super bien !

    Effectivement, j'avais remarqué que le script "fermeture" me ramenait mes servo à leur position d'origine simultanément et en vitesse rapide.
    Ce qui va me poser un problème mécanique parce que l'ordre de la séquence des mouvements est très importante.
    J'avais lu ,grâce au lien de f-leb concernant le délais de lecture du port com, qu'il fallait mettre une résistance de 110 ohms entre le pin reset et le 5v de la carte pour éviter un reset intempestif à chaque utilisation du script.
    Ce qui me rassure, si j'ai bien compris, c'est que si je fait cette manip, mes servo ne reviendront pas automatiquement à leur position d'origine avant la lecture du script et quand j'utiliserais le script "fermeture" les servo utiliseront la séquence du script et uniquement cette séquence pour fermer le capot.

    Plus qu'a trouver une résistance de 110 ohms !

    En tous cas, mille mercis M. Naute pour votre aide !

    Maintenant, la tache difficile va être de transformer ces scripts en applications autonomes pour pouvoir les lancer depuis le bureau ou via une autre application.
    Pour le moment, j'utilise mon Mac pour faire les essais et je compte utiliser py2app pour transformer les scripts mais cela semble une vrai galère
    Si j'y arrive, je ferais la même chose sur linux car ces scripts sont sensés tourner sur cet OS.

    Si l'un d'entre vous à l'expérience de transformer des scripts python en applications exécutables depuis le bureau, je suis preneur

  17. #17
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,



    Donc la boucle ne sert à rien.
    Cöté code, vous pouvez reprendre celui d'ouverture simple.py et y ajouter le try...except... autour du portCom.open()

    - W
    Merci pour votre aide !
    Effectivement, elle ne sert à rien, d'autant plus que je n'aurais pas besoin d'afficher un message d'erreur si je demande à l'arduino de la transmettre via la variable "retour".
    Je vais essayer de modifier le programme arduino pour lui demander de m'envoyer dans "retour" un message d'erreur si les conditions "Capot ouvert" ou "Capot fermé" ne sont pas respectées.

  18. #18
    Rédacteur

    Avatar de naute
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2009
    Messages
    708
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2009
    Messages : 708
    Points : 2 924
    Points
    2 924
    Par défaut
    Citation Envoyé par astrofab Voir le message
    Merci ! Ca marche super bien !
    J'en suis ravi . Et puis, entre astro-amateurs, on peut bien se donner un coup de main.

    Citation Envoyé par astrofab Voir le message
    Effectivement, j'avais remarqué que le script "fermeture" me ramenait mes servo à leur position d'origine simultanément et en vitesse rapide.
    Ce qui va me poser un problème mécanique parce que l'ordre de la séquence des mouvements est très importante.
    Comme je ne connais pas ton montage, je ne peux rien dire quant à l'ordre dans lequel la séquence doit être déroulée, mais il ne faut pas oublier non plus le problème lié à l'inertie des pièces en mouvement, qui peut nuire à ton système de transmission et aux servos eux-mêmes s'ils ne sont pas assez robustes.

    Citation Envoyé par astrofab Voir le message
    si j'ai bien compris, c'est que si je fait cette manip, mes servo ne reviendront pas automatiquement à leur position d'origine
    Absolument : comme aucun reset ne sera généré, la partie "void setup()" sera sautée et la boucle "void loop()" sera directement exécutée. Mais ça ne résous pas l'éventuel problème d'une coupure d'alimentation, quelle que soit son origine, quand ton capot se trouve en position ouverte. À la remise sous tension, manip anti-reset ou pas, le setup sera effectué et la position de tes servos sera réinitialisée . Il faudrait que l'alimentation se fasse au travers d'un relais enclenché par un bouton poussoir et auto alimenté. En cas de coupure de son auto-alimentation, il passera au repos. Quand le courant sera remis, il restera au repos jusqu'à une nouvelle pression sur le bouton poussoir, ce qui te permettra de régler le problème en toute sécurité.

    Citation Envoyé par astrofab Voir le message
    Plus qu'a trouver une résistance de 110 ohms !
    Ça, ce n'est pas le plus difficile .

    Citation Envoyé par astrofab Voir le message
    Maintenant, la tache difficile va être de transformer ces scripts en applications autonomes pour pouvoir les lancer depuis le bureau ou via une autre application.
    Là, je ne comprends pas vraiment la nécessité de cette manipulation. Pour moi, ce n'est utile que pour déployer des applications Python sur des systèmes ne disposant pas de l’interpréteur éponyme ou pour cacher le code. En tout cas, je ne peux pas t'aider à ce niveau car je ne connais pas la marche à suivre, n'en ayant jamais eu besoin. Mais ça m'étonnerait que tu ne trouves pas de l'aide à ce sujet sur le forum. Lance un autre fil pour ça : ce sera plus efficace, d'une part, et rendra la recherche plus facile pour ceux qui seront intéressés par le sujet.

    Amicalement,
    naute

  19. #19
    Candidat au Club
    Homme Profil pro
    artisan
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Points : 4
    Points
    4
    Par défaut
    Bonne idée pour le relais et le bouton poussoir parce que, si la fermeture du capot ne respecte pas la séquence de mouvements, cela risque d'endommager les servo.

    Par ailleurs, j'aimerais modifier le programme arduino afin qu'il m'indique si le capot est bien fermé ou ouvert en fin de séquence.
    Je me suis aperçu que le programme me renvoyait seulement la valeur d'une variable qui est écrite au servo, or cela ne me donne pas vraiment la position exacte du servo.
    Soit je met deux capteur au bout de chaque course qui m'indiqueront que la séquence a bien été exécuté ou j'arrive à lire la position des servo en utilisant la fonction servo.read().
    J'ai essayé mais cela ne semble pas fonctionner. Si je débranche un servo, servo.read() me donne quand même une valeur qui est celle qui lui a été envoyée.
    Je n'ai pas l'impression que servo.read() donne la position mécanique du servo. Donc, il semblerait que la fonction soit inutile dans mon cas.

    Concernant la transformation du script en application, tu as peut être raison, j'en aurais peut être pas l'utilité. J'utilise un couple de soft qui s'appelle Kstar et Ekos qui permettent de piloter un observatoire avec des séquences complètes pour faire de l'astrophoto. Le séquenceur est capable de lancer des scripts et je pensais que ces scripts devais être des applications. Je vais essayer de voir si mes scripts python sont fonctionnels dans Ekos.

    En tous cas, merci pour tous ces conseils.

  20. #20
    Rédacteur

    Avatar de naute
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2009
    Messages
    708
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2009
    Messages : 708
    Points : 2 924
    Points
    2 924
    Par défaut
    Personnellement, je mettrais des capteurs de fin de course. C'est une solution éprouvée en laquelle on peut avoir confiance. Il faut savoir que cela te conduira à modifier le sketch. De plus, quitte à utiliser des capteurs de fin de course pour détecter l'arrivée à une position, pourquoi ne pas l'utiliser directement pour asservir la motorisation ? Est-ce que, dans ce cas, l'utilisation de servos se justifie ? Il y a plein de possibilités .
    Quant à servo.read(), il ne fait que te retourner la dernière valeur de consigne envoyée par servo.write(), à savoir la valeur du rapport cyclique, et il ne faut donc pas compter sur lui pour te donner un renseignement "mécanique" : le servo ne dispose d'aucun dispositif de retour d'information. Cela dit, tu peux toujours coupler un encodeur à chacun de tes servos pour connaître sa position physique exacte, mais ça me semble disproportionné en regard de l'objectif à atteindre. Je le répète : capteurs de fin de course (utilisé ici en tant que détecteur de position). C'est simple, efficace et peu coûteux.

    Tiens-nous au courant de l'avancée de ton projet et des solutions que tu as retenues.

    Amuse-toi bien et bonne fin de soirée .

    Amicalement,
    naute.

Discussions similaires

  1. Problème de script VB pour comparateurs sur plusieurs feuille
    Par Kerberos69 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 12/03/2009, 13h49
  2. Migration sunopsis v4/ODI problème du script jython pour FTP
    Par gusy78 dans le forum ODI (ex-Sunopsis)
    Réponses: 1
    Dernier message: 30/07/2008, 14h21
  3. SUNOPSIS/ODI problème de script Jython pour FTP
    Par bmontandon dans le forum ODI (ex-Sunopsis)
    Réponses: 2
    Dernier message: 01/10/2007, 14h02
  4. [Cherche tuto/cours]Script Python pour Unix
    Par elflamby dans le forum Général Python
    Réponses: 2
    Dernier message: 05/09/2007, 14h38
  5. problème de script php pour revenir à la page précédente
    Par mandyben dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 14/09/2006, 10h12

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