[Resolu] Communication arduino <-> processing via port USB

Bien le bonjours à tous les Arduinautes !

Voila je rencontre quelques difficultés depuis avant hier avec la fonction Serial pour faire communiquer Arduino avec un programme processing sur le port USB.
Je vous explique mon "projet". J'ai voulu découvrir le language processing et de tests en expérimentation j'en suis arrivé à coder un jeu du Pong (dont je suis plutôt content soit dit en passant 8) ).
Après ça j'ai eu la bonne idée de faire discuter le jeux du pong avec mon arduino d'une façon très simple via une LED RGB : si je joueur gagne la LED est allumé en vert, si l'ordinateur gagne la LED est éclairé en rouge et si le score est ex aequo, celle-ci est illuminé en bleu (On est d'accord ça sert à rien, d’autant plus que je jeux du Pong affiche déjà le score, mais cela me semblais être un bon entraînement XD ).

Le problème que j'ai se situe sur l'utilisation de la bibliothèque Serial, je me suis appuyé sur cet exemple pour m'aider : http://www.mon-club-elec.fr/pmwiki_mon_club_elec/pmwiki.php?n=MAIN.ArduinoExpertSerieDepuisPCSliderPWMVarieLED

Malheureusement comme vous devez vous en douter, cela ne se passe pas comme prévu :drooling_face:

Bon je vais commencer par vous partager mon code arduino et la partie de mon code processing qui gère la communication série et je vous explique juste ensuite ce qu'il se passe.

Voici pour la partie Arduino :

const int rouge = 2;
const int vert = 3;
const int bleu = 4;
int led = 3;

int octetReception = 0;
long nombreReception = 0;
long nombreReception0 = 0;
String chaineReception = "";

void setup()
{
  pinMode(rouge,OUTPUT);
  pinMode(vert,OUTPUT);
  pinMode(bleu,OUTPUT);
  
  digitalWrite(rouge, LOW);
  digitalWrite(vert, LOW);
  digitalWrite(bleu, LOW);
  
  Serial.begin(115200);
  Serial.print(octetReception);
}

void loop()
{
  if(Serial.available()==true)
  {
    led = etat();
    if (led == 1)
    {
      digitalWrite(rouge, HIGH);
      digitalWrite(vert, LOW);
      digitalWrite(bleu, LOW);
    }
    else if (led == 2)
    {
      digitalWrite(vert, HIGH);
      digitalWrite(rouge, LOW);
      digitalWrite(bleu, LOW);
    }
    else if (led == 3)
    {
      digitalWrite(bleu, HIGH);
      digitalWrite(rouge, LOW);
      digitalWrite(vert, LOW);
    }
    else
    {
      //rien
    }
  }
  else
  {
  }
}

int etat()
{
int octetRecu = 0; 
int etat = 3; //par defaut le score est de 0/0 donc LED en bleu
  
  while (Serial.available()>0)  //Tant que le port série reçoit des données
  {
    octetRecu = Serial.read();  //stock l'octet reçu dans la variable
    Serial.print(octetRecu);
    if (octetRecu == 10)    //si octetRecu corespond au saut de ligne en ASCII, on sort de la boucle while
    {
      break;
    }
    else
    {
      if(octetRecu = 97)  //97 = a en ASCII
      {
        etat = 1;
      }
      else if (octetRecu = 98)  //98 = b en ASCII
      {
        etat = 2;
      }
      else if (octetRecu = 99)  //99 = c en ASCII
      {
        etat = 3;
      }
      else
      {
        //Eh bah rien ne se passe !
      }
    }
  }
  return(etat);
}

Et le petit bout de processing qui gère la liaison série :

  import processing.serial.*;
  Serial portCom;

void setup()
{
  println(Serial.list());
  portCom = new Serial(this,Serial.list()[1],115200);
  portCom.bufferUntil('\n');
}

void led()
{
  if(changementScore == 1)
  {
    if(scoreIA > scoreJoueur)
    {
      portCom.write(str(char('a'))+"\n");
      changementScore = 0;
      println("envoie a");
    }
    else if(scoreIA < scoreJoueur)
    {
      portCom.write(str(char('b'))+"\n");
      changementScore = 0;
      println("envoie b");
    }
    else if(scoreIA == scoreJoueur)
    {
      portCom.write(str(char('c'))+"\n");
      changementScore = 0;
      println("envoie c");
    }
    else
    {
      portCom.write(str(char('c'))+"\n");
      changementScore = 0;
      println("envoie truc bizard");
    }
  }
  else
  {
    //rien
  }
}

Voila alors le code arduino s'initialise bien (la LED s'allume par défaut en bleu comme prévu) par contre rien ne se passe lorsque le score change. Suite a pas mal de test, la liaison série semble bien se faire (j'avais fait un if(Serial.available()==true) ==> faire changer la LED de couleur, et la LED change bien de couleur lorsque je lance le code processing du Pong) de plus le "Serial.print(octetRecu);" que j'ai placé dans le code arduino pour qu'il me montre un peut ce qu'il reçoit renvoi presque toujours des "ÿ" alors que je m'attendrais à voir apparaitre la lettre a, b ou c, ou peut être la valeur décimale de la table ASCII d'une de ces trois lettres ...

Je vous avoue que je me sent totalement frustré de ne pas trouvé la solution surtout vu le nombre important d'exemple de communication sur le port USB que l'on trouve sur internet. :sweat_smile:

Si quelqu'un avait une idée de ce qui pose problème, je lui en serait très reconnaissant !

PS : Je ne vous ai pas partagé le code complet de mon jeu Pong pour des histoires de visibilité du problème, mais si jamais il vous intéresse, dites le moi :open_mouth:

Cordialement

Maskim

ce qu'il reçoit renvoi presque toujours des "ÿ" alors que je m'attendrais à voir apparaitre la lettre a, b ou c,

Problème de vitesse? en même temps personnellement, j'éviterais le 115200 bauds avec un arduino. Tu devrais commencer avec une vitesse plus faible.

Code arduino

if(Serial.available()==true)

à remplacer par ça

if(Serial.available()>0)

Alors déjà " if(Serial.available()==true) " ça s'utilise pas vraiment parce que ça peut porter à confusion. Ecrit soit "if(Serial.available())" soit "if(Serial.available()>=1)".

Ensuite toujours mettre un petit delay à la réception, le temps que le buffer se remplisse. La comme y'a qu'un char je pense pas que ça changera quelque chose mais c'est une bonne habitude à prendre que de mettre un petit "delay(5);".

Ensuite c'est un peu l'usine à gaz ton code, tu utilises des fonctions qui sont pas forcement pertinente. Moi j'aurais fait :

const int rouge = 2;
const int vert = 3;
const int bleu = 4;

void setup()
{
  pinMode(rouge,OUTPUT);
  pinMode(vert,OUTPUT);
  pinMode(bleu,OUTPUT);
  
  digitalWrite(rouge, LOW);
  digitalWrite(vert, LOW);
  digitalWrite(bleu, LOW);
  
  Serial.begin(115200);
}

void loop()
{
  if(Serial.available())
  {
    char Buffer = Serial.read()
    if (Buffer == 'a')
    {
      digitalWrite(rouge, HIGH);
      digitalWrite(vert, LOW);
      digitalWrite(bleu, LOW);
    }
    if (Buffer == 'b')
    {
      digitalWrite(vert, HIGH);
      digitalWrite(rouge, LOW);
      digitalWrite(bleu, LOW);
    }
    if (Buffer == 'c') 
{
       digitalWrite(bleu, HIGH);
      digitalWrite(rouge, LOW);
      digitalWrite(vert, LOW);
    }  
    }
}

Effectivement B@tto, avec ton code, tout fonctionne parfaitement :relaxed:
J'était persuadé que l'arduino ne pouvait pas tester directement un caractère reçu sur le Serial mais que l'on était obligé de passé par la valeur ASCII du caractère.
C'est clair que à côté mon code faisait vraiment usine à gaz :0
Bon au moins je me doutait bien que le problème se situait côté Arduino et pas Processing.

En tout cas merci, tu m'auras appris une méthode bien plus simple :stuck_out_tongue_closed_eyes:

Cordialement

Maskim

B@tto:
Alors déjà " if(Serial.available()==true) " ça s'utilise pas vraiment parce que ça peut porter à confusion. Ecrit soit "if(Serial.available())" soit "if(Serial.available()>=1)".

Effectivement, ca ne peut pas marcher parce que retourne Serial.available() est le nombre de caractère dispo et non pas un booléen.

Par ailleurs dans le cas général, on évite généralement toute comparaison a TRUE.
Si le résultat d'une fonction est un boolean, on utilise la valeur de la fonction directement :

if ( toto.test() ) // retourne FALSE ou non-FALSE (~= TRUE)

Soit on compare à FALSE par égalité ou non égalite

if ( toto.test() != false )

Pourquoi ? parce que le C ne définit pas de manière unique la valeur TRUE : Toute valeur différent de FALSE (0) est TRUE !