View  Edit  Attributes  History  Attach  Print  Search

ACCUEIL | ARDUINO > S'INSTALLER > DEBUTER > APPROFONDIR | PROCESSING | MECATRONIQUE | MATERIEL | OUTILS | TESTS | Plus...|
Python > Shell > ATELIERS Python + Qt > PyQt apps > PyQt+Arduino | Mes Robots | RepRap | Mes lib'Arduino | Mes shields Arduino | Mes distros | Les Mini-PC |
ATELIERS ARDUINO| VIDEOS | COMPRENDRE | REFERENCES | CODER | TECHNIQUE | GNU/LINUX | LIENS | Rien à voir |

L'appui sur un BP déclenche une trame GPS en provenance d'un module GPS EM-406

Par X. HINAULT - Page créée le : 26/3/2011.

(cliquer sur l'image pour agrandir)

1.  Présentation

Ce programme montre comment déclencher l'émission d'une trame GPS par appui sur un BP. Cette trame est ensuite analysée pour en extraire les coordonnées du lieu.Le résultat est affiché dans le Terminal Série côté PC.

Ce programme utilise les fonctionnalités suivantes :

Ressources utiles associées à ce programme :

  • La librairie Serial - pour les communications séries entre la carte Arduino et l'ordinateur ou d'autres composants
  • La librairie TinyGPS qui fournit les fonctions utiles pour l'analyse des trames GPS issues du module GPS
  • La librairie NewSoftSerial qui permet la communication série logicielle sur les broches numériques de la carte Arduino. Cette librairie est utilisée ici pour la communication série avec le module GPS.

2.  Pour comprendre

  • En mode de fonctionnement par défaut, le module GPS envoie à intervalles régulier des trames NMEA sur sa ligne d'émission série. Ces trames ont divers format et contiennent les informations de localisation, de date et d'heure, etc..
  • Le module GPS peut également recevoir des instructions de commande lui demandant telle ou telle trame, etc...
  • Ici, on va stopper l'émission continue des trames GPS et on va demander au module de renvoyer la trame GPS voulue lors de l'appui sur un BP permettant ainsi d'utiliser l'information GPS uniquement quand on en a besoin.
  • Cette manière de faire présente surtout l'avantage de ne pas être obligé d'écouter en continu la ligne série du module GPS sous peine de perdre de l'information.
  • Pour mémoire, les trames GPS envoyées par le module sont de la forme $TYPE info, info, info, *codecontrole.

3.  Matériel Nécessaire

3.1  L'espace de développement Arduino

  • ... pour éditer, compiler le programme et programmer la carte Arduino.

3.2  Le matériel suivant pour réaliser le montage associé

  • une plaque d'essai pour montage sans soudures,
  • des straps,
  • un bouton poussoir pour CI,

4.  Instructions de montage

  • La connexion série vers le PC utilise les broches 0 et 1 (via le câble USB)
  • Enficher la carte d'extension (shield) Arduino GPS (Sparkfun) broche à broche sur la carte Arduino (le module GPS EM 406 (GlobalSat) doit être en place sur le shield) ce qui connectera :
    • Broches RX du module GPS sur la broche 3 de la carte Arduino
    • Broches TX du module GPS sur la broche 2 de la carte Arduino
    • Mettre le sélecteur DLine/UART sur DLine
  • Broche 4 : Un BP connecté au 0V

5.  Le schéma théorique du montage

Le schéma théorique du montage (cliquer pour agrandir)

6.  Le circuit du montage

Le schéma du montage à réaliser (cliquer pour agrandir)

7.  Explication du programme

  • L'appui sur un BP déclenche une requête de trame de format GGA puis RMC et affiche les données issues de la réponse du capteur.
  • Se reporter au programme abondamment commenté pour les détails.

8.  Mise en oeuvre du programme

8.1  Préparation du montage et programmation de la carte Arduino :

  • Commencer par réaliser le montage indiqué sur plaque d'expérimentation
  • Ensuite, programmer la carte Arduino avec ce programme (en bas de page) selon la procédure habituelle

8.2  Préparation du Terminal côté PC dans le logiciel Arduino

  • Côté PC, il faut ouvrir la fenêtre terminal de l'IDE Arduino : pour ce faire, un simple clic sur le bouton « Sérial Monitor ».
  • La fenêtre « Terminal » s'ouvre alors :
  • Il faut alors régler le débit de communication sur la même valeur que celle utilisée par le programme avec lequel nous allons programmer la carte Arduino :

8.3  Fonctionnement

  • Tout d'abord, il faut mettre le module GPS sous tension (sélecteur sur ON) et lui laisser le temps de se verrouiller sur les satellites ce qui peut prendre 1 à 2 minutes...
  • Passer ce délai, on pourra faire un reset sur la carte pour configurer le fonctionnement du module.
  • Ensuite, à chaque appui sur le BP, on obtient la trame programmée et son décodage dans le Terminal série :

(cliquer sur l'image pour agrandir)

9.  Le programme complet en langage Arduino

A copier/coller directement dans l'éditeur Arduino


// --- Programme Arduino ---
// Trame de code générée par le générateur de code Arduino
// du site www.mon-club-elec.fr

// Auteur du Programme : X. HINAULT - Tous droits réservés
// Programme écrit le : 26/3/2011.

// ------- Licence du code de ce programme -----
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License,
//  or any later version.
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

// ////////////////////  PRESENTATION DU PROGRAMME ////////////////////

// -------- Que fait ce programme ? ---------
 /* Ce programme montre comment déclencher l'émission d'une trame GPS par appui sur un BP.
 Cette trame est ensuite analysée pour en extraire les coordonnées du lieu.
 Le résultat est affiché dans le Terminal Série côté PC.
 */


// --- Fonctionnalités utilisées ---

// Utilise la connexion série matérielle vers le PC
// Utilise la connexion série logicielle
// Utilise un module GPS, type EM 406 (Sparkfun),

// -------- Circuit à réaliser ---------

// La connexion série matérielle vers le PC utilise les broches 0 et 1 (via le câble USB)

// La connexion série logicielle utilise les broches :
// RX sur la broche 3
// TX sur la broche 2
// Le sens de ces broches est automatiquement configuré lors initialisation librairie

// Le module GPS EM 406 avec le shield Arduino (Sparkfun) utilise broche RX=3 et TX=2 (inversé pour version récente)
// Mettre le sélecteur du module sur Dline pour utiliser la connexion série logicielle

// Broche 4 : Un BP connecté au 0V

// /////////////////////////////// 1. Entête déclarative ///////////////////////
// A ce niveau sont déclarées les librairies incluses, les constantes, les variables, les objets utiles...

// --- Déclaration des constantes ---

// --- Inclusion des librairies ---

#include <NewSoftSerial.h> // Inclusion de la librairie pour communication série logicielle
// Avant utilisation, il faut installer manuellement cette librairie
// dans le dossier <Libraries> du dossier Arduino
// à télécharger ici : http://arduiniana.org/libraries/newsoftserial/
// plus d'infos : www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Main.LibrairieNewSoftSerial

#include <TinyGPS.h> // inclusion de la librairie pour module GPS - nécessite communication série logicielle
// Avant utilisation, il faut installer manuellement cette librairie
// dans le dossier <Libraries> du dossier Arduino
// à télécharger ici : http://arduiniana.org/libraries/tinygps/
// plus d'infos : www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.LibrairieTinyGPS

//--- pour info : description des trames GPS disponibles avec module GPS EM 406 (format NMEA) :
// GGA : Latitude, LOngitude, altitude, Heure - utilisée par librairie TinyGPS
// GLL : trame simplifiée avec latitude et longitude - pas utilisée par librairie TinyGPS
// GSA : trame avec infos sur satellites utilisés - pas utilisée par librairie TinyGPS
// GSV : trame avec infos sur les satellites visibles par le module GPS  - pas utilisée par librairie TinyGPS
// RMC : trame minimale recommandée avec mois, jour, heure, vitesse, etc.. - utilisée par librairie TinyGPS
// VTG : trame avec données de vitesse - pas utilisée par librairie TinyGPS


// --- Déclaration des constantes utiles ---
const int APPUI=LOW; // constante pour tester état BP

// --- Déclaration des constantes des broches E/S numériques ---

const int brocheTX=2; // Constante pour la broche 2
const int brocheRX=3; // Constante pour la broche 3
const int BP=4; // Constante pour la broche 4

// --- Déclaration des constantes des broches analogiques ---


// --- Déclaration des variables globales ---

String chaineReceptionGPS=""; // chaine réception



// --- Déclaration des objets utiles pour les fonctionnalités utilisées ---

//--- déclaration objet communication série logicielle
NewSoftSerial mySoftSerial(brocheRX, brocheTX); // déclare un objet pour connexion série logicielle

TinyGPS gps; // déclare un objet GPS


// ////////////////////////// 2. FONCTION SETUP = Code d'initialisation //////////////////////////
// La fonction setup() est exécutée en premier et 1 seule fois, au démarrage du programme

void setup()   { // debut de la fonction setup()

// --- ici instructions à exécuter 1 seule fois au démarrage du programme ---

// ------- Initialisation fonctionnalités utilisées -------  

Serial.begin(115200); // initialise connexion série matérielle à 115200 bauds
// IMPORTANT : régler le terminal côté PC avec la même valeur de transmission
// Utiliser une vitesse rapide pour ne pas perturber la communication série logicielle

mySoftSerial.begin(4800); // initialise connexion série logicielle à 4800 bauds
// IMPORTANT : utiliser la même valeur de transmission que le module utilisant cette connexion série
// Le module GPS EM 406 utilise 4800 bauds par défaut


// ------- Broches en sorties numériques -------  

// ------- Broches en entrées numériques -------  
 pinMode (BP,INPUT); // Broche BP configurée en entrée

// ------- Activation si besoin du rappel au + (pullup) des broches en entrées numériques -------  
 digitalWrite (BP,HIGH); // Rappel au + activé sur la broche BP configurée en entrée

// ------- Initialisation des variables utilisées -------  

// ------- Codes d'initialisation utile -------  

// --- message d'info initiale ---

Serial.print("Librairie TinyGPS version ");
Serial.println(gps.library_version());

Serial.print("Librairie NewSoftSerial version ");
Serial.println(mySoftSerial.library_version());

// --- envoi d'une chaine instruction au module GPS

// info : format instruction de controle du module GPS :  $PSRF103,<msg>,<mode>,<rate>,<cksumEnable>*CKSUM<CR><LF>
// avec :
// <msg> : 00=GGA,01=GLL,02=GSA,03=GSV,04=RMC,05=VTG // le type de trame concerné
// <mode> : 0=SetRate,1=Query // requete ou config débit
// <rate> : Output every <rate>seconds, off=0,max=255 // valeur débit - 0 pour off
// <cksumEnable> : 00=disable Checksum,01=Enable checksum for specified message // code de controle

/* CKSUM : Code de validité de la chaine - Principe calcul : The absolute value calculated by exclusive-OR the
8 data bits of each character in the Sentence,between, but
excluding “$” and “*”. The hexadecimal value of the most
significant and least significant 4 bits of the result are convertted
to two ASCII characters (0-9,A-F) for transmission. The most
significant character is transmitted first.*/

// ceci est réalisé par la fonction checkSum dans ce programme

//<CR><LF> : Hex 0D 0A


// ex 1 : PSRF103,00,01,00,01*25 = Requete trame GGA avec code conrole activé - 25 est le code de validité de la chaine

// désactivation envoi automatique des trames GPS par le module GPS
envoiGPS("PSRF103,00,00,00,01"); // Stop trame GGA (fixe rate=0=off) avec controle activé
envoiGPS("PSRF103,01,00,00,01"); // Stop trame GLL (fixe rate=0=off) avec controle activé
envoiGPS("PSRF103,02,00,00,01"); // Stop trame GSA (fixe rate=0=off) avec controle activé
envoiGPS("PSRF103,03,00,00,01"); // Stop trame GSV (fixe rate=0=off) avec controle activé
envoiGPS("PSRF103,04,00,00,01"); // Stop trame RMC (fixe rate=0=off) avec controle activé
envoiGPS("PSRF103,05,00,00,01"); // Stop trame VTG (fixe rate=0=off) avec controle activé

// autres exemples :
//envoiGPS("PSRF103,05,00,01,01"); // Active trame VTG (fixe rate=1/sec) avec controle activé

mySoftSerial.flush(); // vide le buffer série logiciel

Serial.println("==> Appuyer BP pour lancer une requete de trames GPS ...");
Serial.println("");

} // fin de la fonction setup()
// ********************************************************************************

////////////////////////////////// 3. FONCTION LOOP = Boucle sans fin = coeur du programme //////////////////
// la fonction loop() s'exécute sans fin en boucle aussi longtemps que l'Arduino est sous tension

void loop(){ // debut de la fonction loop()


// --- ici instructions à exécuter par le programme principal ---

if (digitalRead(BP)==APPUI) { // si appui BP

    Serial.println("*** Appui BP = lance une requete de trames GPS *** "); // debug
    delay(500); // pause anti rebond avant envoi requete GPS

    mySoftSerial.flush(); // vide le buffer série logiciel avant envoi requete

      // pour info : la fonction TinyGPS a besoin des trames GGA et RMC - les autres trames sont ignorées      

      // envoi d'une demande de la trame GPS voulue (voir doc NMEA pour détail des trames)
      // mémo : 00=GGA,01=GLL,02=GSA,03=GSV,04=RMC,05=VTG // le type de trame concerné

      //---- requete GGA ----
      Serial.print("Requete trame GGA :");
       envoiGPS("PSRF103,00,01,00,01"); // Demande de trame GGA avec controle activé
      Serial.print("Reponse du GPS : "); // message
      while(!mySoftSerial.available()); // attend une réponse du GPS - stop si pas de réponse
     receptionGPS(); // analyse réponse GPS

     //envoiGPS("PSRF103,01,01,00,01"); // Demande de trame GLL avec controle activé
     //envoiGPS("PSRF103,02,01,00,01"); // Demande de trame GSA avec controle activé

     //envoiGPS("PSRF103,03,01,00,01"); // Demande de trame GSV avec controle activé
     // info : renvoie une trame par satellite visible

     // requete RMC
      Serial.print("Requete trame RMC :");
      envoiGPS("PSRF103,04,01,00,01"); // Demande de trame RMC avec controle activé
     Serial.print("Reponse du GPS : "); // message
     while(!mySoftSerial.available()); // attend une réponse du GPS - stop si pas de réponse
     receptionGPS(); // analyse réponse GPS

     //envoiGPS("PSRF103,05,01,00,01"); // Demande de trame VTG avec controle activé


        // une fois les trames valides reçues, on lit les données GPS
        Serial.println();
        Serial.println("Extraction donnees des chaines recues :"); // message
        gestionGPS(gps);         // appel la fonction de gestion du GPS

    // -- message final --
    Serial.println();
    Serial.println("**** Fin gestion requete trames GPS suite appui BP ****");
    Serial.println("... appuyer BP pour lancer une autre requete...");
    Serial.println();
}






//while(1); // stop loop


} // fin de la fonction loop() - le programme recommence au début de la fonction loop sans fin
// ********************************************************************************


// ////////////////////////// FONCTIONS DE GESTION DES INTERRUPTIONS ////////////////////


// ////////////////////////// AUTRES FONCTIONS DU PROGRAMME ////////////////////

//----- fonction analyse réponse GPS ----

void receptionGPS() {

   while(mySoftSerial.available())  {   // tant que des données sont dispos dans le buffer de réception Série Logiciel
  // à noter que la librairie NewSoftSerial assure en permanence la réception des données série reçues sur RX
  // dans un buffer en arrière fond en utilisant une interruption

      int c = mySoftSerial.read();    // récupère la première donnée présente dans le buffer dans une variable...
      chaineReceptionGPS=chaineReceptionGPS+char(c); // ajoute le caractere à la chaine de réception

      Serial.print(char(c)); // affiche le caractère reçu

     boolean test=gps.encode(c); // encode() ajoute le caractère reçu sur port Série Logiciel à la trame GPS en cours de réception
      //et renvoie true quand une trame entière valide a été reçue - renvoie false tant que chaine reçue pas valide

    delay(1); // entre 2 réceptions... laisse le temps au caractère suivant d'arriver...

      if(test==true) {     // une fois qu'une nouvelle trame GPS valide est disponible... vrai seulement tous les n caractères

        Serial.println();
        Serial.print("Une chaine valide (GGA ou RMC) a ete recue par la librairie TinyGPS :");

        Serial.println(chaineReceptionGPS); // affiche la chaine reçue
        chaineReceptionGPS=""; // RAZ chaine de réception


      } // fin nouvelle trame valide
   } // fin while SoftSerial

} //-- fin fonction receptionGPS

//----- fonction envoi instruction GPS ---
void envoiGPS ( String chaineEnvoi) {


  // calculer le checksum (code de controle) d'une chaine
  String checksumChaine=String (checkSum(chaineEnvoi),HEX);

  Serial.println();
  //Serial.println(checksumChaine); // debug - affiche la valeur de controle

  // mise au format $instruction*CKSUM<CR><LF>
  chaineEnvoi="$"+chaineEnvoi+"*"+checksumChaine+char(0xD)+char(0xA);

  Serial.print("Commande envoyee au GPS : ");
  Serial.print(chaineEnvoi); // debug - affiche commande GPS
  //Serial.println();

  mySoftSerial.flush(); // vide le buffer série logiciel avant requete GPS
  mySoftSerial.print(chaineEnvoi); // envoi la chaine sur le port série logiciel

} // fin fonction envoi GPS



//----- fonction de controle - checksum ---
// cette fonction calcule le code de validité de la chaine à envoyer au GPS
int checkSum (String chaineTest) { // by XH - adapted from http://www.codepedia.com/1/Calculating+and+Validating+NMEA+Checksums

  int test=0; // initialise variable locale

 for (int i=0; i<chaineTest.length(); i++) { // défile les caractères de la chaine entre $ et *

  char c=chaineTest.charAt(i); // extrait le caractère de la chaine

  // Serial.print(c); // debug - affiche caractère


          // si c'est le premier passage
          if (test == 0) {
                // on initialise la variable test avec la valeur du caractère
                test = byte(c);
                }
          else {
                // sinon on fait un XOR entre la variable test et la valeur du caractère
                test = test ^ byte(c);
                }


} // fin for i

return test; // renvoie la valeur de controle


} // fin fonction Checksum


//---- fonction de Gestion du GPS ----

void gestionGPS(TinyGPS &gps) { // la fonction reçoit le pointeur de l'objet GPS

  float latitude, longitude; // variable locale de latitude et longitude

  gps.f_get_position(&latitude, &longitude); // la fonction reçoit les pointeurs des variables
  //et met les valeurs dans les variables

  Serial.print("Lat/Long: ");
  Serial.print(latitude,5); // avec 5 décimales
  Serial.print(", ");
  Serial.println(longitude,5); // avec 5 décimales


  int annee; // variable locale
  byte mois, jour, heure, minute, seconde, centiemes;// variables locales

  gps.crack_datetime(&annee,&mois,&jour,&heure,&minute,&seconde,&centiemes); // la fonction reçoit les pointeurs des variables
  //et met les valeurs dans les variables

  Serial.print("Date: "); Serial.print(mois, DEC); Serial.print("/");
  Serial.print(jour, DEC); Serial.print("/"); Serial.print(annee);
  Serial.print("  Time: "); Serial.print(heure, DEC); Serial.print(":");
  Serial.print(minute, DEC); Serial.print(":"); Serial.print(seconde, DEC);
  Serial.print("."); Serial.println(centiemes, DEC);

  // les fonctions suivantes renvoient directement la valeur float
  Serial.print("Altitude (metres): "); Serial.println(gps.f_altitude());  
  Serial.print("Course (degres): "); Serial.println(gps.f_course()); // ?
  Serial.print("Speed(kmph): "); Serial.println(gps.f_speed_kmph());
  Serial.println();

  //--- statistiques décodage GPS ---
  unsigned long chars; // variable locale
  unsigned short sentences, failed_checksum;
  gps.stats(&chars, &sentences, &failed_checksum); // la fonction reçoit les pointeurs des variables
  //et met les valeurs dans les variables

  Serial.print("Erreurs Checksums: ");Serial.print(failed_checksum); // message indiquant si erreur de validité des chaines reçues
  Serial.println(); Serial.println();

  //---- génération de l'adresse utilisable dans Googlemap
  Serial.println("Adresse pour google map : ");
  Serial.print("http://maps.google.com/maps?q=");
  Serial.print(latitude,5);
  Serial.print(",+");
  Serial.println(longitude,5);

} // fin de la fonction de gestion du GPS


// ////////////////////////// Fin du programme ////////////////////


// ////////////////////////// Mémo instructions ////////////////////
//-------- mémo librairie NewSoftSerial

// begin (long speed)
// end()

// int read()
// int available() // dispo que si connexion série testée est la connexion active

// NewSoftSerial active ()

// boolean overflow()
// flush()


// int library_version

// setTX(transmitPin)
// setRX(receivePin)

// enable_timer0(enable)

//--------------- mémo librairie TinyGPS

//boolean encode (char c)

//get_position (long *latitude, long *longitude, unsigned long *fix_age = 0)
//get_datetime (unsigned long *date, unsigned long *time, unsigned long *fix_age = 0)
//stats (unsigned long *chars, unsigned short *good_sentences, unsigned short *failed_cs)

//f_get_position (float *latitude, float *longitude, unsigned long *fix_age = 0)
//crack_datetime (int *year, byte *month, byte *day, *hour, byte *minute, byte *second, byte *hundredths = 0, unsigned long *fix_age = 0)
//long altitude()
//unsigned long speed ()
//unsigned long course()

//float f_altitude()
//float f_course()
//float f_speed_knots()
//float f_speed_mph()
//float f_speed_mps()
//float f_speed_kmph()
//int library_version ()
//float distance_between (float lat1, float long1, float lat2, float long2)



// ////////////////////////// Fin Mémo instructions ////////////////////