Bonjour à tous,
Après une semaine sur mon pb je le soumet à vos yeux neufs et expérimentés.
Mon projet:
identifier des trames nmea reçues sur le port serie, en identifier une en particulier et en extraire une info pour envoyer une nouvelle trame sur la sortie serie.
Après avoir réécris, nettoyé, debuggé le code, ça marche (reste quelques vérifications tout de même).
Mais certaines trames de sont pas identifiées (via le "$" qui marque le début) alors que j'ai l'impression d'analyser un par un tous les caractères reçus sur le port série...
mon code:
#include <Wire.h> #include <Adafruit_BMP085.h>
/* deuxième sketch pour IAS pour LK8000 dans une forme plus rigoureuse*/
//int ptot=1013; //à supprimer quand BMP085 dispo;
Adafruit_BMP085 bmp;
void setup(){ Serial.begin (57600);
bmp.begin();
}
void loop(){ Serial.println("loop");
while (int n=Serial.peek()!='$'){
if (Serial.available()<1){
continue;
} Serial.print(char(Serial.read())); //penser à enlever le LN!
}
char nmea[83]={'$'};
get_nmea(nmea); //entre toute la trame dans la chaine nmea
if (get_entete(nmea)==true){ //si l'entete est celle qui donne la p_stat Serial.println("if_loop true"); Serial.print("ptot "); Serial.print(bmp.readPressure()/100);Serial.println("hpa");
int ias=10sqrt((2((bmp.readPressure()/100) - get_pstat(nmea)))/1.225);
//calcul de l'IAS Serial.print("IAS caculé est de: "); Serial.print(ias);Serial.println("dm/s");//penser à enlever le LN!
envoie_trame_ias(ias);
void get_nmea(char nmea[]){
// Serial.println("get_nmea");
for (int i=0; i<83; i++){
while (Serial.available()<1); // attente de 1 caractères dispo dans le buffer
nmea_=Serial.read(); //replissage de la chaine nmea avec les caratcères dispo_
_ if (nmea*==10){ //si le caractère est on arrête de remplir*_ * // Serial.print("caractere LF trouvé");* * break; // et on quitte la boucle* * }* * }* _ Serial.println(nmea); // on renvoie la trame sur la sortie serie //penser à enlever le LN!_ * return;*
mince j'avais viré toutes mes lignes de debug pour plus de lisibilité mais elles sont revenue...
#include <Wire.h>
#include <Adafruit_BMP085.h>
/* deuxième sketch pour IAS pour LK8000 dans une forme plus rigoureuse*/
//int ptot=1013; //à supprimer quand BMP085 dispo;
Adafruit_BMP085 bmp;
void setup(){
Serial.begin (57600);
bmp.begin();
}
void loop(){
Serial.println("loop");
while (Serial.peek()!='
){
if (Serial.available()<1){
continue;
}
Serial.print(char(Serial.read())); //penser à enlever le LN!
}
char nmea[83]={'
};
get_nmea(nmea); //entre toute la trame dans la chaine nmea
if (get_entete(nmea)==true){ //si l'entete est celle qui donne la p_stat
Serial.println("if_loop true");
Serial.print("ptot "); Serial.print(bmp.readPressure()/100);Serial.println("hpa");
int ias=10*sqrt((2*((bmp.readPressure()/100) - get_pstat(nmea)))/1.225);
//calcul de l'IAS
Serial.print("IAS caculé est de: "); Serial.print(ias);Serial.println("dm/s");//penser à enlever le LN!
envoie_trame_ias(ias);
}else {
Serial.print("if loop false");
// Serial.print(nmea);
}
}
void get_nmea(char nmea[]){
// Serial.println("get_nmea");
for (int i=0; i<83; i++){
while (Serial.available()<1); // attente de 1 caractères dispo dans le buffer
nmea[i]=Serial.read(); //replissage de la chaine nmea avec les caratcères dispo
if (nmea[i]==10){ //si le caractère est <LF> on arrête de remplir
// Serial.print("caractere LF trouvé");
break; // et on quitte la boucle
}
}
Serial.println(nmea); // on renvoie la trame sur la sortie serie //penser à enlever le LN!
return;
}
boolean get_entete(char nmea[]){
// Serial.print(nmea);
char entete_alti[8]="$PGRMZ,";
for (int i=0;i<6;i++){
if(entete_alti[i]!=nmea[i]){
// Serial.print("condition fausse");
return false;
}
}
return true;
}
La fonction get_entete() comporte une légère erreur : tu boucles de 0 à 5 donc tu ne compare que 6 caractère soit "$PGRM"
Il manque le Z et la virgule. Ce qui n'est pas forcement un problème.
Mais pourquoi s'embeter alors qu'il existe strncmp()
Sans avoir testé le code, en simple lecture directe je ne vois rien de choquant même si je ne l'aurais pas écris comme cela.
Par ailleurs tu te sers de la liaison série à la fois pour le debug vers le PC et pour la liaison avec le GPS. Il se peut que les problèmes viennent de là.
ah oui tiens,
c'est parceque au début, je ne lisais que "PGRMZ" j'ai pas correctement modifié le test.
Pour strncmp(), je ne suis qu'un débutant en C, j'utilise mes restes de "BASIC" de la fin des années 90 et là c'est déjà bien mieux que la première version avec pleins de variables à porté général (j'ai potassé les pointeurs) mais c'est prévu pour la suite, tout comme l'utilisation de sscanf() pour extraire mon info (pour l'instant c'est aussi une boucle faite maison),une fois que j'aurai trouvé mon pb.
Mais c'est vrai que sur le fond ça ne change rien, ça ne devrait pas laisser passer de trame au travers. pour moi le mystère demeure.
Pour le debug, je n'utilise pour l'instant que le terminal série pour envoyer les trames, recevoir des infos pour debug et voir ce qui serait envoyé réellement.
Autre étonnement: Serial.peek() me pose qq soucis: dans le tout début pas de pb, le caractère reste et le serial.read le retrouve. Mais lorsque le "$" arrive, la boucle de remplissage de ma chaine commence et Serial.read() lit direct le caractère suivant dans la file. Je doit entrer "$" manuellement au début de ma chaine pour contourner ça et ça fait pas très propre...
Je vais essayer de corriger ces petites ratures et voir.
Merçi
Romaric
En fait je pense que le problème vient justement du peek
Essaye quelque chose comme cela :
while ( Serial.available() )
{
char c = Serial.read();
if ( c == '
Regarde aussi dans mon tuto sur les protocoles de communication. Je défini un protocole qui est quasiment identique au NMEA et j'utilise un automate pour gérer la réception avec timeout etc ....
)
{
nmea[0] = c;
....
}
}
Regarde aussi dans mon tuto sur les protocoles de communication. Je défini un protocole qui est quasiment identique au NMEA et j'utilise un automate pour gérer la réception avec timeout etc ....
Tu compares entete_alti != nmea dans la boucle, mais tu compares les deux tableaux en entier, ce qui fait que comme ils n'ont pas la même taille, le résultat devrait être faux dès le départ, non?
J'ai modifié le for : de i = 0 à 7 pour comparer les 8 premiers caractères, ainsi que la comparaison pour comparer des caractères et non pas des tableaux de caractères...
oui j'ai vu ça mais les sont bien dans le code... merci à présent: je n'utilise plus serial.peek et il n'y a plus pb de caractère raté. Dommage je trouvais ça plus élégant que la methode du caractère intermédiaire mais ça ne fonctionne pas (une limitation de peek?). j'ai avancé. Maintenant je suis sur le crc32 de la chaine que j'envoie (c'est pas un xor). romaric
Le peek() récupère le premier caractère de la file d'attente mais ne fait pas avancer le pointeur.
Donc si derrière tu n'effectue pas de read() le pointeur n'avance pas et le peek() retourne toujours le même caractère.
Ca marche peut être la 1ere fois et tant que tu retombe juste sur '$' mais si tu rate un caractère, tout se bloque.
ok je viens de piger: je ne maitrise encore pas totalement le forum [i]sans balise particulière n'apparait pas (comme dans mon message précédant ou je l'ai pourtant bien écrit).
Pour le peek. dans les deux cas il était suivit d'un Serial.read: dans un cas en direct et dans l'autre cas dans la fonction appélée.
Pas grave j'ai maintenant utilisé la méthode qui fonctionne.
c'est bon,
tout marche parfaitement bien maintenant.
J'utilise le connecteur USB depuis mon PC ainsi que les i/o série vers mon PNA via un cable micro USB en mode serie (pas USB) et il n'y a pas de problème particulier.
Etape suivante: accélérer le calcul.
Merci,
à bientôt
Romaric