Recevoir plusieurs données en même temps via le port série. Max/Msp à Arduino

Bonjour,
Veuillez m'excuser pour cette question déjà posé mille fois, mais je comprends pas un truc qui doit pourtant etre simple!
J'envoie 5 données en même temps via le port série de cette manière depuis Max/msp.
Puis j'envoie à la ligne suivante 5 autres données.

print: 18 99 87 28 124
print: 18 99 87 28 125

Mais dans le monitor d'Arduino j'ai

87255255255255
28255255255255
28255255255255
124255255255255

Les données vont dans var[0] mais pas dans les autres.
Pourtant j'arrive à moduler la led de l'Arduino avec var[4] qui affiche 255.

Je suis d'avance super reconnaissant pour votre aide

#define NBDATA 5

int var[NBDATA] = { 0 };

#define LED_BUILTIN 16
#define BUILTIN_LED LED_BUILTIN

 void setup() {
 pinMode (LED_BUILTIN,OUTPUT);
 Serial.begin(115200);
 SerialUSB.begin(115200);
}

void dataFromMaxToManageInArduino() {
  //byte rc;
    char rc;
    
   if (Serial.available() > 0){
    if ((rc != 10 && rc != 13))
    {
   
    for(uint8_t i = 0; i < 5; i++)
    {
       rc = Serial.read();
       var[i] = rc; // Integer   
   
    }
    }
 }
}
   
void loop() {
dataFromMaxToManageInArduino();
SerialUSB.print(var[0]);
SerialUSB.print(var[1]);
SerialUSB.print(var[2]);
SerialUSB.print(var[3]);
SerialUSB.println(var[4]);digitalWrite(LED_BUILTIN,var[4]);
}

Lorsque tu fais le test, rc est indéfini.

Tu fais 5 Serial.read() sans t'assurer que tu as des caractères en attente.
et si tu regardes la doc de Serial.read() tu liras que read() retourne -1 lorsqu'il n'y a pas de caractère à lire et -1 dans un char c'est 0xFF qui s'affiche 255 avec print().

Merci,
Donc j'envoie 5 ints avec un espace intercalé.
Pour éviter les espacerai changé la loop comme ça

void dataFromMaxToManageInArduino() {
  //byte rc;
  //char rc;
  int rc;
    
  if (Serial.available() > 0){
  // if ((rc != 10 && rc != 13 && rc != 1 ))
   if ((rc != 10 || rc != 13 || rc != 1 ))
   {   
     for(uint8_t i = 0; i < 5; i++)
     {
       rc = Serial.read();
       var[i] = rc; // Integer   
     }   
   }
  }
}

Maintenant j'ai ça

50-1-1-1-1

et si je remets char rc au lieu de int rc

j'ai

50255255255255

Le but est de pouvoir lire des valeurs qui iront au delà de 65000, donc j'aurai besoin de lire des int32, car 16 int c'est limité à 65536 . C'est bien ça?

la ligne de code semble les envoyer en même temps, mais en réalité chaque bit de chaque représentation de vos nombre

côté réception ils arrivent petit à petit donc comme le dit @fdufnews vous devez attendre d'avoir reçu un octet pour le lire (ou attendre d'en avoir 5 dans le buffer de réception si vous voulez en lire 5 d'un coup).

Si vous voulez explorer comment écouter le port série (ou gérer un flux asynchrone genre keypad) vous pouvez jeter un oeil à mon petit tuto sur le sujet

êtes vous sûr que c'est ce que fait print: 18 99 87 28 124 ??

A ce qu'on voit sur le monitor de max/msp, oui
Mais en effet ça peut etre un problème venant de max/msp. Surtout que j'ai déjà réussi à recevoir les données séparément!
J'ai déjà réussi à en recevoir depuis Processing aussi, et je suis quasi certain que le programme d'Arduino était aussi simple que celui que j'ai posté.

J'ai voulu voir ce que reçoit Arduino. Résultat :

Quelque soit la donnée modulée de 0 à 255 depuis Max/msp, var[0] est modulé par cette donnée.

Quand je module une des 5 données dans max/msp voilà ce que le moniteur de Arduino affiche

20:08:30.821 -> 95 255 255 255 255
20:08:30.821 ->  s 1
20:08:30.821 -> 87 255 255 255 255
20:08:30.821 ->  s 1
20:08:30.821 -> 171 255 255 255 255
20:08:30.821 ->  s 1
20:08:30.821 -> 173 255 255 255 255
20:08:30.821 ->  s 1

le code

void dataFromMaxToManageInArduino() {
  //byte rc;
  char rc;
  //int rc;
    
  if (Serial.available() > 0){
   SerialUSB.print(" s "); SerialUSB.println (Serial.available());
   if ((rc != 10 && rc != 13 && rc != 1 ))
   {   
     for(uint8_t i = 0; i < 5; i++)
     {
       rc = Serial.read();
       var[i] = rc; // Integer   
     }   
   }
  }
}

Même remarques que précédemment, tu es un peu borné.

  • rc ne contient aucune valeur au moment du test. Tu testes le contenu de la variable rc alors que ne lui affectes une valeur qu'au moment du Serial.read().
  • si tu ne fais pas un if Serial.available () AVANT CHAQUE Serial.read() tu ne sais pas si tu as un caractère à lire.
    Et c'est ce que tu affiches d'ailleurs

Available() te dit qu'il y a 1 caractères dans le buffer et tu essaies d'en lire 5

Bonjour,
Merci de m'aider.
J'essaye de comprendre mais j'ai un décalage dans mais données.
J'envoie ceci

print: 185 14 13 40 103

et je reçois 5 données bien séparées mais avec des données erratiques.

103 13 103 40 185
 testA 0
  testA 1
  testA 2
  testA 3
  testA 4
 
103 13 103 40 185
 testA 0
  testB 2
�
 testA 1
  testB 1

 testA 2
  testB 1


 testA 3
  testA 4
  testB 1

donnez nous TOUT le code de réception svp

quand vous affichez 255 ça veut dire que le read() à retourné -1 (0xFFFF) ce qui arrive quand on essaye de lire le buffer et qu'il est vide — puis vous l'avez tronqué et il est devenu 0xFF, affiché en 255.

C'est moi ou il y a des espaces entre les nombres lorsque tu les envoies?

//int rc = 0; // for incoming serial data
//byte rc;// = 0;
char rc;// = 0; // for incoming serial data

#define NBDATA 5
int var[NBDATA] = { 0, 0, 0, 0, 0 };
#define LED_BUILTIN 16
#define BUILTIN_LED LED_BUILTIN

 void setup() {
 pinMode (LED_BUILTIN,OUTPUT);
 Serial.begin(115200);
 SerialUSB.begin(115200);
}

void dataFromMaxToManageInArduino()
{
    for(uint8_t i = 0; i < 5; I++)
    {

       SerialUSB.print(" testA "); SerialUSB.println(i); SerialUSB.print(" ");
      
      if (Serial.available() > 0 ) //  SerialUSB.println("");
      {
     //  if ((rc != 10 && rc != 13))
         if ((rc != 1))
        {   
       SerialUSB.print(" testB "); SerialUSB.println(Serial.available() );     
       rc = Serial.read();  SerialUSB.println(rc); 
       var[i]=rc; 
        }
      } 
    } 
      SerialUSB.println(""); //Serial.println("");       
}        
   
void loop() {
dataFromMaxToManageInArduino();
SerialUSB.print(var[0]); SerialUSB.print(" ");
SerialUSB.print(var[1]); SerialUSB.print(" ");
SerialUSB.print(var[2]); SerialUSB.print(" ");
SerialUSB.print(var[3]); SerialUSB.print(" ");
SerialUSB.println(var[4]);
digitalWrite(LED_BUILTIN,var[4]);

}

oui on dirait qu'il y en a dans le format
image

oui, j'envoie des espaces entre les nombres

commencez simplement:

faites ceci dans le code de l'arduino et dites nous ce que vous voyez dans le terminal série

void setup() {
  Serial.begin(115200);
  SerialUSB.begin(115200);
}

void loop() {
  if (Serial.available() > 0) SerialUSB.write(Serial.read());
}

on saura déjà si c'est de l'ASCII qui est bien envoyé et auquel cas il faudra analyser le buffer (qui fera plus de 5 octets) pour extraire les 5 entiers.

voilà ce que je reçois quand je module une à une chaque variable

<aDax>aDax@aDaxBaDaxDaDaxFaDaxFSDaxFUDaxFWDaxFYDaxF[DaxF]DaxF_DaxFaDaxFcDaxFcDaxFeDaxFeKaxFeSaxFeUaxFeWaxFeYaxFeYaxFeYWxFeYaxFeYcxFeYexFeYixFeYixFeYmxFeYoxFeYqxFeYsxFeYsxFeYuxFeYuvFeYu~FeYu�FeYu�FeYu�FeYu�FeYu�FeYu�FeYu�FeYu�

OK vous voyez que ce qui est réellement envoyé est donc beaucoup plus complexe que ce que vous imaginiez...

essayez à nouveau avec ce code:

void setup() {
  Serial.begin(115200);
  SerialUSB.begin(115200);
}

void loop() {
  if (Serial.available() > 0) {
    byte data = Serial.read();
    SerialUSB.print("0x");
    if (data < 0x10) SerialUSB.write('0');
    SerialUSB.print(data, HEX);
    SerialUSB.write('\t');
    if (isprint(data)) SerialUSB.write((char) data);
    else SerialUSB.write('?');
    SerialUSB.println();
  }
}

je ne connais pas MAX mais êtes vous sûr que donner à sprintf les données en pak
image
est ce qui est attendu ?
ne devriez vous pas connecter directement chacune des sources à un des %ld (et vous assurer que le format émis par les sources est bien un entier)

En branchant les cables sur Max/Msp selon la seconde version, Arduino m'affiche des données seulement quand je module le premier curseur de gauche.
Alors qu'avec l'ancien câblage j'avais des données quelque soit le curseur.

J'ai essaye le second câblage avec mon programme Arduino precedent, celui du post #11, et la DEL est modulé seulement quand je bouge le premier curseur. Ce qui est cohérent!! :wink:

Par contre les données s'affichent toujours erratiquement, peu importe le câblage :frowning:

Voici les données affichées avec votre dernier programme et le second câblage. Les données s'affichent en bougeant le premier curseur uniquement. Alors que rien ne programme la DEL build-in, la DEL clignote aussi quand je bouge ce curseur uniquement!! :thinking:

11:44:06.042 -> 0x83	?
11:44:06.042 -> 0x56	V
11:44:06.042 -> 0x81	?
11:44:06.042 -> 0x4D	M
11:44:06.042 -> 0x4E	N
11:44:06.042 -> 0x91	?
11:44:06.042 -> 0x56	V
11:44:06.042 -> 0x81	?
11:44:06.042 -> 0x4D	M
11:44:06.042 -> 0x4E	N
11:44:06.075 -> 0xA1	?
11:44:06.075 -> 0x56	V
11:44:06.075 -> 0x81	?

et voici les données avec le premier câblage, qui s'affichent dès que je module un des 5 curseurs ! Aussi la LED clignote dès que je module un des 5 curseurs !

11:45:51.869 -> 0x4B	K
11:45:51.869 -> 0x73	s
11:45:51.869 -> 0x4F	O
11:45:51.869 -> 0xD8	?
11:45:51.869 -> 0x6D	m
11:45:51.869 -> 0x4B	K
11:45:51.869 -> 0x73	s
11:45:51.869 -> 0x4F	O
11:45:51.869 -> 0xD8	?
11:45:51.869 -> 0x6F	o
11:45:51.869 -> 0x4B	K
11:45:51.869 -> 0x73	s
11:45:51.869 -> 0x4F	O

je ne connais pas Max/Msp donc je ne sais pas si la fonction sprintf est capable de prendre ses paramètres dans une liste.

pourriez vous donner ce que vous voyez dans la console Max/Msp en même temps que mon dernier code puisqu'on dirait que vous faites aussi un print de la sortie du sprintf ?

image

avez vous donné l'intégralité de ce qui s'affiche dès que vous touchez le curseur ?

Quand je bouge le premier curseur à deux endroit different Max/Msp print

print: 72 72 72 80 97
print: 128 72 72 80 97

et le moniteur d'arduino

0x48	H
0x48	H
0x48	H
0x50	P
0x61	a
0x80	?
0x48	H
0x48	H
0x50	P
0x61	a

OK c'est un peu plus cohérent: 72 72 72 80 97 en décimal, c'est pareil que 0x48 0x48 0x48 0x50 0x61 en Hexa ➜ donc les valeurs sont émises non pas en ASCII mais en binaire, sur un octet et ensuite on reçoit 0x80 qui doit être un séparateur de fin de ligne.
ça ne correspond pas au fonctionnement typique de sprintf()....

et ce qui est bizarre c'est que la même chose est émise si vous allez à 2 endroits différents ➜ votre print est louche

Essayez ce code (qui est fragile car pas de point de synchro) qui permet de tester la réception

const byte tailleMessage = 5;
byte valeurs[tailleMessage + 1];

bool messageRecu() {
  static byte indice = 0;
  bool messagePret = false;
  if (Serial.available() > 0) {
    valeurs[indice++] = Serial.read();
    if (indice == tailleMessage) {
      indice = 0;
      messagePret = (valeurs[tailleMessage] == 0x80); // on vérifie qu'on a reçu le séparateur
    }
  }
  return messagePret;
}

void setup() {
  Serial.begin(115200);
  SerialUSB.begin(115200);
}

void loop() {
  if (messageRecu()) {
    SerialUSB.print("Message : ");
    for (byte i = 0; i < tailleMessage; i++) {
      SerialUSB.print(valeurs[i]);
      SerialUSB.write(' ');
    }
  }
}