Centrale de navigation Low Cost sur plateforme Arduino (2) - Module GPS

Publié le 3 Novembre 2013

Centrale de navigation Low Cost sur plateforme Arduino (2) - Module GPS

Branchement d'un module GPS Parallax PMB-688

Dans le précédent article, le GPS était simulé (une même phrase NMEA était transmise périodiquement comme l'aurait fait un "vrai" GPS).

Cette fois nous allons brancher un module GPS qui enverra des trames NMEA sur le port série de l'ARDUINO. Ces trames sont interceptées et mixées avec les trames instrument sur le port Ethernet. Le module Ethernet est raccordé au Wifi.

Les programmes Iregatta sur tablette ou OpenCPN et PolarCOM sur PC portable reçoivent et exploitent les trames NMEA via le réseau WiFi

L'installation de ce module est l'occasion d'étudier le codage d'une entrée série sur un PIN libre de ARDUINO UNO en utilisant la SoftwareSerial Library.

Le protocole NMEA

Les trames constituées d'un nombre variable de caractères ASCII. Elles commencent par "$" et se terminent par le caractère LF (ligne suivante). Les cinq premiers caractères suivant le "$" indiquent la source (GPS ou instrument) sur 2 caractères et le type de trame sur 3 caractères: GPRMC = trame RMC envoyée par un GPS

Dans une trame, les champs d' informations sont séparées par une virgule. Le caractère * à la fin de la phrase est suivi du checksum.

Exemple de trame:

$GPRMC,131149.000,A,5038.4321,N,00259.2262,E,0.00,151.02,031113,,,A*67
  • GPRMC Time, date, position, course and speed dat
  • GPGGA Time, position and fix type data
  • GPGSA GPS receiver operating mode, satellites used in the position solution, and DOP values
  • GPGSV Number of GPS satellites in view satellite ID numbers, elevation, azimuth

Spécifications NMEA

Structure du programme

Aprés la séquence d'initialisation, le programme tourne en boucle en réalisant séquentiellement les actions suivantes:

  • Lecture de l'entrée GPS, récupération des trames et envoi sur Ethernet
  • Lecture des entrées analogiques correspondant aux capteurs Wind Speed et Wind direction. Construction de la phrase MWV et envoi sur Ethernet
  • Lecture de l'entrée analogique correspondant au capteur Speedo. construction de la phrase VHW et envoi sur Ethernet
  • pause de 0,5 sec

La principale difficulté est de récupèrer "proprement" les trames NMEA sur la "pseudo" interface série.

DETAIL DU CODE

/* ARDUINO NMEA Ethernet Multiplexer

Boards: Arduino UNO & Ethernet Shield
GPS module: Parallax PMB-688
include an NMEA Checksum routine

Analog Inputs:
A5: Wind speed
A4: Wind angle
A3: Water speed
Digital Input;
2: GPS Module (4800 bps)

Output:
Ethernet interface: IP: 192.168.0.177 TCP port number: 9999

SoftwareSerialLibrary: RX buffer is set to 256 instead of 64. This line has to be modified in SoftwareSerial.h:
#define _SS_MAX_RX_BUFF 256 // RX buffer size 256 instead of 64

GPS Sentence for example or debugging: GPRMC,220516,A,5133.82,N,00042.24,W,3.8,4.8,130694,004.2,W


*/


#include <SPI.h>
#include <Ethernet.h>
#include <SoftwareSerial.h> // use of SoftwareSerial Library

SoftwareSerial GPS(2,11); // RX on pin 2 (GPS DATA)



char CSSentence[85] = "" ; //string for sentence assembly
char GPSSentence[85] = "" ;
char MWVSentence[85] = "" ; //string for MVW for sentence assembly
char VHWSentence[85] = "" ; //string for VHW sentence assembly
char NMEASentence[85] = "" ; //string for NMEA sentence
int cs ; //checksum

// network configuration. gateway and subnet are optional.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // the MAC (ethernet hardware) address for the shield
byte ip[] = { 192, 168, 0, 177 }; //the IP address for the shield
byte gateway[] = { 192, 168, 0, 1 }; // the router's gateway address
byte subnet[] = { 255, 255, 255, 0 }; // the subnet

EthernetServer server = EthernetServer(9999); // telnet defaults to port 9999


///////////////////////////////// INITIALISATION /////////////////////////////////////////

void setup()
{
Ethernet.begin(mac, ip, gateway, subnet); // initialize the ethernet device
server.begin(); // start listening for clients
Serial.begin(9600); // Open serial communications and wait for port to open:
GPS.begin(4800); // Start software serial port
}


////////////////////////////////// LOOP ///////////////////////////////////////////////////

void loop()
{
char b[300]="0"; //initialize buffer b
char c[300]="0"; //initialize buffer c
int Z = 0;
int Y = 0; // initialize buffer index

EthernetClient client = server.available(); // if an incoming client connects, there will be bytes available to read:


////////////////////////////// GPS section /////////////////////////////////////
// read GPS input and write NMEA complete sentences on ethernet

GPS.listen(); // start listening on PIN 2

// test if incomplete sentence
if (GPS.read()=='$') {b[Y]='$';Y++;} else { // if begining of a sentence,
if (GPS.read() != -1){
while (GPS.read()!=10); // 10=LF, 13=CR if incomplete sentence,flush buffer
} else {delay (200);} // else delay for receiving datas
}

// main loop: read NMEA sentences and print on Ethernet
while (GPS.available() > 0) { // while there is data coming in, read it
b[Y]= GPS.read();
Y++;
if (b[Y-1]==10) { // line feed (LF) test - if NMEA sentence is complete, print it
server.print(b); // Ethernet print
Serial.print(b); // Serial used for debugging
for (Z=0;Z<Y;Z++) { //clear buffer
b[Z]=0;
}
Y=0; // re-initialize index
}
}

///////////////////////// Analog Sensors section /////////////////////////////

///////////////////////// MWV Sentence - Wind Speed and Angle //////////

//Assemble a sentance of the various parts so that we can calculate the proper checksum
strcpy(MWVSentence,"PIMWV,"); // PIMWV: P (prefix for all proprietary devices) and I for instrument
Z=analogRead(5)/2; // read Pin 5 : Relative wind Direction - Wind Direction can go from 0 to 360°
sprintf(b,"%d",Z);
strcat(MWVSentence, b);
strcat(MWVSentence, ",R,");

Z=analogRead(4)/2; //read Pin 4 Relative Wind Speed - Wind speed can go from 0 to 50 knots
sprintf(b,"%d",Z/10); //b represent the knots
sprintf(c,".%d",(Z-(Z/10)*10)); //c represent the deci knots
strcat(MWVSentence, b);
strcat(MWVSentence, c);
strcat(MWVSentence, ",N,A");

EtherNMEA(MWVSentence); // Write MWV Sentence on Ethernet with Checksum
delay (10);

//////////// ////////////// VHW Sentence - Water Speed /////////////////

Z=analogRead(3)/5; // read Pin 3 : Boat Speed - Speed from 0 to 20 Knots - resolution of 0.1 Knots
strcpy(VHWSentence, "PIVHW,,T,211,M,");
sprintf(b,"%d",Z/10); //b represent the knots
sprintf(c,".%d",(Z-(Z/10)*10)); //c represent the deci knots
strcat(VHWSentence, b);
strcat(VHWSentence, c);
strcat(VHWSentence, ",N,0.0,K");

EtherNMEA(VHWSentence); // Write VHW sentence on Ethernet with Checksum



//////////////////////// END OF LOOP //////////////////////////

delay (600); // LOOP Tempo

}

///////////////////////////// FUNCTIONS //////////////////////////////////////


String Checksum(char* CSSentence) {
cs=0; //clear any old checksum
char b[10]="0";
//return b;

for (int n=0; n < strlen(CSSentence); n++) {
cs ^= CSSentence[n]; //calculates the checksum
}
sprintf(b,"%02X",cs);
return b;
}

void EtherNMEA (char* NMEASentence) {
server.print("$"); // Assemble the final message and send it out Ethernet
server.print(NMEASentence);
server.print("*");
server.println(Checksum(NMEASentence)); // Call Checksum function
Serial.print("$"); // Assemble the final message and send it out the serial port
Serial.print(NMEASentence);
Serial.print("*");
Serial.println(Checksum(NMEASentence)); // Call Checksum function
}

Exemples de trames NMEA transmises:

PRE.cjk { font-family: "WenQuanYi Zen Hei Mono",monospace; }PRE.ctl { font-family: "Lohit Hindi",monospace; }P { margin-bottom: 0.08in; }

$GPRMC,131134.000,A,5038.4321,N,00259.2262,E,0.00,151.02,031113,,,A*6D 
$PIMWV,262,R,14.7,N,A*0E 
$PIVHW,,T,211,M,9.2,N,0.0,K*75 
$GPGGA,131135.000,5038.4321,N,00259.2262,E,1,10,0.9,58.9,M,47.2,M,,0000*65 
$GPGSA,A,3,03,27,11,22,32,19,01,28,20,14,,,1.8,0.9,1.5*35 
$GPRMC,131135.000,A,5038.4321,N,00259.2262,E,0.00,151.02,031113,,,A*6C 
$PIMWV,262,R,14.7,N,A*0E 
$PIVHW,,T,211,M,9.2,N,0.0,K*75 
$GPGGA,131136.000,5038.4321,N,00259.2262,E,1,10,0.9,58.9,M,47.2,M,,0000*66 
$GPGSA,A,3,03,27,11,22,32,19,01,28,20,14,,,1.8,0.9,1.5*35 
$GPRMC,131136.000,A,5038.4321,N,00259.2262,E,0.00,151.02,031113,,,A*6F 
$PIMWV,262,R,14.7,N,A*0E 
$PIVHW,,T,211,M,9.2,N,0.0,K*75 
$GPGGA,131137.000,5038.4321,N,00259.2262,E,1,10,0.9,58.9,M,47.2,M,,0000*67 
$GPGSA,A,3,03,27,11,22,32,19,01,28,20,14,,,1.8,0.9,1.5*35 
$PIMWV,262,R,14.7,N,A*0E 
$PIVHW,,T,211,M,9.2,N,0.0,K*75 
$GPGSV,3,2,12,03,36,159,18,22,31,056,26,14,31,095,22,27,30,146,17*74 
$GPGSV,3,3,12,28,27,308,18,06,20,147,,20,10,222,33,18,01,048,*74 
$GPRMC,131137.000,A,5038.4321,N,00259.2262,E,0.00,151.02,031113,,,A*6E 
$PIMWV,262,R,14.7,N,A*0E 
$PIVHW,,T,211,M,9.2,N,0.0,K*75

Rédigé par Jerome Delecour

Publié dans #Instruments

Repost0
Pour être informé des derniers articles, inscrivez vous :
Commenter cet article