Go Down

Topic: Découper une trame (Read 685 times) previous topic - next topic

meerya

Nov 22, 2020, 05:44 pm Last Edit: Nov 22, 2020, 08:47 pm by meerya
Bonjour,

Je suis actuellement en train d'écrire un programme qui me permet de découper une trame pour en extraire les différentes informations.
La trame est reçue par le port série de l'Arduino, sous la forme : <AAAA,BB.BB,CCCC,DDDD,EEEE,FFF.F,GGG.G,HHH.H,III.I,JJJ.J,KKK.K,LLL.L,QQ,RR,SSSSSSSSS>
Elle ne comporte que des chiffes (entiers et flottant), chaque nombre est séparé d'une virgule. Enfin, la trame commence toujours par "<" et termine par ">".

J'ai tant bien que mal essayé de faire un bout de code mais ce n'est pas du tout concluant :
Code: [Select]
String trame = "<AAAA,BB.BB,CCCC,DDDD,EEEE,FFF.F,GGG.G,HHH.H,III.I,JJJ.J,KKK.K,LLL.L,QQ,RR,SSSSSSSSS>";
String tableau[100];

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

void loop()
{
  if (Serial.available() > 0)
  {
    for (int i = 0; i < 19; i++) {
      tableau [i] = Serial.readStringUntil(",");
    }
    Serial.println(tableau[i]);
  }
}


Mon but est de mettre chaque valeurs dans un tableau pour les exploiter par la suite.
Exemple : tableau[1] = AAAA; tableau[2] = BB.BB ...

Merci à ceux qui voudront bien m'aider.

TheMemberFormerlyKnownAsAWOL

Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

meerya

#2
Nov 22, 2020, 06:17 pm Last Edit: Nov 22, 2020, 08:49 pm by meerya
Il y a peut-être des erreurs, ça fait un an que je n'ai pas touché à la programmation...

Il faut penser comme si on devait le faire à la main et traduire en C
- j'attends de recevoir un < (pas fait)
- je lis une chaine jusqu'à la virgule (ce qui est fait)
- si je lis >, j'ai fini (on s'est arrêté trop tôt ou trop tard?)

Le problème est que la dernière valeur ne finit pas par virgule mais par > Du coup, on va ajouter le début de la trame suivante. On peut faire:
- j'attends de recevoir un < (pas fait)
- je lis une chaine jusqu'à la virgule ou supérieur (moins commode!) et je recommence tant que cela finit par virgule

Une solutions:
- j'attends un <
- je positionne pointeur à 0 (je vais écrire la chaine dans tableau[pointeur])
- je répète:
    - je vide tableau[pointeur] en faisant ( tableau[pointeur] = "" )
    - je lis un caractère
           - si c'est un chiffre ou un point, je l'ajoute à tableau[pointeur]
           - si c'est virgule, j'incrémente pointeur
      jusqu'à lire un >

A réfléchir, si c'est des nombres pourquoi stocker dans un tableau de chaine et pas dans un tableau de nombre?
Pour rentrer un entier en lisant d'abord les poids forts:
répéter: nombre = nombre *10 + valeur_lue
Si c'est un float, on peut si on voit le point compter combien de chiffres suivent et diviser par 10ce_nombre:
- je répète:
    - je vide tableau[pointeur] en faisant  tableau[pointeur] = 0.0
    - je met decimales à -1 (-1 c'est "je n'ai pas vu de point", N>0: il y a N chiffres après la virgule
    - je lis un caractère
           - si c'est un chiffre, je l'ajoute  tableau[pointeur] = tableau[pointeur]*10 + chiffreLu
                et si decimales >= 0 j'incrémente décimales
           - si c'est un point je mets decilmales à 0
           - si c'est virgule ou un >
                   - si decimales >0   tableau[pointeur] = tableau[pointeur]/10decimales
                   - j'incrémente pointeur
      jusqu'à lire un >




lesept

#4
Nov 22, 2020, 11:10 pm Last Edit: Nov 22, 2020, 11:29 pm by lesept
strtok est ton ami...  :)

Un truc du genre :

Code: [Select]
String trame = "<1111,22.22,3333,4444,5555,666.66,777.7,888.8,999.9,101.1,121.2,314.1,59,26,12345678>";
char trame2[];
float val[];

void setup()
{
  Serial.begin(9600);
  trame2 = trame.c_str();  // <-- pas sûr, à vérifier
// Si ça compile pas,essayer :
// strcpy (trame2, trame.c_str());
}

void loop()
{
  char * pch;
  int i = 0;
  pch = strtok (trame2,"<,>");
  while (pch != NULL)
  {
    pch = strtok (NULL, "<,>");
    if (i>0 && pch!='>') val[i] = atof(pch);
    Serial.print(i); Serial.print(" : "); Serial.println(val[i]);
    ++i;
  }
}

A tester...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

biggil

NON :
Code: [Select]
  for (int i = 0; i < 19; i++) {
    tableau [i] = Serial.readStringUntil(",");
  }
  Serial.println(tableau[i]);


OUI:
Code: [Select]
  for (int i = 0; i < 19; i++) {
    tableau [i] = Serial.readStringUntil(",");
    Serial.println(tableau[i]); // A L'INTERIEUR DE LA BOUCLE
  }

Aide toi, le compilateur t'aidera

Quote
Code: [Select]
String trame = "<1111,22.22,3333,4444,5555,666.66,777.7,888.8,999.9,101.1,121.2,314.1,59,26,12345678>";
Il manque un truc important, si la trame arrive par la voie série, il faut déjà la lire caractère par caractère pour arriver jusqu'au > final, c'est à dire faire une analyse avant de l'avoir. Le problème est différent si la trame est sans une string.

BrUnO14200

Moi j'utilise Json et il fait le boulot à ta place ;) 
Projet aquaponique  :https://forum.arduino.cc/index.php?topic=677286.msg4584918#new

lesept

#8
Nov 23, 2020, 11:14 am Last Edit: Nov 23, 2020, 11:14 am by lesept
Autant lire la trame en une seule fois, la stocker dans un tableau de char et la traiter ensuite (après détection du '>'), plutôt que tout faire d'un coup.
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

J-M-L

#9
Nov 23, 2020, 11:28 am Last Edit: Nov 23, 2020, 11:31 am by J-M-L
Autant lire la trame en une seule fois, la stocker dans un tableau de char et la traiter ensuite (après détection du '>'), plutôt que tout faire d'un coup.
tout dépend de la longueur de la trame et s'il faut faire des traitements pendant la réception. Dans l'absolu, oui, si la trame n'est pas trop longue, c'est plus simple de traiter une trame entière d'un coup car on peut vérifier sa validité totale.

éventuellement  vous pouvez jeter un oeil à mon petit tuto sur le sujet
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

meerya

Merci à tous pour vos réponses !!
Effectivement lesept j'ai utilisé la fonction strtok. Je ne savais pas qu'elle existait mais elle simplifie beaucoup de choses.
Je suis actuellement en train d'essayer de récupérer la trame, puis de la stocker dans un tableau pour ensuite la découper.
Je regrouperais les 2 fonctions ensemble par la suite.
Code: [Select]
char string[200];
  int availableBytes = Serial.available();
  for (int i = 0; i < availableBytes; i++)
  {
    string[i] = Serial.read();
  }
Serial.print (string);


J'ai un petit soucis avec mon bout de code j'obtiens quelque chose comme : <<<<<<<<<<<<<<<AAAA,BB.BB,etc...
Comme si la boucle prenais le premier caractère plusieurs fois. Je ne comprends pas très bien ... 

TheMemberFormerlyKnownAsAWOL

Your string isn't terminated by the code snippet you posted, so you can't print it and expect consistent results.
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

lesept

Cherche le tuto de J-M-L qui explique comment lire le port série.

Pense à mettre un 0 à la fin de la chaine, donc après le } de la boucle for :

Code: [Select]
string[availableBytes] = '\0';

Damned, grilled by Prince !!!
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

J-M-L

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

meerya

J-M-L tu es mon sauveur !  :smiley-lol:
J'ai suivi ton tuto pour comprendre comment fonctionne le port série (on dirait pas mais c'est pas si simple)
Finalement, j'ai adapté ton code pour qu'il réagisse à ma trame et tout fonctionne !

En bonus j'ai réussi rassembler les 2 codes en 1. 
Le port série en lecture c'est beaucoup plus complexe que ça y parait, je ne pensais pas que sans "délimitation" tout partirait en sucette comme avec mon code précédent... 

Go Up