Arduino Forum

Forum 2005-2010 (read only) => International => Français => Topic started by: jfs on Mar 15, 2009, 01:17 pm

Title: communication série entre deux Arduino
Post by: jfs on Mar 15, 2009, 01:17 pm
J'ai branché deux plaques Arduino par les pins rx-tx, en croisant les fils, les deux sont sur le même Gnd.

la première plaque m'envoit :

Code: [Select]

...
Serial.print ("   time ");
 Serial.print (millis(),DEC);
 Serial.print ("   rpm ");
 Serial.print(rpm,DEC);
 Serial.print ("   pos ");
 Serial.print (encoderpos,DEC);
 Serial.print ("   index ");
 Serial.print (index,DEC);
 Serial.println ("\0");
...



Et la deuxième a ce code:

Code: [Select]
int incomingByte ;      
char myStr[100];


void setup() {
     Serial.begin(38400);
}

void loop() {

     Serial.print("I received: ");
     while (Serial.available() > 0) {
           
for (int i = 0; i < sizeof(myStr) - 1; i++)
{
 incomingByte = Serial.read();
  myStr[i]=incomingByte;
  Serial.print(myStr[i]);
}
}
}



Ensuite j'envoie les valeurs sur le serial monitor.
Les valeurs s'affichent correctement comme ce qui sort de la première plaque, la mention "I received: " ne s'affiche qu'une fois, ce qui indique que je suis enfermé dans la boucle While et que même avec le '\0' je n'en sort pas...

Ce qui me préocuppe pour le moment c'est que je n'arrive pas à récupérer les données du flux reçu afin de les convertir en variable exploitable.

J'aimerais par exemple pouvoir utiliser la valeur des t/min mais je n'arrive pas à séparer cette valeur du reste du flux.
En plus comme les valeurs varient et passent d'unités à dizaines, centaines, ça ne facilite pas.

J'ai essayé plusieurs choses différentes (que je ne poste pas car c'est totalement inexploitable).
Title: Re: communication série entre deux Arduino
Post by: Vincent on Mar 15, 2009, 01:50 pm
Le problème je pense c'est que la liaison USB utilise déjà la liaison série de l'Arduino, du coup l'utiliser pour communiquer avec l'ordi et avec une autre Arduino ça doit pas le faire
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 15, 2009, 01:55 pm
Si,si, ça fonctionne (du moins dans ce cas), ce qui est affiché est exactement similaire si je suis directement sur celle qui lit la roue codeuse ou si j'ai la deuxième plaque en intermédiaire.
Mon problème réside surtout dans le fait que je ne sais pas  comment convertir le flux (string ?) en un valeur ( int, long..) exploitable.

Pour l'instant ça ne fait qu'aligner les bytes tels quels, j'aimerais pouvoir les remettre dans la même configuration qu'avant l'envoi.
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 17, 2009, 12:05 am
Dans mes essais actuels j'essaye de séparer les valeurs qui m'intéresse en les envoyant entre des balises.
Par exemple, la valeur "time" envoyée par Arduino-1 est précédée par 'T' et suivie de 'U'.

Je pensais la séparer du reste en utilisant un code comme cela :

Code: [Select]

char time;
char value;

void setup() {
 Serial.begin(38400);
}

void loop() {

 while (Serial.available() > 0) {
   
   value = Serial.read();
   
   if (value =='T'){
     while (value !='U'){
       value = Serial.read();
       time = value;
       if (value !='U'){
       Serial.print(time);
       }
     }
     Serial.println();
   }
 }
}




Pour ensuite mettre la valeur "time" dans un tableau dont j'additionnerais les "cases" en le lisant depuis la fin en multipliant par 1000, 100, 10 suivant la position du chiffre dans la valeur affichée à la fin.

Pour l'instant j'ai bien la valeur "time" qui s'affiche selon la progression de millis(), mais les chiffres sont précédés de trois " ÿ " comme cela :

Code: [Select]
ÿÿÿ641735
ÿÿÿ641752
ÿÿÿ641769
ÿÿÿ641786
ÿÿÿ641804
ÿÿÿ641821
ÿÿÿ641838
ÿÿÿ641855

Je n'arrive pas à trouver d'où ils viennent.
Title: Re: communication série entre deux Arduino
Post by: julien@pobot.org on Mar 17, 2009, 10:57 am
C'est ton println peut-être (caractère \r ou \n).
Mais je connais bien ce caractère (ÿ), je le vois souvent passer dans mes logs série, je me demande si c'est pas plutôt 0xFF
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 17, 2009, 08:04 pm
Voila le code que j'essaye actuellement sur l'Arduino-2 :

Code: [Select]
char value;
int a=0;
int b=0;
int c=0;
long time=0;
char t[15];


void setup() {
 Serial.begin(38400);
}

void loop() {

 while (Serial.available() > 0) {

   value = Serial.read();

   if (value =='T'){
     a=0;
     while (value !='U'){
       value = Serial.read();

       if (value !='U'){
         t[a]=value;
         Serial.print(value);
         
       }
         a++;
         b=a;
         c=a;
     }
     a=0;
     while(a < c){

       switch (b){

       case 8:
         time=+(t[a]*100000000);
       case 7:
         time=+(t[a]*10000000);
       case 6:
         time=+(t[a]*1000000);
       case 5:
         time=+(t[a]*100000);
       case 4:
         time=+(t[a]*10000);
       case 3:
         time=+(t[a]*1000);
       case 2:
         time=+(t[a]*100);
       case 1:
         time=+(t[a]*10);
       case 0:
         time=+(t[a]*1);
       }
       b--;
       a++;
     }
     Serial.print(" time   ");
     Serial.print(time);
     Serial.print(" time fin  ");
     Serial.println("stop");
     time=0;
   }
 }
}


Pour l'instant ça ne marche pas alors si quelqu'un a une correction a amener  ::)
Title: Re: communication série entre deux Arduino
Post by: Vincent on Mar 17, 2009, 10:38 pm
J'ai remarqué une choses mais ça ne change pas le fonctionnement :

Code: [Select]
char value;
int a=0;
int b=0;
int c=0;
long time=0;
char t[15];


void setup() {
 Serial.begin(38400);
}

void loop() {

 while (Serial.available() > 0) {

   value = Serial.read();

   if (value =='T'){
     a=0;
     while (value !='U'){
       value = Serial.read();

       if (value !='U'){   // pourquoi mettre un if ? si le while est vrai le if aussi
         t[a]=value;
         Serial.print(value);
         
       }
         a++;
         b=a;
         c=a;
     }
     a=0;
     while(a < c){

       switch (b){

       case 8:
         time=+(t[a]*100000000);
       case 7:
         time=+(t[a]*10000000);
       case 6:
         time=+(t[a]*1000000);
       case 5:
         time=+(t[a]*100000);
       case 4:
         time=+(t[a]*10000);
       case 3:
         time=+(t[a]*1000);
       case 2:
         time=+(t[a]*100);
       case 1:
         time=+(t[a]*10);
       case 0:
         time=+(t[a]*1);
       }
       b--;
       a++;
     }
     Serial.print(" time   ");
     Serial.print(time);
     Serial.print(" time fin  ");
     Serial.println("stop");
     time=0;
   }
 }
}


Par contre j'ai pas la longueur des long en tête mais est-ce que ça passe quand b = 8 ?
Sinon où est-ce que ça bloque plus précisément ?
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 18, 2009, 07:20 am
Effectivement ça dépasse la capacité des long, mais normalement ça ne devrait jamais arriver jusqu'à la position 8.


J'ai un truc comme ça qui s'affiche en console :


Code: [Select]

ÿÿÿ538 time   50 time fin  stop
ÿÿÿ555 time   50 time fin  stop
ÿÿÿ571 time   50 time fin  stop
ÿÿÿ587 time   50 time fin  stop
ÿÿÿ604 time   50 time fin  stop
ÿÿÿ620 time   50 time fin  stop
ÿÿÿ636 time   50 time fin  stop
ÿÿÿ653 time   50 time fin  stop
ÿÿÿ669 time   50 time fin  stop
ÿÿÿ685 time   50 time fin  stop
ÿÿÿ701 time   50 time fin  stop



Si je ne Reset pas la carte 1 la valeur time reste à 0.
Title: Re: communication série entre deux Arduino
Post by: julien@pobot.org on Mar 18, 2009, 08:08 am
Le if est nécessaire car entre le while et le if, la valeur a été changée par un nouveau read.

C'est normal que tu aies le yyy538 en début de ligne : comme tu écoutes "en espion" (j'ai oublié le terme exact) la ligne série, tu vois à la fois ce que la carte reçois et ce qu'elle envoie).
Title: Re: communication série entre deux Arduino
Post by: Vincent on Mar 18, 2009, 08:44 am
C'est vrai, j'avais pas fait attention à la nouvelle lecture
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 18, 2009, 12:06 pm
Le if est nécessaire, sinon le U s'affiche après la valeur "time".

En fait le 538 est normal, vu que j'affiche value aprés chaque première lecture, les y sont moins "normaux"  ;D.

Le problème que j'ai c'est qu'entre "time" et "time fin", le 50 devrait être ma valeur 538 (et suite) qui s'affiche, mais dans une seule variable.
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 18, 2009, 01:18 pm
J'ai trouvé une erreur, les Compound Operators sont inversé:

Code: [Select]
     ...
          case 8:
         time=+(t[a]*100000000); // le + et = sont à inverser
       case 7:
         time=+(t[a]*10000000);  //idem
       ...



il faut corriger par :

Code: [Select]
     ...
          case 8:
         time+=(t[a]*100000000); // le + et = étaient à inverser
       case 7:
         time+=(t[a]*10000000);  //idem
       ...
Title: Re: communication série entre deux Arduino
Post by: julien@pobot.org on Mar 18, 2009, 02:16 pm
Regarde du côté des décalages, ce serait plus pratique que tes multiplications.

Voici comment on envoit un entier (2 octets sur Arduino) sur la liaison série :

Code: [Select]

Serial.print(0xff, BYTE);
Serial.print( (val >> 8) & 0xff, BYTE);
Serial.print( val & 0xff, BYTE);


Et voici comment on le récupère :

Code: [Select]

while (Serial.available() >= 3) {
   if (Serial.read() == 0xff) { // le premier octet, équivalent à ton T
     val = (Serial.read() << 8) | (Serial.read());
   }
 }
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 18, 2009, 07:27 pm
Je viens de faire un essai avec tes deux bouts de code....  :D
Je me cassais les c....les pour pas grand chose...

J'ai pas tout compris  ::), j'ai trouvé que << sert a décaler les bits, mais ça reste compliqué à comprendre pour moi.

Serait-il possible de commenter ce que ça fait (les deux séquences complètes), j'aimerais vraiment comprendre ça.

Est-ce possible de faire la même chose pour un long ?
Il faut juste me répondre par oui-non, car si c'est faisable j'aimerais trouver par moi-même si les premiers code me sont expliqués.   ;)
Title: Re: communication série entre deux Arduino
Post by: julien@pobot.org on Mar 18, 2009, 08:59 pm
Si on doit envoyer par exemple 867, qui vaut en hexadecimal 0x0363

Code: [Select]

int val = 0x0363;
Serial.print(0xff, BYTE); // la valeur envoyée est 0xFF
Serial.print((val >> 8) & 0xFF, BYTE); // la valeur envoyée est 0x03
Serial.print(val & 0xFF, BYTE); // la valeur envoyée est 0x63


Devine quelle valeur on aura avec (val >> 4)


Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 18, 2009, 09:29 pm
0xD ?
Title: Re: communication série entre deux Arduino
Post by: julien@pobot.org on Mar 19, 2009, 12:29 am
Non, 0x36.

0x363 vaut en binaire 0000 0011 0110 0011
donc un décalage vers la droite (>>) de 4 va donner le binaire suivant : 0000 0011 0110 soit 0x036.

(Parenthèse, pour décoder une trame ASCII en nombre, plutôt que de passer par des multiplications par 1 000 000, il vaut mieux multiplier par 10. j'ai fait un petit exemple : http://www.pobot.org/Interface-ligne-de-commande-pour.html)




Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 19, 2009, 07:28 am
Ah! oui effectivement,j'ai pas fait mon décalage comme ça.. là je comprends mieux.

Pour le 0xFF pourquoi est'il dans trois lignes et à quoi sert le & dans les deux dernières ?


(Intéressant ton article).
Title: Re: communication série entre deux Arduino
Post by: julien@pobot.org on Mar 19, 2009, 01:27 pm
La première ligne, il a le même rôle que ton 'T', il est là pour identifier le début d'une trame (3 octets, le premier FF est non significatif).

Pour la présence du FF dans les deux lignes suivantes, je ne sais pas vraiment, c'est une habitude que j'ai vu.

EDIT : j'ai les réponses d'un des membres de Pobot

Quote

> Serial.print( (val >> 8) & 0xff, BYTE);

Cela sert à être certain d'avoir un résultat après décalage sur un byte au cas où val ait été déclaré signé et que le bit de signe soit propagé par le shift.

> Serial.print( val & 0xff, BYTE);

Cela sert à être certain d'avoir un résultat après décalage sur un byte.

En principe ça ne semble pas indispensable puisqu'on spécifie à print() que la donnée est sur un byte. Mais ça ne mange pas de pain au cas où on utilise autre chose comme fonction et qu'on oublie de forcer la taille de la donnée envoyée.
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 20, 2009, 11:06 pm
Merci pour ces précisions.

Est-ce possible d'envoyer un "long" par la même méthode (4 octets) ?
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 21, 2009, 03:34 pm
J'ai fait quelques essais.

Sur la carte Rx :

Code: [Select]
long val = 0x74CBB1;

Serial.print(0xff, BYTE); // la valeur envoyée est 0xFF
Serial.print((val >> 24) & 0xFF, BYTE); // la valeur envoyée est 0x0
Serial.print((val >> 16) & 0xFF, BYTE); // la valeur envoyée est 0x74
Serial.print((val >> 8) & 0xFF, BYTE); // la valeur envoyée est 0xCB
Serial.print(val & 0xFF, BYTE); // la valeur envoyée est 0xB1


Si je remplace BYTE par HEX, sur le moniteur série j'ai FF074CBB1, donc jusque là ça va.

Sur la carte Tx, je pensais qu'avec ce code j'arriverais à récupérer mes valeurs :

Code: [Select]
while (Serial.available() >= 5) {  //  5 = 1 octet pour FF + 4 octets
   if (Serial.read() == 0xff) { // le premier octet, équivalent à ton T
val = ((Serial.read() << 24) |(Serial.read() << 16))|((Serial.read() << 8) |(Serial.read()));

Serial.println(val,DEC);
 
       


mais cela ne fonctionne pas, la valeur retournée est -19969.

Pour voir ce que j'avais dans le flux, j'ai essayé de faire :

Code: [Select]
Serial.println(serial.read(),HEX)

Les 100 premières lignes j'ai :

Code: [Select]
FF
74
CB
B1
FF
74
CB
B1
FF
74
CB


Et ensuite je n'ai plus qu'une valeur qui est retournée :

Code: [Select]

CB
CB
CB
CB
CB
CB
CB
CB
CB
CB
CB
CB

Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 22, 2009, 12:22 am
Si j'utilise directement le Serial.read avec les bitwises , ça ne fonctionne pas, par contre en faisant comme cela, ça marche  :D :

Code: [Select]
void loop()
{
while (Serial.available() >= 5) {
   if (Serial.read() == 0xff) {
val = Serial.read();
val2 = Serial.read();
val3 = Serial.read();
val4 = Serial.read();

Serial.flush();

valeur=((val4<<24)|(val3<<16)|(val2<<8)|(val));

 Serial.println(valeur);
       
   }
 }
}


Depuis la carte Rx j'envoie 987654321 et en lisant la carte Tx avec le moniteur la variable "valeur" affiche 987654321.
Si je fais "valeur+10" j'ai 987654331.  :)

Par contre si quelqu'un a un tuyaux pour raccourcir tout ça  ;).
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 22, 2009, 10:12 am
Je viens de remarquer quelques chose, si j'envoie un nombre avec une série de F comme 7FAFFAF, la lecture n'est pas juste à chaque fois, je pense qu'il prend le FF du milieu comme balise de départ.

Comment remédier à ce problème ?
Title: Re: communication série entre deux Arduino
Post by: julien@pobot.org on Mar 22, 2009, 09:47 pm
utilise deux caractères comme séquence de départ.
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 22, 2009, 10:12 pm
Ce que je voulais dire c'est que j'envoie d'abord FF et ensuite mon nombre.
Title: Re: communication série entre deux Arduino
Post by: julien@pobot.org on Mar 23, 2009, 04:27 pm
Oui, pas de problème. Normalement il n'y a pas de raison qu'il perde des caractères, mais si c'est le cas, il ne fera pas de distinction entre le FF du début et le FF en plein milieu.

Donc si j'ai bien compris, tu peux envoyer ceci :

FF 01 FF 32 1E
FF 04 23 60 AD
FF 03 C6 FF F3

mais si le premier octet n'est pas passé, il va jeter le 01 et tu vas te retrouver avec

FF 32 1E FF 04 --> faux
23 60 AD --> supprimé
FF 03 C6 FF F3 --> récupéré par chance

Il y a deux solutions :

- allonger la chaine de reconnaissance et diminuer la probabilité de retrouver cette même séquence : soit FF FF, soit FA FA ou tout autre chaine selon les valeurs que tu envoie

- utiliser un "CRC", une formule de vérification qui t'oblige à envoyer une valeur supplémentaire, et à faire un calcul sur les octets reçus puis comparer et ainsi vérifier que c'est toujours correct.
Title: Re: communication série entre deux Arduino
Post by: jfs on Mar 23, 2009, 05:14 pm
Tu as bien cerné le problème, c'est exactement ça.

Un contrôle de redondance cyclique serait bien, mais plus complexe à mettre en place.