RESOLU : Communication série entre Arduino et Python

Bonsoir à tous,

J'essaie de connecter un arduino à mon PC via un script Python.
Le script Python doit envoyer une chaine de caractère représentant un entier, et l'arduino allume des leds sur le port F (de A0 à A7)

Lorsque j'essaie avec le moniteur série, les leds s'allument correctement, la représentation binaire de cet entier.

Par contre, lorsque j'utilise mon script Python simplifié, c'est l'échec.
Le script python est sensé n'envoyer qu'une chaîne de caractère représentant un entier.

Bien entendu, je reset l'arduino avant chaque tentative d’exécution du script Python.
J'ai beau modifier mon python en fonction de ce que j'ai lu un peu à gauche et à droite, mais je ne comprends pas pourquoi cela ne fonctionne pas.

Est ce que quelqu'un a déja eu ce genre de soucis? Et comment établir la communication entre les 2 programmes?

Code Arduino :

/* Source : https://forum.arduino.cc/index.php?topic=288234.0
  Receive an int value, then lights up leds on port F (A0 to A7) */

#define port PORTF

const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;

int value;

void setup() {
  Serial.begin(9600);
  Serial.println("<Ready!>");

  //PORTF :
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);
  pinMode(A6, OUTPUT);
  pinMode(A7, OUTPUT);
}

void loop() {
  recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker() {
  static byte ndx = 0; /*Index of array*/
  char endMarker = '\n';
  char rc; /*received char*/

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}

void showNewData() {
  if (newData == true) {
    
    value = atoi(receivedChars);
    /*
    Serial.print("Resp :");
    Serial.println(value);
    */
    
    port = value; //light up leds
    

    newData = false;
  }
}

Script Python :

#!/usr/bin/env python 
#-*-coding:utf-8-*- 
 
#test d'encoding ascii : sans effet 
 
import serial 
 
def send(chaine): 
    """ """ 
    cnx = serial.Serial(port = "/dev/ttyACM0", 
                        baudrate = 9600 
                        ) 
     
    #cnx.flush() #Doesnt work 
     
    #cnx.write(chaine.encode()) #Doesnt work 
    cnx.write(chaine) #Doesnt work 
    cnx.close() 
     
if __name__ == "__main__": 
    """ """ 
    send("45")

Matériel et logiciels utilisés :

  • Arduino IDE, V1.8.13,
  • Board Arduino Mega 2560
  • Python 2.7
  • Système d'exploitation : Ubuntu 18.04

Par le passé, j'ai effectué de nombreux projets avec arduino, j'ai réussi à trouver des solutions sur le net.
Mais là, je sèche vraiment.

Merci de votre soutien.

Bonjour,

Si tu veux envoyer la string en ascii il faut la préfixer par b
cnx.write(b"45");

ou utiliser .encode() comme tu avais fait en commentaire

Merci pour ton soutien.

Je suis véritablement une andouille cosmique.
Dans le premier paragraphe de la fonction recvWithEndMarker(), j'ai l'attente d'un newline \n :

void recvWithEndMarker() {
  static byte ndx = 0; /*Index of array*/
  char endMarker = '\n';
  char rc; /*received char*/

Effectivement, en jouant avec les options du moniteur série en refusant les fins de ligne : il n'y a pas d'affichage.
Je peux même changer l'endMarker par '+' dans le moniteur et dans le sketch : j'ai l'affichage.
Mais lorsque je passe à l'envoi par Python, mon affichage reste désespérément vide.
Voici ce que j'ai essayé :

#cnx.write("90"+chr(10)) #Doesnt work 
#cnx.write(b"90"+chr(10)) #Doesnt work 
#cnx.write( ("90"+chr(10) ).encode()) #Doesnt work 
#cnx.write("90".encode()+chr(10) ) #Doesnt work

Avec ta piste en préfixant ma chaine avec b, kamill, je suis tombé sur ceci : What’s New in Python 2.6 — Python v2.6.6 documentation

J'ai essayé de convertir mes chaines avec bytearray(), mais toujours rien.
Je continue à chercher.

Quand tu te connectes à la liaison série avec serial.Serial() ça provoque un reset de la carte.
Il faut mettre un delai de plusieurs secondes afin de laisser le temps à la carte de faire son reset avant d'envoyer quelque-chose.

1 Like

cnx.write(("90"+chr(10)).encode()) doit fonctionner

ou de manière plus concise
cnx.write("90\n".encode())

Bien vu : il s'agit d'insérer une petite temporisation après serial.Serial.

J'ai fais des tests avec ou sans encode(), cela fonctionne, je vais le garder par précaution.

Mon projet est en réalité un sketch Arduino qui gère l'affichage d'une matrice à les 8x8.
Relié à un programme en Python sur lequel on dessine le motif à afficher et qui envoie la trame qui va bien à l'Arduino.

Avec la temporisation, je parviens bel et bien à mes fins.

Voici le programme python simplifié et corrigé, pour ceux que cela intéressera :

#!/usr/bin/env python 
#-*-coding:utf-8-*- 
 
import serial, time 
 
def send(chaine): 
    """ """ 
    cnx = serial.Serial(port = "/dev/ttyACM0", 
                        baudrate = 9600 
                        ) 
     
    val = (chaine+chr(10)) 
     
    time.sleep(1) 
    cnx.write(val.encode()) 
     
    cnx.close() 
     
if __name__ == "__main__": 
    """ """ 
    send("180")

Le problème est résolu.
Merci beaucoup.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.