Partage
  • Partager sur Facebook
  • Partager sur Twitter

Communication Arduino vers Python

    6 octobre 2021 à 11:04:23

    Bonjour,
    J'ai codé un code arduino et je veux converser avec un code python mais sur cette communication je suis un débutant car je code beaucoup en python mais pas pour l'arduino. Je veux récupérer les données arduino qui sont envoyées par ma carte électronique. En arduino c'est bien j'ai en sortie mes données qui changent quand j'exécute une action sur ma carte mais en Python je suis perdu. Pouvez-vous m'expliquer s'il vous plaît la méthode pour réaliser cela? Je joins mon code arduino avec ce message.
    #define analogPin_21B  A3  //définit analogPin_21B comme une constante et qui aura comme port analogique A3
    #define analogPin_22B  A2
    #define analogPin_21A  A1
    #define analogPin_22A  A0
    
    #define pin_led  8  //définit pin_led comme une constante et qui aura comme port digital 8
    #define pin_btn1 9
    #define pin_btn2 6
    #define pin_btn3 7
    #define pin_btn4 5
    
    int state = 0;  // définit une varibale entière globale state à 0
    
    void led(int status); // instanciation d'une fonction void led
    
    int button1(); // instanciation d'une fonction int button1
    int button2();
    int button3();
    int button4();
    
    int joy1_x();
    int joy1_y();
    int joy2_x();
    int joy2_y();
    
    #define OFFSET_JOYSTICK 50
    
    #define Pin1_comm1  4
    #define Pin2_comm1  3
    #define Pin3_comm1  2
    #define Pin1_comm2  13
    #define Pin2_comm2  12
    #define Pin3_comm2  11
    
    int commutateur1();
    int commutateur2();
    
    void setup() { // déclaration  d'une fonction void initialisatrice
      // put your setup code here, to run once:
      
      Serial.begin(115200); //définit la communication à 115200 bauds par secondes sur le port série
      pinMode(Pin1_comm1,INPUT_PULLUP); // configuration de la broche Pin1_comm1 comme entrée tirer vers le haut   
      pinMode(Pin2_comm1,INPUT_PULLUP);
      pinMode(Pin3_comm1,INPUT_PULLUP);
      pinMode(Pin1_comm2,INPUT_PULLUP);
      pinMode(Pin2_comm2,INPUT_PULLUP);
      pinMode(Pin3_comm2,INPUT_PULLUP);
      pinMode(pin_btn1,INPUT_PULLUP);
      pinMode(pin_btn2,INPUT_PULLUP);
      pinMode(pin_btn3,INPUT_PULLUP);
      pinMode(pin_btn4,INPUT_PULLUP);
      pinMode(pin_led,OUTPUT); // configuration de la broche pin_led comme sortie   
    
    }
    
    void loop() { // déclaration d'une fonction void sans fin équivalent à un main 
      // put your main code here, to run repeatedly:
       
      if (joy1_x()<512-OFFSET_JOYSTICK || joy1_x()>512+OFFSET_JOYSTICK){  //condition sur la position du joystick 1 sur l'axe x qui doit être inférieur ou plus grande que celle prédéfinit. Pour cela on appelle la fonction joy1_x() 
        Serial.println("Joystick 1 axe x :"); 
        Serial.println(joy1_x()); // affichage des données de positions de joy1_x() sur le port série
        Serial.println(" "); 
      }
      if ( joy1_y()<512-OFFSET_JOYSTICK || joy1_y()>512+OFFSET_JOYSTICK){ 
        Serial.println("Joystick 1 axe y :"); 
        Serial.println(joy1_y());
        Serial.println(" ");
      }
      if (joy2_x()<512-OFFSET_JOYSTICK || joy2_x()>512+OFFSET_JOYSTICK){ 
        Serial.println("Joystick 2 axe x :"); 
        Serial.println(joy2_x());
        Serial.println(" ");
      }
       if (joy2_y()<512-OFFSET_JOYSTICK || joy2_y()>512+OFFSET_JOYSTICK){
        Serial.println("Joystick 2 axe y :"); 
        Serial.println(joy2_y());
        Serial.println(" ");
      }
    
      /*
      switch (state) {  // instruction à choix mutliples pour la vérification de l'état du button1 
        
        case 0 :  led(0); // mise à l'état bas de la led
                  if ( !button1() ){ // en cas d'appui sur le button1 
                    state=1;  // on passe à l'état suivant et donc au case 1
                    delay(500); // mise en place d'une attente de 500 ms
                  }
                  else {
                    state= 0; 
                  }
                  break; // sortie de la première instruction 
                   
        case 1 :  led(1); // mise à l'état haut de la led 
                  if ( !button1() ){  // en cas d'appui sur le button1
                    state=0;  //on passe à l'état suivant et donc au case 0
                    delay(500);
                  }
                  else {  //sinon
                    state = 1;  // on reste dans l'état 1 donc le case 1
                  }
                  break;
      }
      */
      Serial.println("Sélecteurs : ");
      Serial.println(commutateur1()); // affichage de la position du commutateur
      Serial.println(commutateur2());
      Serial.println(" ");
      delay(500);
      Serial.println("Boutons poussoirs : ");
      Serial.println(!button1());
      Serial.println(!button2());
      Serial.println(!button3());
      Serial.println(!button4());
      Serial.println(" ");
      delay(500);
      //Serial.println(state);  // affichage de l'état du bouton sur le port série
      
    
    }
    
    int joy1_x() {
      return analogRead(analogPin_21B); // retourne la valeur analogique de analogPin_21B après la lecture de la broche
    }
    int joy1_y() {
      return analogRead(analogPin_22B);
    }
    int joy2_x() {
      return analogRead(analogPin_21A);
    }
    int joy2_y() {
      return analogRead(analogPin_22A); 
    }
    
    int commutateur1() {
      if (digitalRead( Pin1_comm1) == 0) return 1;
      if (digitalRead( Pin2_comm1) == 0) return 2;
      if (digitalRead( Pin3_comm1) == 0) return 3;
      return 0;
    }
    
    int commutateur2() { // déclaration de la fonction entière commutateur2
      if (digitalRead( Pin1_comm2) == 0) return 1; //retourne un certain nombre en fonction du port digital lu
      if (digitalRead( Pin2_comm2) == 0) return 2;
      if (digitalRead( Pin3_comm2) == 0) return 3;
      return 0;
    }
    
    void led(int status)  // déclaration de la fonction void led qui renvoie le statut de la led déclaré comme un entier
    {
      digitalWrite(pin_led, status);  //écrit la valeur du statut sur la broche de la pin_led
    }
    
    int button1() { // déclaration de la fonction entière button1
      return digitalRead(pin_btn1); //retourne l'état de pin_btn1 après la lecture de sa broche
    }
    
    int button4() { // déclaration de la fonction entière button1
      return digitalRead(pin_btn4); //retourne l'état de pin_btn2 après la lecture de sa broche
    }
    
    int button2() { // déclaration de la fonction entière button1
      return digitalRead(pin_btn2); //retourne l'état de pin_btn3 après la lecture de sa broche
    }
    
    int button3() { // déclaration de la fonction entière button1
      return digitalRead(pin_btn3); //retourne l'état de pin_btn4 après la lecture de sa broche
    }
    Merci de votre aide.
    Cordialement,
    • Partager sur Facebook
    • Partager sur Twitter
      6 octobre 2021 à 11:19:37

      ton code python il est sur quoi ? comment est relié la carte arduino avec ce quoi ? à mon avis, Pc avec cordon usb mais vu comme port série virtuel, donc un début de réponse, utiliser le module de communication série de python pySerial > https://pyserial.readthedocs.io/en/latest/pyserial.html#installation
      • Partager sur Facebook
      • Partager sur Twitter
        6 octobre 2021 à 11:32:03

        J'utilise Python sous Pycharm en version 3.9. Ma carte arduino est relié à mon pc sous cordon usb. Oui j'ai déjà codé un début de code Python.

        import serial
        
        i=0
        ser = serial.Serial('COM3',115200)
        # vide tout ce qu'il y a sur l'entrée en supprimant tout son contenu
        ser.flushInput()
        # Efface tout le contenu de sortie, annule la sortie actuelle et supprime tout ce qu'il y a dans le contenu
        ser.flushOutput()
        for i in range (5) :
            data_raw = ser.readline()
            ser.flushInput()
            ser.flushOutput()
        while True:
            #lit une ligne jusqu'au retour chariot
            data_raw = ser.readline()
            #print(data_raw)
            # Convert string to list of int
            integers = list(map(int, data_raw.split()))
            print (integers)

        Cependant après ça je suis perdu.

        -
        Edité par Aistos 6 octobre 2021 à 11:33:16

        • Partager sur Facebook
        • Partager sur Twitter
          6 octobre 2021 à 12:30:30

          tu es perdu sur quoi du coup ?

          ton arduino va envoyer en boucle (valeurs mises au hasard):

          Joystick 1 axe x :
          15
           [ici il y a un espace]
          Joystick 1 axe y :
          75
           [ici il y a un espace]
          Joystick 2 axe x :
          57
           [ici il y a un espace]
          Joystick 2 axe y :
          125
           [ici il y a un espace]
          Sélecteurs : 
          1
          1
           [ici il y a un espace]
          [tempo de 500ms]
          Boutons poussoirs : 
          0 [ou True/False]
          0
          0
          0
           [ici il y a un espace]
          [tempo de 500]


          Il faut donc traiter ces chaines que tu reçois ligne par ligne (ser.readline()): une 1ère chaine qui indique de quoi il s'agit, les suivantes (jusqu'à une chaine avec un espace seul) sont les valeurs, et on recommence.

          Si tu décommentes la ligne 16 et commentes les suivantes, tu devrais voir défiler un texte semblable à ce que j'ai mis.

          PS: pas sûr de l'utilité de la boucle ligne 9 à 12

          -
          Edité par umfred 6 octobre 2021 à 12:31:21

          • Partager sur Facebook
          • Partager sur Twitter
            6 octobre 2021 à 14:26:22

            Je ne comprenais pas comment faire la réception de mon code arduino en python. J'ai fais les modifications que vous m'avez dit d'apporter et j'obtiens le code suivant maintenant. 

            import serial
            
            i=0
            ser = serial.Serial('COM3',115200)
            # vide tout ce qu'il y a sur l'entrée en supprimant tout son contenu
            ser.flushInput()
            # Efface tout le contenu de sortie, annule la sortie actuelle et supprime tout ce qu'il y a dans le contenu
            ser.flushOutput()
            for i in range (5) :
                data_raw = ser.readline()
                ser.flushInput()
                ser.flushOutput()
            while True:
                #lit une ligne jusqu'au retour chariot
                data_raw = ser.readline()
                ser.readline()
                print(data_raw)
                # Convert string to list of int
                #integers = list(map(int, data_raw.split()))
                #print (integers)

            Cependant je pense encore avoir un problème par rapport à ma réception car en sortie j'obtiens ce type de valeurs.

            b'Boutons poussoirs : \r\n'
            b'0\r\n'
            b'0\r\n'
            b'S\xc3\xa9lecteurs : \r\n'
            b'1\r\n'
            b'Boutons poussoirs : \r\n'
            b'0\r\n'
            b'0\r\n'
            b'S\xc3\xa9lecteurs : \r\n'
            b'1\r\n'
            b'Boutons poussoirs : \r\n'
            b'0\r\n'
            b'0\r\n'
            b'S\xc3\xa9lecteurs : \r\n'
            b'1\r\n'

            Cela viendrait t-il d'un problème avec mon nombre de bits ?

            La boucle que j'ai faites de la ligne 9 à 12 était pour être sûre que l'on ai rien et que la mémoire soit bien vide pour l'écriture. 


            • Partager sur Facebook
            • Partager sur Twitter
              6 octobre 2021 à 15:49:11

              non c'est bon, c'est juste que l'on voit aussi les retours à la ligne façon windows (\r\n) à la fin des lignes et un problème d'encodage des caractères accentuées. En fait, les chaines sont sous forme de bytes, on peux les afficher normalement en faisant print(data_raw.decode('utf8'))

              PS la lecture en ligne 16, te fais perdre la lecture d'une ligne sur le port (vu que tu ne la stocke pas)

              PS2 normalement, les flush sont là pour vider les buffers (comme actuellement, on n'écrit rien sur le port, le buffer d'écriture est peu important)

              Ensuite, comme on ne sait pas quel traitement tu veux côté python, pas évident de te guider sur la suite, mais tu pourrais tester le message reçu avec les divers messages attendus et agir/afficher selon le message.

              Prévoir aussi l'utilisation d'un timeout sur la lecture pour éviter un blocage de l'application. Ci-dessous, une structure de départ (bien avancée je pense) à compléter/modifier selon le besoin

              import serial
              
              ser=serial.Serial('COM3',115200)
              ser.timeout=1.5 # valeur en secondes
              ser.reset_input_buffer() #flushInput est dépréciée depuis PySerial 3.0
              ser.reset_output_buffer() #idem pour flushOutput
              
              etape=0
              
              while True:
                 try:
                    msg_recu=ser.readline().decode('utf8').rstrip().lower() #réception puis décodage puis retrait des '\r\n' (avec rstrip()) puis mise en minuscule)
                 except serial.SerialTimeoutException:
                    print("Erreur: Sortie par Timeout de lecture")
                    print(f"Pas de message reçu dans l'intervalle de temps indiqué ({ser.timeout}s)")
                    break
                  except serial.SerialException:
                    print("Erreur: Erreur d'E/S du port série")
                    break
                  else:
                    if msg_recu.startswith("boutons"):
                       etape=1
                    elif msg_recu.startswith("sélecteur"):
                       etape=10
                    elif msg_recu.startswith("joystick"):
                       etape=20
                    elif msg_recu=='': # on passe ici si la chaine est vide (correspond à un changement de type de message)
                       etape=0  # ça évite de le tester à chaque type de message
                    elif etape==1:
                       #on passe ici si on a eu le message "boutons poussoirs" et que l'on a reçu le 1er message suivant
                       val=bool(int(msg_recu)) #'0'=>False, '1'=>True
                       # on traite la valeur reçue (qui peut être la 1ère ou la 2nde ou ...)
                     elif etape==10:
                        #on passe ici si on a eu le message "sélecteur" et une des valeurs
                       val=int(msg_recu)
                       # on traite la valeur reçue
                     elif etape==20:
                        #on passe ici si on a eu le message "joystick" et une des valeurs
                       val=int(msg_recu)
              
              ser.close()
              


              Edit: correction d'une coquille (COM3' => 'COM3') , utilisation du bon nom des méthodes de vidage des buffers de comm, et ajout de la fermeture du port à la fin

              -
              Edité par umfred 7 octobre 2021 à 16:10:29

              • Partager sur Facebook
              • Partager sur Twitter
                6 octobre 2021 à 16:20:55

                Effectivement après ajout dans mon code l'erreur n'apparaissait plus. Oui j'ai vu ça et malheureusement je perds deux valeurs pour mes boutons et ensuite une valeur pour mon commutateur et de même pour mes joysticks. 

                Je vois, je vous remercie pour ces informations et votre aide alors.

                Côté python je souhaiterai donc récupérer les valeurs comme je vous l'ai dis précédemment pour les "relier" ensuite à un serveur OPC UA qui est connecté à un logiciel que j'utilise pour ainsi pouvoir utiliser ma carte électronique dans le logiciel.

                Mon serveur fonctionne et j'ai pu me connecter sur le logiciel mais c'est côté transmission des données arduino vers python où j'ai du mal encore car une fois que j'aurai récupéré ces données je pourrai les réexploiter dans mon serveur.

                Le flush_input_buffer et le output semblent me créer des erreurs :

                AttributeError: 'Serial' object has no attribute 'flush_input_buffer'

                Cependant lorsque je remplace ces deux instructions par un flushInput et Output normal je n'obtiens alors plus rien en sorti.



                -
                Edité par Aistos 6 octobre 2021 à 16:21:56

                • Partager sur Facebook
                • Partager sur Twitter
                  6 octobre 2021 à 16:34:24

                  Aistos a écrit:

                  Le flush_input_buffer et le output semblent me créer des erreurs :

                  AttributeError: 'Serial' object has no attribute 'flush_input_buffer'

                  Cependant lorsque je remplace ces deux instructions par un flushInput et Output normal je n'obtiens alors plus rien en sorti.

                  -
                  Edité par Aistos il y a 3 minutes


                  c'est que tu n'utilises pas la version 3 ou + de PySerial 

                  Avec mon code tu peux récupérer les données, reste à les mettre dans la forme pour les fournir à ton serveur

                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 octobre 2021 à 16:46:11

                    Pourtant j'utilise la version 3.5 de PySerial je viens de vérifier dans mes paramètres.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      6 octobre 2021 à 17:09:23

                      Au temps pour moi,  leur nom est maintenant reset_input_buffer() et reset_output_buffer() (j'ai lu trop vite leur nouveau nom ^^)
                      • Partager sur Facebook
                      • Partager sur Twitter
                        7 octobre 2021 à 9:30:28

                        Bonjour,

                        Effectivement mais il n'y a pas de mal ne vous en faites pas ^^.

                        ser.reset_input_buffer()
                        ser.reset_output_buffer()

                        Cependant j'ai bien fait le changement et je n'ai plus rien alors en sortie qui s'affiche. 

                        Il est pourtant dit sur la documentation qu'il faut utiliser cela mais je ne comprends pas pourtant.

                        reset_input_buffer()
                        Flush input buffer, discarding all its contents.
                        
                        Changed in version 3.0: renamed from flushInput()
                        
                        reset_output_buffer()
                        Clear output buffer, aborting the current output and discarding all that is in the buffer.
                        
                        Note, for some USB serial adapters, this may only flush the buffer of the OS and not all the data that may be present in the USB part.
                        
                        Changed in version 3.0: renamed from flushOutput()



                        • Partager sur Facebook
                        • Partager sur Twitter
                          7 octobre 2021 à 12:38:32

                          tu ne l'utilises pas dans la boucle principale ? 

                          ce qu'il peut y avoir aussi, c'est qu'on a oublié de fermer le port COM (mais ça devrait déclencher une erreur)

                          PS: j'ai fait quelques corrections/ajouts dans mon code plus haut;

                          -
                          Edité par umfred 7 octobre 2021 à 12:39:48

                          • Partager sur Facebook
                          • Partager sur Twitter
                            7 octobre 2021 à 14:35:25

                            J'ai réalisé pour le moment deux scripts python. Le 1er est mon serveur et le second est l'envoi arduino/python. J'aimerai ensuite relier les deux grâce à un import je pense , le problème étant que les deux scripts ne peuvent tourner en même temps à cause du port 'COM3' occupé déjà par la réception .

                            Je ne pense pas que l'erreur vienne forcément du COM même s'il y avait pour autant deux coquilles dans le code avec COM et msg_recu == ' ' que vous avez corrigé par la suite.

                            J'ai vu les différentes corrections dont la fermeture du port oui.

                            J'ai bien peur cependant que cela n'ai réglé le problème car même après fermeture rien ne m'apparaît en sortie toujours. Pourtant sur ma carte j'essaye de réaliser des actions mais rien ne se passe en sortie.

                            import serial
                            
                            ser = serial.Serial('COM3', 115200)
                            ser.timeout = 1.5  # valeur en secondes
                            ser.reset_input_buffer()  # flushInput est dépréciée depuis PySerial 3.0
                            ser.reset_output_buffer()  # idem pour flushOutput
                            
                            etape = 0
                            
                            while True:
                                try:
                                    msg_recu = ser.readline().decode(
                                        'utf8').rstrip().lower()  # réception puis décodage puis retrait des '\r\n' (avec rstrip()) puis mise en minuscule)
                                except serial.SerialTimeoutException:
                                    print("Erreur: Sortie par Timeout de lecture")
                                    print(f"Pas de message reçu dans l'intervalle de temps indiqué ({ser.timeout}s)")
                                    break
                                except serial.SerialException:
                                    print("Erreur: Erreur d'E/S du port série")
                                    break
                                else:
                                    if msg_recu.startswith("boutons"):
                                        etape = 1
                                    elif msg_recu.startswith("sélecteur"):
                                        etape = 10
                                    elif msg_recu.startswith("joystick"):
                                        etape = 20
                                    elif msg_recu=='':  # on passe ici si la chaine est vide (correspond à un changement de type de message)
                                        etape = 0  # ça évite de le tester à chaque type de message
                                    elif etape == 1:
                                        # on passe ici si on a eu le message "boutons poussoirs" et que l'on a reçu le 1er message suivant
                                        val = bool(int(msg_recu))  # '0'=>False, '1'=>True
                                        # on traite la valeur reçue (qui peut être la 1ère ou la 2nde ou ...)
                                    elif etape == 10:
                                        # on passe ici si on a eu le message "sélecteur" et une des valeurs
                                        val = int(msg_recu)
                                        # on traite la valeur reçue
                                    elif etape == 20:
                                        # on passe ici si on a eu le message "joystick" et une des valeurs
                                        val = int(msg_recu)
                            
                            ser.close()

                            La carte étant fonctionnelle encore après de nombreux tests récents et après étude de votre code qui est correct je vous avoue être perdu, je ne comprends pas le pourquoi du comment à cette sortie vide.

                            • Partager sur Facebook
                            • Partager sur Twitter
                              7 octobre 2021 à 16:24:28

                              Si en sortie, tu parles affichage, effectivement rien ne s'affiche, il faut mettre un print(msg_recu) avant le except ligne 14 (de ton code) ou mieux dans le else en ligne 22.
                              Pour le traitement, je n'ai rien codé à part convertir la chaine en entier ou booléen dans val.

                              Il faut voir comment tu passes les infos. Tu pourrais les enregistrer dans un fichier type json.

                              Quand tu dis qu'ils ne peuvent pas fonctionner en même temps à cause du port COM, c'est à cause de la réception bloquante  par readline? ou parce que le script server utilise aussi ce port ?

                              • Partager sur Facebook
                              • Partager sur Twitter
                                8 octobre 2021 à 9:46:45

                                Efffectivement je n'avais pas remarqué l'abscence du print veuillez m'excuser. 

                                Si j'ai bien compris les données envoyées à la carte sont "enregistrées" dans les variables et json permettrai de les retranscrire ensuite dans le programme du serveur à l'aide de son fichier texte. Cependant je vous avoue n'avoir jamais utilisé json. 

                                Certes, par contre je vois l'intérêt de les mettre dans ce fichier après réception pour pouvoir les réutiliser dans le serveur en appelant ce fichier texte.

                                Ce fichier est-il mis à jour de façon automatique et instantanée dès qu'une action est faite sur la carte ?  

                                Je pense que c'est par le fait de la réception bloquante par readline car je ne lis pas le port COM3 sur mon serveur.

                                J'ai d'ailleurs modifier légèrement le code pour que les variables correspondent plus à ce que je souhaitais.

                                import serial
                                import time
                                
                                ser = serial.Serial('COM3', 115200)
                                ser.timeout = 1.5  # valeur en secondes
                                ser.reset_input_buffer()  # flushInput est dépréciée depuis PySerial 3.0
                                ser.reset_output_buffer()  # idem pour flushOutput
                                
                                etape = 0
                                
                                
                                while True:
                                    try:
                                        msg_recu = ser.readline().decode('utf8').rstrip().lower()  # réception puis décodage puis retrait des '\r\n' (avec rstrip()) puis mise en minuscule)
                                    except serial.SerialTimeoutException:
                                        print("Erreur: Sortie par Timeout de lecture")
                                        print(f"Pas de message reçu dans l'intervalle de temps indiqué ({ser.timeout}s)")
                                        break
                                    except serial.SerialException:
                                        print("Erreur: Erreur d'E/S du port série")
                                        break
                                    else :
                                        print((msg_recu))
                                        if msg_recu.startswith("boutons"):
                                            etape = 1
                                        elif msg_recu.startswith("sélecteur"):
                                            etape = 10
                                        elif msg_recu.startswith("joystick"):
                                            etape = 20
                                        elif msg_recu=='':  # on passe ici si la chaine est vide (correspond à un changement de type de message)
                                            etape = 0  # ça évite de le tester à chaque type de message
                                        elif etape == 1:
                                            # on passe ici si on a eu le message "boutons poussoirs" et que l'on a reçu le 1er message suivant
                                            boutons = bool(int(msg_recu))  # '0'=>False, '1'=>True
                                            # on traite la valeur reçue (qui peut être la 1ère ou la 2nde ou ...)
                                        elif etape == 10:
                                            # on passe ici si on a eu le message "sélecteur" et une des valeurs
                                            selecteurs = int(msg_recu)
                                            # on traite la valeur reçue
                                        elif etape == 20:
                                            # on passe ici si on a eu le message "joystick" et une des valeurs
                                            joysticks = int(msg_recu)
                                
                                ser.close()

                                Après edit sur mon logiciel il ne me faudrait récupérer au final plus que les valeurs des boutons 3 et 4 ainsi que celle du 1er commutateur et des 2 axes du second joysticks. 

                                -
                                Edité par Aistos 8 octobre 2021 à 9:49:49

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  8 octobre 2021 à 10:11:13

                                  je crois que j'ai fait le plus dur, à toi de l'adapter et compléter :p

                                  Juste pour préciser le fonctionnement (pas sûr que tu l'ai bien compris)

                                  Par exemple, quand on reçoit :

                                  Boutons poussoirs:
                                  1
                                  0
                                  
                                  

                                  Quand on reçoit "Boutons poussoirs" (ligne 14), on passe à la ligne 25, puis on revient au début de la boucle pour lire la suite (ligne 14).

                                   On reçoit donc '1', on va à la ligne 34 (puisque etape est à 1 et que les conditions d'avant ne sont pas vraies), donc on a boutons = True. Ensuite, on retourne au début de la boucle pour lire la suite (ligne 14).

                                  On reçoit le '0', on va toujours en ligne 34; donc boutons prend maintenant la valeur False; On poursuit et on retourne en ligne 14.

                                  On reçoit une chaine vide '', donc on va ligne 31, et etape vaut alors 0. On retourne en réception (ligne14) pour recevoir la suite.

                                  Donc, comme tu le constates, si tu veux les 2 valeurs, tu peux utiliser une liste (ou dictionnaire) à laquelle tu ajoutes les valeurs; ou tu rajoutes une (ou plus) étape pour recevoir chacune des valeurs et mettre à jour le fichier (par exemple).

                                  -
                                  Edité par umfred 8 octobre 2021 à 10:11:36

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    11 octobre 2021 à 9:42:46

                                    Très bien, je vous remercie de votre grande aide déjà :).

                                    Merci de m'avoir appelé le fonctionnement, mais ne vous en faites pas je l'avais compris mais peut-être mal réexpliqué à l'écrit sûrement.

                                    Oui j'ai un peu regarder comment fonctionnait json et même déjà commencé à coder un peu dessus. Effectivement l'utilisation d'un dictionnaire où d'une liste me semble aussi être le plus adapté par rapport à mon besoin. Rajouter les valeurs à la liste n'est-il pas le plus efficace et rapide ?

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      11 octobre 2021 à 11:58:04

                                      peut-être, mais json se basant sur une "architecture" de dictionnaire (ensembles clé : valeurs); ça éviterai des manips supplémentaires
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        11 octobre 2021 à 15:20:32

                                        Effectivement après plusieurs tests l'architecture dictionnaire de json me semble la meilleure. J'arrive à mettre à jour maintenant dans mon fichier les valeurs du sélecteur et d'un des deux boutons poussoirs à tour de rôle. Malheureusement pour le joystick c'est une autre histoire mais je réfléchis encore à la solution.

                                        import serial
                                        import time
                                        import json
                                        
                                        ser = serial.Serial('COM3', 115200)
                                        ser.timeout = 0.5  # valeur en secondes
                                        ser.reset_input_buffer()  # flushInput est dépréciée depuis PySerial 3.0
                                        ser.reset_output_buffer()  # idem pour flushOutput
                                        
                                        etape = 0
                                        
                                        
                                        while True:
                                            try:
                                                msg_recu = ser.readline().decode('utf8').rstrip().lower()  # réception puis décodage puis retrait des '\r\n' (avec rstrip()) puis mise en minuscule)
                                            except serial.SerialTimeoutException:
                                                print("Erreur: Sortie par Timeout de lecture")
                                                print(f"Pas de message reçu dans l'intervalle de temps indiqué ({ser.timeout}s)")
                                                break
                                            except serial.SerialException:
                                                print("Erreur: Erreur d'E/S du port série")
                                                break
                                            else:
                                                print((msg_recu))
                                                if msg_recu.startswith("boutons"):
                                                    etape = 1
                                                elif msg_recu.startswith("selecteur"):
                                                    etape = 10
                                                elif msg_recu.startswith("joystick"):
                                                    etape = 20
                                                elif msg_recu == '':  # on passe ici si la chaine est vide (correspond à un changement de type de message)
                                                    etape = 0  # ça évite de le tester à chaque type de message
                                                elif etape == 1:
                                                    # on passe ici si on a eu le message "boutons poussoirs" et que l'on a reçu le 1er message suivant
                                                    boutons = int(msg_recu)
                                                    dictionnaire ={"boutons": boutons}
                                                    with open("data.json", "w", encoding='utf-8') as l:
                                                        json.dump(dictionnaire, l)
                                                    with open("data.json", "r") as l:
                                                        dat = json.load(l)
                                                    # on traite la valeur reçue (qui peut être la 1ère ou la 2nde ou ...)
                                                elif etape == 10:
                                                    # on passe ici si on a eu le message "sélecteur" et une des valeurs
                                                    selecteur = int(msg_recu)
                                                    dico ={"selecteur": selecteur }
                                                    with open("data.json", "w", encoding='utf-8') as p:
                                                        json.dump(dico, p)
                                                    with open("data.json", "r") as p:
                                                        donnee = json.load(p)
                                                    # on traite la valeur reçue
                                                elif etape == 20:
                                                    # on passe ici si on a eu le message "joystick" et une des valeurs
                                                    joystick = float(msg_recu)
                                                    my_dictionnaire ={"joystick": joystick}
                                                    with open("data.json","w",encoding= 'utf-8') as f:
                                                        json.dump(my_dictionnaire,f)
                                                    with open("data.json","r") as f:
                                                        data_donnee = json.load(f)
                                        ser.close()



                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          11 octobre 2021 à 16:25:40

                                          et si plutôt que tester si msg_recu commence par 'joystick', on testait si ça commençait par 'joystick 1'/joystick 2' ou 'joystick 1 axe x'/'joystick 1 axe y'/.. :-°
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            12 octobre 2021 à 9:45:53

                                            Je ne pense pas que c'est la meilleure méthode et sûrement pas la plus efficace mais elle fonctionne du moins. J'ai décidé de créer trois fichiers json pour chacune de mes variables. Qu'en pensez-vous ?

                                            Il ne me reste donc plus que (dans la logique) à régler ce problème de valeurs non réécrites du bouton poussoir 3 dans mon fichier json boutons poussoirs puis ensuite à importer ces 3 fichiers json dans mon serveur et à régler ce soucis de readline bloquant.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              12 octobre 2021 à 13:08:36

                                              pourquoi ton server a besoin d'accéder au port COM ? 

                                              Si tu lances les 2 scripts en parallèle (si le server n'a pas besoin du port COM), il ne devrait pas y avoir de problèmes

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                12 octobre 2021 à 16:02:33

                                                Effectivement je devais avoir une erreur quelque part car cela fonctionne maintenant. Sauriez-vous par contre comment charger les données d'un fichier à un autre car j'ai écrit le code suivant mais cela me semble incorrect du moins j'ai l'impression que les données ne se mettent pas à jour sans relancer le serveur.

                                                    fileObject = open("boutons.json")
                                                    jsonContent = fileObject.read()
                                                    boutons = json.loads(jsonContent)
                                                    #print(boutons)
                                                    #print(boutons['boutons'])
                                                
                                                    fileObj = open("selecteur.json")
                                                    jsonCont = fileObj.read()
                                                    selecteur = json.loads(jsonCont)
                                                    #print(selecteur)
                                                    #print(selecteur['selecteur'])
                                                
                                                    file = open("joystick.json")
                                                    jsonfichier = file.read()
                                                    joystick = json.loads(jsonfichier)
                                                    #print(joystick)
                                                    #print(joystick['joystick'])



                                                -
                                                Edité par Aistos 12 octobre 2021 à 16:02:58

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  12 octobre 2021 à 17:34:58

                                                  j'ai pas trop compris ta demande, mais pour récupérer les données d'un fichier json, il suffit d'utiliser json.load() https://docs.python.org/3/library/json.html?highlight=json#json.load 

                                                  (et penser à fermer les fichiers aussi ou utiliser un bloc with)

                                                  import json
                                                  
                                                  #exemple de dictionnaire
                                                  boutons={"b1": True, "b2": False, "b3":True, "b4":True}
                                                  
                                                  #pour l'écriture
                                                  with open("boutons.json","w") as f:
                                                      json.dump(boutons,f)
                                                  
                                                  #pour la lecture
                                                  with open("boutons.json") as f:
                                                      boutons=json.load(f)
                                                  
                                                  



                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    13 octobre 2021 à 9:43:41

                                                    Veuillez m'excusez j'ai du mal m'expliquer. J'ai codé en python la réception de mes données.
                                                    import serial
                                                    import time
                                                    import json
                                                    
                                                    
                                                    ser = serial.Serial('COM3', 115200)
                                                    ser.timeout = 0.5  # valeur en secondes
                                                    ser.reset_input_buffer()  # flushInput est dépréciée depuis PySerial 3.0
                                                    ser.reset_output_buffer()  # idem pour flushOutput
                                                    
                                                    etape = 0
                                                    
                                                    
                                                    while True:
                                                        try:
                                                            msg_recu = ser.readline().decode('utf8').rstrip().lower()  # réception puis décodage puis retrait des '\r\n' (avec rstrip()) puis mise en minuscule)
                                                        except serial.SerialTimeoutException:
                                                            print("Erreur: Sortie par Timeout de lecture")
                                                            print(f"Pas de message reçu dans l'intervalle de temps indiqué ({ser.timeout}s)")
                                                            break
                                                        except serial.SerialException:
                                                            print("Erreur: Erreur d'E/S du port série")
                                                            break
                                                        else:
                                                            print((msg_recu))
                                                            if msg_recu.startswith("boutons"):
                                                                etape = 1
                                                            elif msg_recu.startswith("selecteur"):
                                                                etape = 10
                                                            elif msg_recu.startswith("joystick"):
                                                                etape = 20
                                                            elif msg_recu == '':  # on passe ici si la chaine est vide (correspond à un changement de type de message)
                                                                etape = 0  # ça évite de le tester à chaque type de message
                                                            elif etape == 1:
                                                                # on passe ici si on a eu le message "boutons poussoirs" et que l'on a reçu le 1er message suivant
                                                                boutons = int(msg_recu)
                                                                dictionnaire ={"boutons": boutons}
                                                                with open("boutons.json", "w", encoding='utf-8') as l:
                                                                    json.dump(dictionnaire, l)
                                                                with open("boutons.json", "r") as l:
                                                                    bout = json.load(l)
                                                                # on traite la valeur reçue (qui peut être la 1ère ou la 2nde ou ...)
                                                            elif etape == 10:
                                                                # on passe ici si on a eu le message "sélecteur" et une des valeurs
                                                                selecteur = int(msg_recu)
                                                                dico ={"selecteur": selecteur }
                                                                with open("selecteur.json", "w", encoding='utf-8') as p:
                                                                    json.dump(dico, p)
                                                                with open("selecteur.json", "r") as p:
                                                                    select = json.load(p)
                                                                # on traite la valeur reçue
                                                            elif etape == 20:
                                                                # on passe ici si on a eu le message "joystick" et une des valeurs
                                                                joystick = float(msg_recu)
                                                                my_dictionnaire ={"joystick": joystick}
                                                                with open("joystick.json","w",encoding= 'utf-8') as f:
                                                                    json.dump(my_dictionnaire,f)
                                                                with open("joystick.json","r") as f:
                                                                    joy = json.load(f)
                                                    ser.close()

                                                    Ensuite, j'ai également codé mon serveur ci-dessous.

                                                    import time
                                                    import json
                                                    from opcua import ua, Server
                                                    
                                                    
                                                    if __name__ == "__main__":
                                                        # setup server
                                                        server = Server()
                                                        server.set_endpoint("opc.tcp://localhost:4841")
                                                    
                                                        '''
                                                        server.set_security_policy([
                                                          ua.SecurityPolicyType.NoSecurity,
                                                          ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
                                                          ua.SecurityPolicyType.Basic256Sha256_Sign
                                                        ])
                                                        '''
                                                        OFFSET_JOYSTICK = 50
                                                    
                                                        # setup our own namespace, not really necessary but should as spec
                                                        uri = "http://localhost"
                                                        idx = server.register_namespace(uri)
                                                    
                                                        # get Objects node, this is where we should put our nodes
                                                        objects = server.get_objects_node()
                                                        print(objects)
                                                    
                                                        # populating our address space
                                                        MyObjects = objects.add_object(idx, "MyObjects")
                                                        button3 = MyObjects.add_variable(idx,"button3",int(0))
                                                        button4 = MyObjects.add_variable(idx,"button4",int(0))
                                                        joy2_x = MyObjects.add_variable(idx,"joy2_x",int(512))
                                                        joy2_y = MyObjects.add_variable(idx,"joy2_y",int(512))
                                                        Selecteur = MyObjects.add_variable(idx,"selecteur",int(0))
                                                    
                                                        # starting!
                                                        server.start()
                                                    
                                                        while True:
                                                    
                                                            with open("boutons.json") as p:
                                                                boutons = json.load(p)
                                                                print(boutons)
                                                                print(boutons['boutons'])
                                                    
                                                            if button3 == 1:
                                                                ButtonSignal = True
                                                                button3.set_writable()
                                                            else:
                                                                ButtonSignal = False
                                                                button3.set_writable()
                                                    
                                                            if button4 == 1:
                                                                for i in range(1,4):
                                                                    if i == 1:
                                                                        SlowSpeed = True
                                                                        FastSpeed = False
                                                                        StartStopSpeed = False
                                                                        button4.set_writable()
                                                                    if i == 2:
                                                                        SlowSpeed = False
                                                                        StartStopSpeed = False
                                                                        FastSpeed = True
                                                                        button4.set_writable()
                                                                    if i == 3:
                                                                        FastSpeed = False
                                                                        SlowSpeed = False
                                                                        StartStopSpeed = True
                                                                        button4.set_writable()
                                                    
                                                            if button4 == 0:
                                                                SlowSpeed = False
                                                                FastSpeed = False
                                                                StartStopSpeed = False
                                                                button4.set_writable()
                                                    
                                                            with open("selecteur.json") as f:
                                                                selecteur = json.load(f)
                                                                print(selecteur)
                                                                print(selecteur['selecteur'])
                                                    
                                                            if selecteur == 1:
                                                                Vitesse_lente = True
                                                                Selecteur.set_writable(selecteur)
                                                                with open("joystick.json") as o:
                                                                    joystick =json.load(o)
                                                                    print(joystick)
                                                                    print(joystick['joystick'])
                                                                if joy2_x < (512 - OFFSET_JOYSTICK) and joy2_y < (512 - OFFSET_JOYSTICK):
                                                                    joy2_x.set_writable()
                                                                    joy2_y.set_writable()
                                                                    Vitesse_lente = 300
                                                    
                                                            if selecteur == 2:
                                                                Vitesse_normale = True
                                                                Selecteur.set_writable(selecteur)
                                                                with open("joystick.json") as l:
                                                                    joystick = json.load(l)
                                                                    print(joystick)
                                                                    print(joystick['joystick'])
                                                                if joy2_x == 512 and joy2_y == 512:
                                                                    joy2_x.set_writable()
                                                                    joy2_y.set_writable()
                                                                    Vitesse_normale = 500
                                                    
                                                            if selecteur == 3:
                                                                Vitesse_rapide = True
                                                                Selecteur.set_writable(selecteur)
                                                                with open("joystick.json") as r:
                                                                    joystick = json.load(r)
                                                                    print(joystick)
                                                                    print(joystick['joystick'])
                                                                if joy2_x > (512 + OFFSET_JOYSTICK) and joy2_y > (512 + OFFSET_JOYSTICK):
                                                                    joy2_x.set_writable()
                                                                    joy2_y.set_writable()
                                                                    Vitesse_rapide = 700
                                                    
                                                            # Set MyVariable to be writable by clients
                                                    
                                                            print(server.get_namespace_array())
                                                    
                                                            try:
                                                                # count = 0
                                                                # while True:
                                                                #     time.sleep(1)
                                                                #     count += 0.1
                                                                #     myvar.set_value(count)
                                                                input("Press Enter to shutdown server...\n")
                                                            finally:
                                                                # close connection, remove subcsriptions, etc
                                                                server.stop()

                                                    Effectivement, après avoir fait un peu de documentation j'avais vu que load chargeait mes fichiers json dans la réception données et dans le serveur. Est-ce que le fait de charger ces fichiers dans deux endroits différents peut-il avoir un impact ? (Selon moi, il n'est pas nécessaire de les charger aussi dans la réception à part pour vérification au pire de si elles se mettent à jour correctement dans leurs fichiers respectifs)

                                                    Ce que je souhaitais dire c'est que malgré par exemple une position 1 sur mon sélecteur je ne passe pas dans ma boucle if j'ai l'impression car ma valeur de joystick ne s'affiche pas dans mon terminal sur mon serveur. C'est pour ça que j'avais l'impression que les données ne se mettaient à jour que après l'arrêt de mon script serveur et au relancement de celui-ci.

                                                    -
                                                    Edité par Aistos 13 octobre 2021 à 9:46:17

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      13 octobre 2021 à 11:30:20

                                                      Je ne vois pas pourquoi tu les réouvres après les avoir créer dans la réception (à noter que le fichier ne contient que la dernière valeur lue du bouton/sélecteur/joystick, qui va être tour à tour la 1ère valeur, puis la 2nde, ...)

                                                      Les ouvrir des 2 côtés ne devrait pas trop posé de problèmes je pense (sauf peut-être dans le cas où le fichier est ouvert pour lecture d'un côté et ouvert en écriture de l'autre.

                                                      Sinon sauf erreur de ma part, je ne vois aucune liaison entre les données du fichier json et tes variables button3 et autres (côté serveur) (a priori seul selecteur serait ok)

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        13 octobre 2021 à 15:13:49

                                                        Oui dans la réception je pense que je n'avais pas besoin de les rouvrir et d'ailleurs j'ai supprimé les différentes parties de code ou je les chargeaient.

                                                        Ayant créé 3 fichiers différents pour chacune des mes variables j'évite ce tour à tour justement je pense non ?

                                                        Oui effectivement mais le problème étant que dans ma réception de données Arduino je suis obligé d'avoir l'écriture dans les différents fichiers json tandis que dans le serveur le chargement de ces données pour la connexion avec mon logiciel et ainsi agir dessus avec ma carte électronique. 

                                                        Oui mais cela est dû au fait que je ne me suis pas encore occupé du problème avec la détection seulement de mon bouton 4 et pas 3. Lorsque j'aurai réussi à différencier les deux variables dans l'écriture sur json je pourrai alors les charger sur mon serveur de façon correcte. Pour le moment seulement le bouton 4 est détecté sur mon fichier json lorsqu'il y a appui et sur le serveur seulement l'appui sur les deux boutons en même temps met la variable à 1. Oui pour le sélecteur aussi cela me semble correct même si je ne comprends pas pourquoi malgré un print mon joystick ne s'affiche pas en sortie (côté serveur).

                                                        Je corrige mes différentes erreurs et reviens vers vous plus tard pour vous donner des nouvelles. Je vous remercie en tout cas pour toute l'aide déjà donnée et les différents conseils que vous m'avez fournis. 

                                                        -
                                                        Edité par Aistos 13 octobre 2021 à 15:22:52

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          13 octobre 2021 à 19:13:25

                                                          je répète (peut-être plus clairement), dans le json, tel que tu l'as écrit tu n'as qu'une seule valeur à chaque fois, qui peut être celle du bouton 1, 2, 3 ou 4, sans savoir lequel il s'agit.

                                                          ton selecteur ne fonctionne pas, car selecteur est un distionnaire et donc est différent de 1, 2 ou 3; en revanche, si dans tes tests, tu remplaces par selecteur['selecteur'] ça devrait fonctionner.

                                                          Et comment le serveur peut agir sur la carte arduino ? (qu'est-ce qu'il faut faire pour envoyer une commande à l'arduino)

                                                          Il ne vaudrait pas mieux définir un protocole de communication entre le pc et la carte arduino (quitte à ce le programme python reçoive les données, autant y répondre) ?  du style:

                                                          PC : "LIRE BOUTON 1\n"

                                                          Arduino: "BOUTON 1 = [valeur]\n"

                                                          PC: "ECRIRE SPEED [LOW ou FAST ou STOP]\n"

                                                          Arduino: "OK\n"

                                                          (ça peut être fait de manière codée par octet)

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            14 octobre 2021 à 10:03:14

                                                            Oui effectivement j'avais remarqué pour les boutons cette erreur et je viens de la "réparer". Cependant mon bouton est devenu un string et dans la logique je devrais le convertir en float puis en int . Cependant la conversion semble impossible.

                                                            bouton3 = int(float(msg_recu))
                                                            ValueError: could not convert string to float: 'bouton3 :'

                                                            Très bien, je vois merci j'avais pensé à cette idée mais je n'étais pas sur.

                                                            Le serveur est relié au logiciel et à partir du moment où je vais effectuer une commande sur ma carte, grâce au code créé le logiciel va par exemple du coup pouvoir détecté l'appui et ainsi exécuté l'action ainsi voulue dans le logiciel.

                                                            Le serveur ne doit pas agir sur la carte mais voir si par exemple la valeur d'un bouton est à 1 ou 0 et ensuite c'est le logiciel connecté en liaison OPC UA avec mon serveur qui gère le reste. Enfin selon moi cela fonctionne comme ça, car je ne pense pas avoir la nécessité de répondre à ces données envoyées.



                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              14 octobre 2021 à 12:15:16

                                                              là tu cherches à convertir la chaine 'bouton 3:' en float ou entier ce qui n'est pas possible

                                                              Si tu changes la façon d'envoyer les données de ton arduino, il faut adapter en conséquence la réception.

                                                              J'ai toujours du mal à voir l'organisation des logiciels. Ce que j'ai compris:

                                                              • un logiciel Arduino qui lit l'état de boutons/selecteur/joystick et qui envoi leur état en série à un PC (le code ne semble faire que ça, donc j'en viens à supposer qu'il "surveille" un autre système
                                                              • un logiciel python qui reçoit les données et les mets (plus ou moins) à dispositon via fichiers json
                                                              • un logiciel python serveur qui utilise les fichiers json pour connaitre les états et fournir les infos à un autre logiciel
                                                              • un dernier logiciel qui utilise les états fourni par le serveur pour faire quelque chose ("le reste" ? interaction avec la carte arduino, avec un autre système?). c'est quoi ce logiciel ? 
                                                              Donc déjà tu pourrais avoir un seul script python qui lit les données envoyés par l'arduino puis les mets à dispo pour l'autre logiciel mystère (tu t'évites l'étape des fichiers json)

                                                              -
                                                              Edité par umfred 14 octobre 2021 à 12:18:19

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Communication Arduino vers Python

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown