Vitesse de communication Série PC -> Arduino

Bonjour.

Je souhaite faire communiquer une application codée sur en Processing (https://processing.org/) sur PC avec une carte Arduino NANO (j'ai fait les même test avec une Arduino UNO).

Je parviens sans problème a envoyer des donnée depuis le PC vers la carte, mais je constate qu'il y as environ 1.2s entre le moment ou j'appuie sur le bouton de l'appli, et le moment ou la carte effectue l'action désignée (allumer une LED pour mon test).
J'ai vérifié mes deux code, a aucun moment, je ne met de délai, et pris séparément, ils s'exécute tout deux très rapidement.

Est ce quelqu'un saurait m'expliquer d'où vient cette lenteur de communication, et si possible, comment la diminuer ?

Merci d'avance.

postez les 2 codes ... sinon vous nous demandez de faire de la divination...

Mon pari si je regarde la boule de cristal : vous utilisez la fonction arduino comme readString etc qui a un timeout d'une seconde...

Merci de votre réponse si rapide.

Je n'ai pas posté le code car il est très grand (700 lignes).
Quand je rentre chez moi, je poste les deux codes.

En effet, j'utilise la fonction Arduino readString().
Si vous dites que le délai de transmission vient de la, est ce que vous connaissez une alternative plus rapide ?

ce n'est pas si immense que ça

S'est pour ça que j'ai dit "très grand".
En tout cas, moi s'est mon plus grand code...

oui tout est relatif :slight_smile:

cette fonction attend un timeout, c'est à dire qu'il n'y ait plus d'activité en réception sur le port série et le défaut est d'attendre une seconde, ce qui fait que votre réponse est retardée d'une seconde.

Vous pourriez modifier ce délai (cf Serial.setTimeout()) ou mieux - traiter le flot en provenance du port série quand les octets arrivent et avoir un marqueur de fin de message (comme le passage à la ligne par exemple)

Vous pouvez jeter un oeil à mon petit tuto sur le sujet

Merci, je vais aller regarder.

voici une version allégé de mes codes :

Arduino :

int LED_1 = 8;
int LED_PWM = 10;
int val = 0; // valeur recus par le port serie
void setup() {
  pinMode(LED_1, OUTPUT);
  pinMode(LED_PWM, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200); // vitesse de tensmission par le port Serie
}
/*
  CODEC
   0 - 255 : vitesse
   256 : OFF
   257 : ON

  Ce sont les codes de transmission. En théorie, on peut aussi utiliser des lettres, ou comuniquer dirrectement en ASCII, mais je n'ai pas essayer
*/
void loop() {
  if( Serial.available() ){
    val=Serial.readStringUntil("\n").toInt();
    digitalWrite(LED_BUILTIN, HIGH);
  }
  else{
    digitalWrite(LED_BUILTIN, LOW);
  }

  Serial.println(val);

  if( val <= 255 ){
    analogWrite(LED_PWM, val);
  }
  else if( val == 256 ){
    digitalWrite(LED_1, LOW);
  }
  else if( val == 257 ){
    digitalWrite(LED_1, HIGH);
  }
}

Processing

import processing.serial.*; // on importe la bibliothèque serial pour la comunication serie
Serial myPort; //  on crée un objet myPort, qui correspond au port USB ou est brancher la carte.

int bouton_1 = 0; // variable de la valeur du bouton : 0-OFF 1-ON
int etat_bouton_1 = 0; // variable de la positon du bouton : 0-relacher 1-apuiller

int bouton_plus = 0;
int etat_bouton_plus = 0;

int bouton_moin = 0;
int etat_bouton_moin = 0;

int vitesse = 0; // variable de la vitesse, elle est modifier par les bouton plus et moins

/*
  CODEC
   0 - 255 : vitesse
   256 : OFF
   257 : ON

  Ce sont les codes de transmission. En théorie, on peut aussi utiliser des lettres, ou comuniquer dirrectement en ASCII, mais je n'ai pas essayer
*/


void send(int val){ // variable pour envoyer de donée sur le port serie (s'est pas obligué de faire une variable, mais s'est bien plus pratique.
  fill(0,0,0); // on change la couleur pour passer a du noir
  textSize(15); // on defini la hauteur du texte a 15px
  text(val,width-20,height-10); // on affiche le texte de la variable val a la position x, y
  // Pour les position, il vaut mieux utiliser des fraction de la hauteur de la fenete (width) et de sa largeur (height)
  // Ce qui permet de garder la meme disposition des element dans l'ecran si l'on modifie sa taille (ercan plus haute résolution)
  myPort.write(str(val)+"\n"); // on envoie sur le port serie la valeur val. Il faut la configurer en str pour envoyer une chaine de charactère (sa ne marche pas sinon), et mettre un retour a la ligne
}
void setup(){
  size(500,500); // nombre de pixels de la fenetre (largeur, hauteur)
  
  myPort = new Serial(this, "COM9", 115200); // initialisation de la comunication Serie
  // la deuxieme valeur correspond au nom du port USB ou est conecter la carte. Pour savoir sur quelle port elle est brancher, il faut soit :
  //   - executer la fonction Serial.list()
  //   - ouvrir  l'IDE arduino pour savoir sur quel port est brancher la carte
  // NOTE : On ne peut pas utiliser le moniteur serie d'Arduino et le port serie avec processing simulanement !
  // La troisieme valeur correspond au nombre de Bauds (vitesse de transmission). Je la met az 115200 pour augmenter la vitesse.
  // La carte doit absolument etre sur la meme vitesse !
  
}
void draw(){ // equivalent de la boucle loop() en C++
  background(200,200,200); // mettre la couleur de l'arriere plan a RGB(200,200,200). A mettre au debut du draw() pour reinitialisé ce qui a ete dessiner precedement
  
  // affichage du dessin de fond
  noStroke(); // on desactive la fonction bordure des carré. Pour les réactiver: stroke(0);   Pour modifier l'épaisseur: strokeWeight(valeur);
  rectMode(CORNER); // on defini ou sera le point de coordonée du reectengle : CORNER - en haut a gauche   CENTER - au centre  (il y en as d'autre, mais je ne les utilise pas
  fill(30,157,29); // on defini la couleur en RGB. Pour bien choisir la couleur, va dans: Outil -> Sélecteur de couleur
  rect(0+(width/100),0+(height/100), width/2-(width/100), height-(height/50)); // rectangle afficher rect(positionX, positionY, largeur, hauteur);
  fill(0); // changer la couleur. Pour les couleur en nuance de gris, on peut ecrire qu'un seul valeur. Ainsi, fill(150,150,150); est comme fill(150); . Ici, fill(0); fait comme fill(0,0,0);
  rect(width/3,0+(height/100),width/40,height-(height/50)); // on dessine le rail
  fill(201,20,26); // couleur de la maison
  rect(width/10,height/2,width/5,height/5); // dessin du toit de la maison
  
  // dessin des bouton
  // -- bouton 1 --
  if( bouton_1 == 0 ){ // si la valeur du bouton vaut 0, il sera rouge
    fill(255,0,0);
  }
  else if( bouton_1 == 1 ){ // sinon, il sera vert
    fill(0,255,0);
  }
  stroke(0); // on defini la couleur des bordure
  strokeWeight(1); // on defini la largeur du trait, 1px par defaut, mais on peut mettre plus
  rectMode(CENTER); 
  rect(3*width/4,height/4,width/5,width/5,15); // dessin du rectengle qui figure le bouton. NOTE: la deniere valeur correspond au rayon de l'angle du rectangle
  
  // -- bouton moin --
  if( etat_bouton_moin == 0 ){ // quand on n'apruille pas sur le bouton, il est gris clair
    fill(180,180,180);    
  }
  else if( etat_bouton_moin == 1 ){ // quand on appuille sur le bouton, il deviens gris foncé
    fill(150,150,150);
  }
  rect(5*width/8,3*height/4,width/6,height/6);
  fill(0); // on remet la couleur en noir pour afficher le texte du bouton
  textSize(width/10);
  textAlign(CENTER,CENTER); // on defini que la valeur X et Y du text correspond a cont centre en X et en Y
  text("-",5*width/8,3*height/4); // comme le texte et le rectangle sont defini en CENTER (voir plus haut), il suffit de mettre les meme cooerdonée au texte pour qu'il se centre dans le carée
  
  // -- bouton plus --
  if( etat_bouton_plus == 0 ){ // quand on n'apruille pas sur le bouton, il est gris clair
    fill(180,180,180);    
  }
  else if( etat_bouton_plus == 1 ){ // quand on appuille sur le bouton, il deviens gris foncé
    fill(150,150,150);
  }
  rect(7*width/8,3*height/4,width/6,height/6);
  fill(0); // on remet la couleur en noir pour afficher le texte du bouton
  textSize(width/10);
  textAlign(CENTER,CENTER); // on defini que la valeur X et Y du text correspond a cont centre en X et en Y
  text("+",7*width/8,3*height/4); // comme le texte et le rectangle sont defini en CENTER (voir plus haut), il suffit de mettre les meme cooerdonée au texte pour qu'il se centre dans le carée
  
  
  
  // affichage de la vitesse
  textSize(width/15);
  text("vitesse : " + vitesse + "%",3*width/4,4.5*height/8);
  
  
  // code des bouton
  
  /*
  sytaxe de la comande de bouton :
  
  if(abs(mouseX-( positionX ))<( largeur )/2 && abs(mouseY-( positionY ))<( hauteur )/2 && mousePressed ){
      Code a effectuer qand le bouton est pressé
    }

  mouseX - renvoie la position en X de la sourie
  mouseY - renvoie la position en Y de la sourie 
  mousePressed - quand on appuie sur la sourie

*/
  if(abs(mouseX-(3*width/4))<(width/5)/2 && abs(mouseY-(height/4))<(width/5)/2 && mousePressed){
      if( bouton_1 == 1 && etat_bouton_1 == 0 ){ // la comande ne s'effectue QUE si le bouton valais 1 ET qu'il etait relacher. Si tu enleve le "&& etat_buoton_1 == 0", tu peut voir que le bouton clignote tant que tu appuille dessus
        bouton_1 = 0;
      }
      else if( bouton_1 == 0 && etat_bouton_1 == 0 ){
        bouton_1 = 1; 
      }
      etat_bouton_1 = 1; // on precise que le bouton est apuiller
    }
    else{
      etat_bouton_1 = 0; // on precise que le bouton est relacher
    }
    
    // -- bouton moin --
    if(abs(mouseX-(5*width/8))<(width/6)/2 && abs(mouseY-(3*height/4))<(height/6)/2 && mousePressed){
      if( vitesse > 0 ){ // je n'utilise pas la variable etat_bouton_moin car il faut que si l'on laisse appuiler sur le bouton la vitesse augment en continue. Si je eut que l'on na puisse pas maitenir appuiler sur le bouton il faut ajouter " && etat_bouton_moin == 0 "
        vitesse = vitesse - 5;
        delay(50);
      }
      etat_bouton_moin = 1;
    }
    else{
      etat_bouton_moin = 0;
    }
   
    // -- bouton plus --
    if(abs(mouseX-(7*width/8))<(width/6)/2 && abs(mouseY-(3*height/4))<(height/6)/2 && mousePressed){
      if( vitesse < 100 ){
        vitesse = vitesse + 5;
        delay(50);
      }
      etat_bouton_plus = 1;
    }
    else{
      etat_bouton_plus = 0;
    }



  // envoie des donée
  if( etat_bouton_1 == 1 ){ // ce qui s'esxecute des que l'on appuie sur le bouton
    if( bouton_1 == 0 ){
      send(256); // si le bouton vaut 0, en envoie le code "eteint"
    }
    else if( bouton_1 == 1 ){
      send(257); // si le bouton vaut 1, on envoie le code "allumer"
    }
  }
  if( etat_bouton_plus == 1 || etat_bouton_moin == 1 ){ // veut dire "Si etat_bouton_plus est egal a 1 OU si etat_bouton_moin est egal a 1"
    send(int(vitesse*2.55)); // on envoie la vitesse apres l'avoir converti en 255
  }
}

Si je comprend bien, il faut que j'ajoute une ligne dans le setup() du code Arduino qui dit :

Serial.setTimeout(20);

Ce qui me permettrais de réduire a 20ms le délai de lecture ?

Sinon, si se n'est pas abuser, est ce que vous pourriez me dire plus en détails comment "traiter le flot en provenance du port série quand les octets arrivent et avoir un marqueur de fin de message (comme le passage à la ligne par exemple)" ?

ah vous utilisez Serial.readStringUntil()

il faut écrire plutôt val=Serial.readStringUntil('\n').toInt(); car la fonction attend un caractère, pas une chaîne de caractères.

elle s'arrête dès que le caractère est reçu donc si vous l'émettez correctement, ce n'est pas là le souci.

Quel délai voyez vous avec ce code ?

attention il faut mettre aussi tout le code qui traite val dans le if quand vous avez effectué la réception, sinon ce sera exécuté en permanence pour rien.

c'est dans mon tuto

Bonjour guillaume_lrt

Tu as déjà quasiment tout juste, il faut juste faire la correction "\n" en '\n' et ça devrai fonctionner sans cette attente de 1 seconde. Le timout n'est plus nécessaire.

Maintenant, si tu veux une communication plus "évoluée" pour pouvoir transmettre plus de paramètres commee:
VIT200 pour vitesse 200
TEMP12.35 pour une consigne température de 12,35°
etc.
Je peux t'indiquer comment faire.

A+
Cordialement
jpbbricole

Bonsoir @jpbbricole,

Est ce que transmettre une combinaison de lettre et de chiffre comme tu me l'a proposer permettrais de réduire encor la vitesse de transmission ?

Sinon, j'ai modifier ma commande de réception, et il n'y as plus (ou presque) de délai !
Merci beaucoup de votre aide !

Guillaume

Bonjour Guillaume

Non, certainement pas, mais à 115200 l'impact est faible. L'avantage est d'augmenter la plage des possibilités de commandes différentes.

Bonne soirée.
jpbbricole