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)
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.
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]);
}
}
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)
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.
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]);
}
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 )