//----------------------------------------
// GPS copernicus et deulingne de SNOOTLAB
//----------------------------------------
// Arduino UNO
//----------------------------------------
//Affichage sur le LCD des coordonnées et conversion
//Affichage de l'heure GPS
//Suivant manipulation du bouton directionnel
//Visualisation des données dans une fenetre terminal.
// 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
#include <NewSoftSerial.h> // Inclusion de la librairie pour communication série logicielle
#include "Wire.h"
#include <TinyGPS.h> // inclusion de la librairie pour module GPS - nécessite communication série logicielle
#include <Deuligne.h>
Deuligne lcd;// Avant utilisation, il faut installer manuellement cette librairie
int escape=0;
// 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 ---
int x;
int y;
int d;
int m;
int D;
int M;
const int brocheTX=2; // Constante pour la broche 2
const int brocheRX=3; // Constante pour la broche 3
String chaineReceptionGPS=""; // chaine réception
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 //////////////////////////
void setup() { // debut de la fonction setup()
Serial.begin(115200); // initialise connexion série matérielle à 115200 bauds
mySoftSerial.begin(4800); // initialise connexion série logicielle à 4800 bauds
lcd.init();
// --- 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
} // 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 ---
mySoftSerial.flush(); // vide le buffer série logiciel avant envoi requete
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
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
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();
}
//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
x = latitude ;
y = 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,¢iemes); // 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);
lcd.clear ();
x=latitude;//mise en x de la valeur de latitude
y=longitude;// mise en y de la valeur longitude
d=(((latitude-x)*1000*60)/1000);// formule de conversion en degres sexagesime
m=((((latitude-x)*1000*60)/1000)-d)*60;// conversion pour latitude
lcd.print ( x ); lcd.print ( "d "); lcd.print (d); lcd.print ( "m");lcd.print (m); // affichage des coordonnées
D=(((longitude-y)*1000*60)/1000); // conversion en degres sexagesime
M=((((longitude-y)*1000*60)/1000)-D)*60;
lcd.setCursor ( 0,1);
lcd.print ( y ); lcd.print ("d ");lcd.print (D); lcd.print ( "m");lcd.print (M);;// affichage du resultat
lcd.setCursor ( 9,1);
lcd.print(gps.f_altitude()); // affichage de l'altitude.
lcd.setCursor ( 15 , 1);
lcd.print ("m");
escape=lcd.get_key();
delay(50);
if (escape==4) lcd.clear ();
if (escape==4)lcd.print(heure+1, DEC);
if (escape==4)lcd.print(":");
if (escape==4)lcd.print(minute, DEC);
if (escape==4)lcd.print(":");
if (escape==4)lcd.print(seconde, DEC);
if (escape==4) delay(1000);
if (escape==0) lcd.clear ();
if (escape==0)lcd.print(latitude,5);
if (escape==0)lcd.setCursor(0,1);
if (escape==0)lcd.print(longitude,5);
if (escape==0)delay(1000);
if (escape==1) lcd.clear();
if ( escape==1) lcd.print (chaineReceptionGPS);
if (escape==1) lcd.scrollDisplayRight();
if (escape==1)delay(1000);
} // 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 ////////////////////
Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 0 invités