Dimension Array

Salut salut,

Etant assez nouveau sur Arduino et en particulier avec les tableaux, j'ai besoin d'un peu d'aide !

J'essaie d'extraire des données précises d'une trame RS232 provenant d'une station météo dont voici une trame d'exemple :

ULTIMETER WEATHER REPORT 02/03/17 08:14
Wind:     Cur   0.6M/S 253Deg, 1mAvg   1.0M/S,  1mPeak   2.1M/S 305Deg
           Hi   4.0M/S 180Deg
WChill:   Cur   7.5C, Lo   6.2C
Temp Out: Cur   7.5C, Hi  20.5C, Lo   7.5C
Temp In:  Cur  21.7C, Hi  21.7C, Lo  19.6C
Rain:   Today   0.00in, Since 01/01/09:    0.00in

(Je voudrais avoir la date, heure, et plusieurs autres données)

Jusqu'ici rien de sorcier me direz vous !
Pour la méthode de réception j'ai choisi le tableau, j'ai fais un petit bout de code que voici :

char Array[200];
int Dataserial;


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

void loop() {

     while (Serial.available() > 0) {

for(int i=0; i < sizeof(Array); i++)
{

Dataserial = Serial.read();
Array[i]=Dataserial;

Serial.print(Array[i]);
}

J'arrive avec succès a l'afficher dans le port série mais avec des caractères supplémentaires pas vraiment désirable !
Screen : Code #1 - Imgur

Peut être s'agit-il de données qui reviennent de la station ? peut être !
Mais ce n'est pas le seul problème ; vous voyez dans mon code que j'ai défini le tableau avec 200 caractères (sauf erreurs de ma part), hors j'ai calculé que ma trame faisait dans les 300 caractères au complet. Si je ne me trompe pas, ma trame aurait du être coupée quand je demande l'écriture dans le porte série ?
J'ai essayé en mettant [1] au lieu de [200], les caractères indésirables disparaissent mais la trame est toujours complète ><

Concernant la méthode de transmission Station > Arduino, j'ai un Max202 relié du DB9 de la station vers le port Rx (pin 0) de mon Arduino (+ gnd et 5v)

Bonjour,

Tu dépasses la taille de ton tableau
En C/C++ il n'y a pas de vérification si tu écris ou lis en dehors du tableau. S'il n'y a rien derrière ça peut (apparemment) bien se passer, s'il y a des variables après le tableau, ça va les écraser.

Bonjour,

Merci de ta réponse rapide,
Que me conseillerais tu de faire ?

Il faut attendre le début de trame, par exemple attendre le premier caractère, puis lire les données dans ton tableau en faisant attention à ne pas dépasser la taille.

Par exemple:

char Array[300];
int Dataserial;


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

void loop() {
  char c=Serial.read();
  if (c=='U')       // début de trame
  {
    Array[0]=c;
    int length=Serial.readBytes(Array+1,sizeof Array-2);  // lit les données, on réserve un place pour le 0 de fin
    length++;     // pour prendre en compre le premier caractère
    for (int i=0; Array[i]!=0; i++)
      Serial.print(Array[i]);
  }
}

Impeccable, merci beaucoup !
Je vais essayer ça pour récupérer mes autres données !

Bonjour,

Je reviens ici avec encore mes tableaux :c

Je dois calculer le checksum d'une trame contenant un message.
La trame complète est sous cette forme :

 <ID00><L1><PA><FE><MA><WB><FE><CE>"Message""Checksum"<E>

En sachant que l'identifiant et la fin de trame ne doivent pas être pris en compte lors du checksum

Identifiant :
Fin de trame :

Le meilleur moyen de calculer le checksum serait de mettre la trame dans un tableau et ensuite faire les ou exclusif (“^=” il me semble) entre chaques caractères.
Sauf que je n’ai aucune idée de la syntaxe à mettre !
D’autant plus que le tableau doit faire la taille de la trame et la longueur de celle ci peut changer du simple au double (en restant dans la limite du raisonnable)

C'est pourquoi je demande un petit peu d'aide ! :wink:

Il faut un tableau assez grand pour vos besoins et savoir combien de caracteres sont dedans - vous ne traitez que cela pour la checksum

Bonjour,

Si tu as utilisé un programme du genre de celui que je t'ai proposé pour recevoir les caractères tu as le tableau et sa longueur. Il suffit de faire un ou exclusif pour les octets concernés.

Justement, la longueur du tableau varie :c mais pas plus de 100 caractère je pense (ce qui fait déjà grand)
Oui uniquement que pour le checksum.

J'ai essayé avec ce que tu m'a donné, avec une trame de test et si j'ai bien compris, ça donne un truc du genre :

// trame de test : <ID00><L1><PA><FE><MA><WB><FE><CE>test<E>

char Array[41];

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

void loop() {

char c=Serial.read();
  if (c=='<'){       // début de trame
  
    Array[0]=c;
    int length=Serial.readBytes(Array+6,sizeof Array-4);
    length++;
    for (int i=0; Array[i]!=0; i++)
      Serial.print(Array[i]);

  }
}

?

Plutôt quelque-chose de ce genre:

void loop() {
  char c=Serial.read();
  if (c=='<')       // début de trame
  {
    Array[0]=c;
    int length=Serial.readBytes(Array+1,sizeof Array-2);  // lit les données, on réserve un place pour le 0 de fin
    length++;     // pour prendre en compre le premier caractère
    for (int i=0; Array[i]!=0; i++)
      Serial.print(Array[i]);

    byte chk=0;
    for (int i=6; i<length-4; i++)
      chk^=(byte)Array[i];
  }
}

Ok, je reprend tout à zero.
Dans un premier temps avec un tableau de 41 soit la longueur de la trame
Je comprend plus rien là xD

normalement, avec ça il devrait me retourner juste le milieu de la trame (enfin ce que je veux, sans l'ID et la fin) non ?

// trame de test : <ID00><L1><PA><FE><MA><WB><FE><CE>test<E>

char Array[41];
byte chk=0;

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

void loop() {
  char c=Serial.read();
  
    Array[0]=c;
    int length=Serial.readBytes(Array+6,sizeof Array-4);
    length++;
    
    int i;
    for (i = 0; i < 41; i = i + 1) {
    Serial.print(Array[i]);  
    }

Non, ça ne retourne pas que le milieu de trame.Il faut lire toute la trame et traiter ce qui t’intéresse.

J'ai finalement réussi a calculer le checksum en décimal puis la conversion en hexa ! avec seulement la partie de la trame qui m'intéresse

Par contre une question, il me le calcul une fois sur deux, voir le screen.

prog :

// trame de test : <ID00><L1><PA><FE><MA><WB><FE><CE>mess<E>
char Array[41];
int i;
byte chk=0;
String checksum;

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

void loop() { 
char c=Serial.read();
  if (c=='U')       // début de trame
  {
    Array[0]=c;
  
  for (i = 0; i < sizeof(Array) - 1; i++){
  //Serial.write(Array[i]);
  }
  delay(5000);

  
  for (int i=6; i< sizeof(Array)-4; i++)
  chk^=(byte)Array[i];
  
  Serial.print("dec: ");
  Serial.println(chk);
  
  checksum =  String(chk, HEX);
  Serial.println("hex: " + checksum);
  
}

Screen : Imgur: The magic of the Internet

Dans ton programme, on ne voit pas de lecture de la trame.

Faudrait penser à remettre chk à zéro avant de commencer le calcul du checksum

Oui avec la 'mode' arduino qui consiste à mettre toutes les variables globales, on oublie de les initialiser quand il faut.

kamill:
Dans ton programme, on ne voit pas de lecture de la trame.

Que veux tu dire ?

fdufnews:
Faudrait penser à remettre chk à zéro avant de commencer le calcul du checksum

Fait !

Skeetch:
Que veux tu dire ?

Ben, qu'il n'y a pas de réception de la trame dans ton programme.

faut arrêter avec la classe String partout...

  checksum =  String(chk, HEX);
  Serial.println("hex: " + checksum);

il suffit juste de faire un

Serial.print("hex: ");
Serial.println(chk, HEX); // sur un seul digit si <= 15

pourquoi passer par une String??

Re bonjour et merci de vos réponses !

Surement un question très bête que je pose mais, quand je fais ceci :

 if (Serial.available() > 0){
        incomingByte = Serial.read();

        Serial.println(incomingByte);

il me ressort la valeur décimale de mon caractère ASCIIi, ce qui est désagréable ! J'avais déjà rencontré ce problème et je pensais l'avoir réglé mais apparemment il s'agissait d'un coup de bol ! (voir screen : Imgur: The magic of the Internet )

Ma variable incomingByte est déclarée en int