Bonjour tout le monde !
C’est ma semaine de partiels les articles se font donc rares.
Je vais tenter demain ou vendredi de finir mon article sur le DF3120 mais je ne garantie rien 😉
Histoire de vous donner votre dose d’arduino voici un petit morceau de code réalisé pour un membre du forum arduino.
Le but est simple, parser (= parcourir et interpréter) une chaine de caractères reçue sur le port série pour en extraire les données utiles quelle contient.
La chaine type utilisait dans le cadre de ce code a cette forme :
$ texte;valeur;index;diviseur;°c/f;
Le code est facilement modifiable pour coller à n’importe quelle format, il suffit de suivre le principe de base 😉
Sans plus attendre, le code :
// Buffer qui va contenir la trame série #define TAILLE_MAX 32 // Buffer qui va contenir le texte (taille du buffer / 2, oui j'ai mis ça au pif) char texte[TAILLE_MAX / 2], unite; // Données utiles extraites int valeur, index, diviseur; // setup() void setup() { // Initialisation du port série Serial.begin(9600); } // loop() void loop() { // Récupération d'une trame + parsing if(recupInfo(texte, &valeur, &index, &diviseur, &unite)) { Serial.println("Erreur de trame !"); return; } // Affichage Serial.print("Texte: "); Serial.println(texte); Serial.print("Valeur: "); Serial.println(valeur); Serial.print("Index: "); Serial.println(index); Serial.print("Diviseur: "); Serial.println(diviseur); Serial.print("Unité: "); Serial.println(unite); } /* * Parse une chaine au format $ texte;valeur;index;diviseur;°c/f; * Et retourne la valeur des différents champs. */ int recupInfo(char *texte, int *valeur, int *index, int *diviseur, char *unite) { char c, buf[TAILLE_MAX + 1]; unsigned char i = 0; /* Attente du $ espace */ do { /* Attente de 2 char sur le port série */ while(Serial.available() < 2); /* Tant que chaine != $ espace -> boucle */ } while(Serial.read() != '$' && Serial.read() != ' '); /* Remplissage du buffer */ do{ /* Si la chaine a dépassé la taille max du buffer*/ if(i == (TAILLE_MAX + 1)) /* retourne 1 -> erreur */ return 1; /* Attente d'un char sur le port série */ while(Serial.available() < 1); /* Tant que char != 0x1A (fléche) -> boucle */ } while((buf[i++] = Serial.read()) != 0x1A); /* Cloture la chaine de char */ buf[i] = '\0'; /* Copie le texte au début de buf[] dans texte[] */ i = 0; while((texte[i] = buf[i]) != ';') i++; texte[i] = '\0'; /* Parse la chaine de caractères et extrait les champs */ if(sscanf(buf + i, ";%d;%d;%d;%*c%c;", valeur, index, diviseur, unite) != 4) /* Si sscanf n'as pas pu extraire les 4 champs -> erreur*/ return 1; /* retourne 0 -> pas d'erreur */ return 0; }
Voila voila Enjoy ! 🙂
Fonctionne parfaitement!!
Salut,
j’effectue un projet à peu près pareil, une communication via port série RS232 avec un module GPS, la carte arduino alors traite la trame GPS reçue & l’affiche sur écran, pourriez vous m’orienter vers une documentation qui peut m’aider à établir cette connection et dans un second lieu exploiter ce bout de code??
Voila de quoi t’occuper 😉
La connexion RS232 – arduino :
http://chuckontech.com/?p=147
Le protocole NMEA :
https://fr.wikipedia.org/wiki/NMEA_0183
GPS + arduino :
http://learn.adafruit.com/adafruit-ultimate-gps/arduino-wiring
http://playground.arduino.cc/Tutorials/GPS
Thanks a bunch 😀
Bonjour,
Lorsque je le lance le programme il me retourne systématiquement ‘Erreur de trame ».
Est ce que l’erreur peut venir du sscanf? je ne connais pas cette fonction!!!
Merci.
Si il dit qu’il y a une erreur c’est que le format ne correspond pas à la trame envoyé.
http://www.cplusplus.com/reference/cstdio/sscanf/
Bonjour,
Comment faire pour ne pas rendre l’application non bloquante, pour qu’elle puisse faire autre chose.
si j’exécute se code, le programme est tjs en attente du serial et ne fait rien d’autre.
pour afficher par exemple « je suis en attente »
-> « Machine à états fini » + interruption sur le port série pour traiter les caractères un à un en parallèle du programme principal.
Autant prévenir de suite c’est tout sauf simple et c’est ultra chiant à débugger.
Cherche « FSM ragel » sur google pour avoir un outil bien pratique qui génère le code de l’automate en fonction d’une série d’expressions régulières.
Bonjour
je construit une télécommande ou je dois envoyer 3 paramètres.
j’ai réussi à les concaténer avec sprintf(machaine, « %d-%d-%d »,angle,relaisemb,relais), mon séparateur étant -.
Mais je n’arrive pas à le séparer à la réception (et à retrouver mes 3 valeurs: angle, relais emb, relais).
le système envoie les caractères en ascii, mais je ne sais pas comment les séparer (sachant que la valeur angle peut prendre une valeur entre 1 et 180, y compris la valeur 49, valeur ascii du séparateur..
Si quelqu’un pouvait m’aider, je lui en serait reconnaissant.
Merci
Un simple sscanf comme présenté dans l’article devrait suffire, quel est le problème ?
sscanf(buf, « %d-%d-%d », &angle, &relaisemb, &relais)
Super ton bout de code je travaille sans succès sur du decodage de trame entre 2 arduinos en liaison série mais sans succès
je test ton code dès ce soir cependant je ne comprends pas pourquoi « tant que char != 0x1A » pourquoi parle tu de flèche?
0x1A est le code ascii pour SUB qui est souvent représenté par une flèche.
C’est aussi le code généré par la séquence de touche CTRL+Z.
Après je pourrai pas t’en dire plus. Je me rappelle plus du tout du pourquoi de ce code …
Merci bcp pour ton code.
Je cherche aussi à parser une chaine de caractère et je galère un peu.
J’ai essayé avec ton code, sans même le modifié, et en envoyant une chaine type ‘$ Char;Int;Int;Int;Char’ sur le port série, mais j’ai toujours une réponse d’erreur de trame.
As tu une explication?
Merci d’avance.
Tu as bien un point virgule à la fin de la trame ?
Mon code d’exemple a été conçu à l’époque pour un cas où la fin de trame est ; quoi qu’il arrive.
Exemple: « $ Bonjour;1;2;3;°c; »
Sinon, en utilisant %s avec sscanf il est possible d’obtenir un résultat semblable avec moins de code (attention aux dépassement de mémoire avec %s seul sans taille max spécifié).
J’ai modifié le code de l’article pour qu’il utilise un retour ligne au lieu de CTRL+Z pour la fin de donnée.
bonjour, moins que débutant je souhaitais utiliser cette fonction pour commander un train par ctrl C et ctrl V
dans le moniteur serie je tape $ texte;1;2;3;°c/f;
ou $ Bonjour;1;2;3;°c;
la ligne s’efface mais je ne récupère aucun message
si je tape une erreur j’ai bien le message erreur trame
j’utilise un arduino mega 2560 et le logiciel 1.7.9 et le programmer AVRISP mkII
ou est mon erreur
merci
ya
Bonsoir tout le monde, j’ai copié ce code et quand je l’ai compilé, Arduino a détecté une erreur « Stray \302 » au niveau du « return 0; » Pourriez vous m’indiquer la cause et l’éventuelle solution à suivre ^^ ?
je trouve votre blog tres interessant 🙂