Problème liaison série

bonjour j'ai un gros souci avec la liaison série j'essaye d'envoyer plusieurs valeurs comme ceci: (et plusieurs autres par la suite)

///////////////////////FONCTION JOYSTICK//////////////////////
int x = analogRead(A0);
int y = analogRead(A1);
int acc = analogRead(A2);

 Serial.print(x);
  Serial.print(",");
 Serial.print(y);
  Serial.print(",");
 Serial.print(acc);
 Serial.print(",");
 Serial.println();

et je les réceptionne sur un autre arduino avec ce code :

const int NoF = 3;
int fieldIndex = 0;  //Pointer for the array contents
int val[NoF];

//////////////////////////////////////////////////
if(Serial.available()) 
  {
    
    for(fieldIndex = 0; fieldIndex < 3; fieldIndex ++)
    {
      val[fieldIndex]=Serial.parseInt();     
      
    }

j'ai aussi sur le premier arduino des bouton qui "print" les valeurs sur différent ports série via serial1,serial2...

le souci est que quand je bouge le joystick ou que je change de port série les valeur dans le moniteur de l'arduino esclave se mélangent : genre x est lu en premier puis tout à-coup il passe en 2eme ou 3eme du coup les valeurs récupéré dans mon tableau c'est du n'importe quoi je ne peut pas trier ces valeur car elles changent de place constamment
aurai 'je raté un truc? la je passe par sofwareserial mais même en direct (rx/tx) même problème

parsint() s’arrête au premier caractère non numérique sans distinction. Donc si tu démarres mal synchronisé tu seras toujours désynchronisé.
Il faut lire la chaine jusqu'au line feed \n puis analyser la chaine.

Bonjour,

Comme dit kamill, il vaut mieux lire la chaine entière puis analyser, avec strtod, strtok, sscanf, ou autre...

Quelque chose comme ça

void loop()
{
  while ( mySerial.available() > 0 )
  {
    static char input[64];
    static uint8_t i = 0;

    char c = mySerial.read();

    if ( c != '\n' && i < 64 - 1 )
    {
      input[ i++ ] = c;
    }
    else
    {
      input[ i ] = '\0';
      i = 0;
      
      Serial.print( "Commande recue: " );
      Serial.println( input );
      
      if ( sscanf( input, "%d,%d,%d", &val[0], &val[1], &val[2] ) == 3 )
      {
        Serial.print( "x = " );
        Serial.print(val[0]);
        Serial.print( " y = " );
        Serial.print(val[1]);
        Serial.print( " acc = " );
        Serial.println(val[2]);
      }
    }
  }
}

merci ca marche entre temp j'ai trouvé une solution qui fonctionne aussi mais moins propre

String variableRecue = Serial.readStringUntil('\n');

//Serial.println(variableRecue);
int PX = variableRecue.indexOf(" ");
int TY = variableRecue.indexOf(" ");
int AC = variableRecue.indexOf(" ");
int ME = variableRecue.indexOf(" ");

String PX1 = variableRecue.substring(0, PX); // Depuis le début jusqu'au séparateur
String TY1 = variableRecue.substring(0, TY);
String AC1 = variableRecue.substring(0, AC);
String ME1 = variableRecue.substring(0, ME);

String PX2 = variableRecue.substring(PX+1);  // Depuis après le séparateur
String TY2 = variableRecue.substring(TY+1);  // Depuis après le séparateur
String AC2 = variableRecue.substring(AC+1);  // Depuis après le séparateur
String ME2 = variableRecue.substring(ME+1);  // Depuis après le séparateur



int PX3 = PX2.toInt();
int TY3 = TY2.toInt();
int AC3 = AC2.toInt();
int ME3 = ME2.toInt();


if (PX1 == "pan"){
   pan2 = PX3;
 
}
if (TY1 == "tilt"){
   tilt2 = PX3;
    
}
if (AC1 == "acc"){
   acc2 = PX3; 
  
}
if (ME1 == "mem"){
   memflag = ME3; 
  
}

La propreté n'est pas le problème, mais l'utilisation de String risque d'en poser un, qui s'appelle la fragmentation mémoire (à moins qu'il ne s'agisse d'un ESP8266 ou ESP32).
La solution de guix à base de sscanf() est plus sûre.

Non seulement c'est moins propre mais ça ne décode absolument pas le message qui est envoyé au post #1.
De plus ici:

PX, TY AC et ME ont la même valeur. Ça sert à quoi?

oui desolé j'ai aussi changé le message pour

int x = analogRead(A0);
int y = analogRead(A1);
int acc = analogRead(A2);
 mySerial1.print("pan ");
 mySerial1.print(x);
 mySerial1.print("\n");
  mySerial1.print("tilt ");
 mySerial1.print(y);
 mySerial1.print("\n");
  mySerial1.print("acc ");
 mySerial1.print(acc);
 mySerial1.print("\n");
 mySerial1.print("mem ");
 mySerial1.print(memflag);
 mySerial1.print("\n");

mais je vais plancher sur la solution de guix
le souci est que je ne comprend pas bien ce que le code fait exactement même si ca marche (sscanf ???)
il faut que j'apprenne quoi sert a quoi

une petite question :
au niveau de l'envoi je peut envoyer une syntaxe comme celle ci ?

int x = analogRead(A0);
int y = analogRead(A1);
int acc = analogRead(A2);
 mySerial1.print("pan ");
 mySerial1.print(x);
 mySerial1.print("\n");
  mySerial1.print("tilt ");
 mySerial1.print(y);
 mySerial1.print("\n");
  mySerial1.print("acc ");
 mySerial1.print(acc);
 mySerial1.print("\n");
 mySerial1.print("mem ");
 mySerial1.print(memflag);
 mySerial1.print("\n");

Oui, mais c'est moins efficace que ta première version.

ok mais avec la première version tout se mélangeait a l'arrivée le code de guix saura quand même faire le tri ?

Oui (sauf peut être pour le premier message reçu).

d'accord le problème est que je commande des têtes motorisée et que je change de canal série pour changer de tète donc si le premier message est erroné cela risque de faire bouger la tête
du coup peut être utiliser un message plus lourd mais plus fiable serais plus judicieux

Ca peut être traité par une analyse plus fine du message, mais c'est plus compliqué que le programme de guix
Ou tu peux rejeter le premier message.
Tu peux aussi mettre un caractère d'en tête pour t'assurer que le message reçu est bien entier.

genre
x1024
y512
...
?
avec x et 1024 dans le même "print"?
ou alors comme j'avais fait ?

mySerial1.print("X ");
 mySerial1.print(x);
 mySerial1.print("\n");

Genre S123,256,789\n

ha ok j'ai compris ben je vais tester ca
merci

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