Go Down

Topic: analyse de trame de 27 octets  (Read 5507 times) previous topic - next topic

medeloualidi

Jun 24, 2016, 03:00 pm Last Edit: Jun 24, 2016, 03:09 pm by medeloualidi
Bonjour ArduinoTeam

Je travail sur un projet de communication numérique,  et j'essaye d'envoyer 27 octets sur le port série  chaque 90 ms dont le 'entête est de valeur 255, avec un débit de 4800 baud.

de l'autre coté le récepteur est une carte arduino uno, je veux savoir comment je peux stocker les 27 octetsdans un tableau une fois je reçois le premier byte qui est de valeur 255,??

 quelqu'un a une idée svp ??!!!! :)

-Standby

Il y a un peut un manque de motivation.

Ecrire une valeur dans un tableau n'est pas compliqué, incrémenter l'index d'un tableau non plus, comparé une valeur non plus.
The Mind is like a parachute it works best when opened.

medeloualidi

Ah Non ne dis pas ça ... j'ai déjà essayé pas mal de solution mais je trouve toujours un décalage au niveau de la trame reçu, comme celui la par exemple

Code: [Select]

#include "TimerOne.h"

boolean readyToRead = false;

void setup() {
  Serial.begin(4800);// put your setup code here, to run once:
  //Serial.setTimeout(100);
}

void loop() {
 Serial.flush();
 
  //unsigned long duree = micros();
  int duree = micros();

  boolean bitArray[200];
  boolean datar[208]; 
  int i = 0;
  byte received;
  while (Serial.available() > 0 && !readyToRead)
  {
    byte b = Serial.read();
    delayMicroseconds(100);
    if (b == 255)
    {
      readyToRead = true;

    }
  }
  if (readyToRead)
  {
    while ( (Serial.available() > 0 ) && (i < 25))
    { // esayer avec 26
     
      received = Serial.read();
      delayMicroseconds(100);
     
      //Serial.print(received, HEX);
      //Serial.print(" ");

      for (int bit = 0; bit <= 7; bit++)
      {
        if (received & (1 << bit)) {
          bitArray[bit + i * 8] = 1; // add true to array
        }
        else {
          bitArray[bit + i * 8] = 0; // add alse to array
        }
        //Serial.print(bitArray[bit + i * 8]);
      }
      i++;

      if ( received == 144)
      {
        readyToRead = false;
        Serial.flush();

      }
    }
  }


kamill

#3
Jun 24, 2016, 03:55 pm Last Edit: Jun 24, 2016, 03:57 pm by kamill
Bonjour,

Ton programme m'a l'air super compliqué
La méthode suivante devrait fonctionner
Code: [Select]
void loop() {
  static byte buffer[27];
  if (Serial.available())
  {
    Serial.find(255); // attend l'octet de début
    buffer[0]=255;    // range le premier octet
    Serial.readBytes(buffer+1, sizeof buffer - 1);  // lit les 26 octets suivants
  }
}

medeloualidi

Oh! Merci  mais une question svp
Code: [Select]
Serial.readBytes(buffer+1, sizeof buffer - 1); qu'est ce qu'elle renvois  ???  et j'espère que
Code: [Select]
   for (int i = 0; i < sizeof(buffer); i++) {
      Serial.print(buffer[i]);
    }


print bien ce que je reçois dans le moniteur série

kamill

Oui, ça doit afficher les octets que tu as reçu, mais tu ne dois pas voir grand chose si tu ne sépares pas tes octets à l'affichage.

medeloualidi

j'ai essayé avec ça,  mais il affiche une sel fois des octets que je n'ai pas envoyé
Code: [Select]


void setup() {
  Serial.begin(4800);// put your setup code here, to run once:
  //Serial.setTimeout(100);
}

void loop() {
 
   byte buffer[26];
   
  if (Serial.available()>0)
  {
    Serial.find(255); // attend l'octet de début
    buffer[0] = 255;  // range le premier octet
    Serial.readBytes (buffer + 1, sizeof(buffer) - 1); // lit les 26 octets suivants
  }
   for (int i = 0; i < sizeof(buffer); i++) {
      Serial.print( buffer[i]);
      Serial.print(" ");     
    }
    Serial.print("\n");
  delay(1000);
 
}

kamill

#7
Jun 24, 2016, 05:48 pm Last Edit: Jun 24, 2016, 05:49 pm by kamill
L'affichage doit être dans le if {} après la réception
Code: [Select]
void loop() {
  byte buffer[27];

  if (Serial.available() > 0)
  {
    Serial.find(255); // attend l'octet de début
    buffer[0] = 255;  // range le premier octet
    int nbOctets=Serial.readBytes (buffer + 1, sizeof(buffer) - 1); // lit les 26 octets suivants
   
    for (int i = 0; i < nbOctets+1; i++) {
      Serial.print( buffer[i]);
      Serial.print(" ");
    }
    Serial.print("\n");
  }
  delay(1000);
}


buffer doit avoir 27 octets et non 26
j'ai amélioré un peu le programme en testant le nombre d'octets reçus

medeloualidi

Est ce que t'as jamais essayer ça ??!! parceque ça n'a pas marché pour moi :(

J-M-L

#9
Jun 25, 2016, 02:22 am Last Edit: Jun 25, 2016, 08:31 am by J-M-L
Il est important de comprendre que Serial.find(255) n'attend qu'une seconde par défaut - le timeout peut être réglé Dans le setup avec un appel à setTimeout()

donc il serait bien de faire

If (Serial.find(255)) {...}
Plutôt que de croire aveuglément qu'on a bien reçu 255 une fois que l'appel à la fonction retourne.

De même

Code: [Select]
Serial.readBytes (buffer + 1, sizeof(buffer) - 1);


Peut retourner avant d'avoir lu les 26 octets si timeout

Le mieux c'est vraiment d'avoir un index x (initialisé à 0), et un booléen de début de trame qui indiquera si on a reçu le premier 255 (initialisé  à faux)

créer  un boucle générale infinie qui contient:
  si une donnée est dispo sur la ligne série
     On lit 1 caractère (byte)
     Si on a déjà reçu 255 (test du booléen)
          rajouter le caractère au buffer en position x,
           passer à x+1,
           si x vaut 26 alors on a tout reçu on fait un break; pour sortir de la boucle infinie
      Sinon  on n'a pas encore reçu 255 alors
           on teste si le caractère reçu vaut 255 et  si oui
                  on met le booléen  vrai pour dire que c'est bon on a reçu 255,
                   on met x à 0
            et sinon on ne fait rien et on retourne à la boucle infinie en attente du prochain charactere


L'amélioration suivante de cet algorithme c'est de rajouter la gestion d'un temps d'attente max éventuellement au début de la boucle infinie et faire un break si le temps max est atteint avec bien sûr un booléen supplémentaire qui dira qu'on n'a pas tout reçu alors que si on a bien tout reçu on le met à vrai


Voilà - reste plus qu'à coder

Vous essayez?

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

kamill

#10
Jun 25, 2016, 09:29 am Last Edit: Jun 25, 2016, 09:31 am by kamill
Bonjour,

Apparement Serial.find() n'a pas l'air de fonctionner avec des caractères >127. Je te propose le code suivant en remplacement:
Code: [Select]
void loop() {
  static byte buffer[27];
 
  if (Serial.available() > 0)
  {
    byte octet=Serial.read();
    if (octet==255)
    {
      buffer[0] = 255;  // range le premier octet
      int nbOctets = Serial.readBytes(buffer + 1, sizeof buffer - 1); // lit les 26 octets suivants

      for (int i = 0; i < nbOctets+1; i++) {
        Serial.print(buffer[i]);
        Serial.print(" ");
      }
        Serial.print("\n");
    }
  }
}

medeloualidi

Merci J-M-L, c'est presque le même algorithme que j'ai essayé avant de poster mon problème, mais l'idée de kamill   a l'aire qu'elle donne des bonnes résultats aussi sauf que dès fois je reçois une trame correcte dès fois non, pour moi je veux faire la transmission chaque 100 ms, voilà ce qu'il m'affiche

255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 144 trame correcte
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 144 trame correcte
255 137 31 80 116 133 176 122 46 153 144 92 12 201 144 255 137 168 176 219 14 165 12 232 154 153 trame fausse
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 144 92 12 201 144 255 137 168 176 trame fausse
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 144 trame correcte
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 168 176 219 14 165 12
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 165 12 232 154 153 43 32
255 137 168 176 219 14 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 144 255 137 168 176
255 137 80 116 133 176 122 46 153 144 92 12 201 144 255 137 168 176 219 14 165 12 232 154 153 43
255 153 144 92 12 201 144 255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 255 137 168 176 219 14 165 12 232 154
255 137 168 176 219 14 165 12 232 154 153 43 32 31 255 137 168 176 219 14 165 12 232 154 153 43
255 137 168 176 219 14 165 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 43 32 31 80 116
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 80
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 144
255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 144


medeloualidi

Est ce que c'est un problème de synchronisation parce que j'envoie la même trameà chaque fois qui commence par 255 et finit par 144

255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 144

J-M-L

les communications séries sont asynchrones par nature. utiliser Serial.readBytes comme le propose Kamill pour lire d'un coup les 26 octets arrivant ensuite est séduisante mais dépendante du timeout implicite de la fonction Serial.readBytes qui est de 1 seconde. Si pour une raison ou pour une autre les 26 chars n'arrivent pas en une seconde, votre trame sera incomplète. si en plus vous n'avez pas vidé le buffer et que vous l'imprimez en entier (pas ce que Kamill fait cependant, je ne sais pas si c'est le code que vous utilisez) alors vous allez imprimer des données que vous n'avez pas vraiment reçu. il faut donc penser à remettre le buffer à zéro.

je pense que gérer manuellement 1 par 1 les octets quand ils arrivent va vous donner plus de contrôle sur ce qu'il se passe.
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

J-M-L

#14
Jun 25, 2016, 11:01 am Last Edit: Jun 25, 2016, 11:08 am by J-M-L
à quelle vitesse envoyez vous la trame? est-ce que les 2 ports séries sont bien calés sur la même vitesse en BAUD? au début je vois que vous utiliser 4800 comme vitesse de communication

à 4800 bauds vous envoyez environ 480 characters par seconde donc en 100ms vous pouvez envoyer 48 octets environ. ça peut sembler suffisant puisque vous n'envoyez que 27 éléments mais ensuite votre programme imprime

255 137 168 176 219 14 165 12 232 154 153 43 32 31 80 116 133 176 122 46 153 144 92 12 201 144

soit 95 caractères. c'est bufferisé et ça peut répondre vite comme ça peut attendre si le buffer d'entrée est plein - et comme vous lisez à 480 caractères par seconde mais écrivez ça 10 fois par seconde (puisque vous envoyez une trame toutes les 100ms) vous essayez de mettre dans le buffer 950 caractères par seconde... le Serial.print devient alors en fait bloquant et vous commencez à accumuler du retard pour revenir lire les 27 éléments suivants car le buffer d'entrée se remplit (et overflow possible) en attendant.


quel outil utilisez vous pour envoyer votre trame? pouvez vous passer à 115200 bauds la fois côté émetteur et récepteur juste pour voir ce que ça donne ou vérifiez les octets dans votre programme et n'imprimez que OK si c'est bien la bonne trame reçue pour ne pas surcharger le buffer
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

Go Up