Aiutino per adattamento libreria

Salve,
nell'intendo di collegare il mio modulo gps ad arduino, stavo provando ad adattare una libreria scritta qualche tempo fa da DIYDrones.
La libreria in questione è questa:

/*
	GPS_MTK.cpp - Ublox GPS library for Arduino
	Code by Jordi Muñoz and Jose Julio. DIYDrones.com
	...
			
*/

#include "GPS_MTK.h"
#include <avr/interrupt.h>
#include "WProgram.h"


// Constructors ////////////////////////////////////////////////////////////////
GPS_MTK_Class::GPS_MTK_Class()
{
}


// Public Methods //////////////////////////////////////////////////////////////
void GPS_MTK_Class::Init(void)
{
	ck_a=0;
	ck_b=0;
	UBX_step=0;
	NewData=0;
	Fix=0;
	PrintErrors=0;
	GPS_timer=millis();   //Restarting timer...
	// Initialize serial port
	#if defined(__AVR_ATmega1280__)
		Serial1.begin(38400);         // Serial port 1 on ATMega1280
	#else
		Serial.begin(38400);
	#endif
}

// optimization : This code don´t wait for data, only proccess the data available
// We can call this function on the main loop (50Hz loop)
// If we get a complete packet this function calls parse_ubx_gps() to parse and update the GPS info.
void GPS_MTK_Class::Read(void)
{
  static unsigned long GPS_timer=0;
  byte data;
  int numc;
  
  #if defined(__AVR_ATmega1280__)    // If AtMega1280 then Serial port 1...
	numc = Serial1.available();
  #else
	numc = Serial.available();
  #endif
  if (numc > 0)
    for (int i=0;i<numc;i++)  // Process bytes received
      {
	  #if defined(__AVR_ATmega1280__)
        data = Serial1.read();
      #else
		data = Serial.read();
	  #endif
      switch(UBX_step)     //Normally we start from zero. This is a state machine
      {
      case 0:  
        if(data==0xB5)  // UBX sync char 1
          UBX_step++;   //OH first data packet is correct, so jump to the next step
        break; 
      case 1:  
        if(data==0x62)  // UBX sync char 2
          UBX_step++;   //ooh! The second data packet is correct, jump to the step 2
        else 
          UBX_step=0;   //Nop, is not correct so restart to step zero and try again.     
        break;
      case 2:
        UBX_class=data;
        ubx_checksum(UBX_class);
        UBX_step++;
        break;
      case 3:
        UBX_id=data;
        UBX_step=4;
        UBX_payload_length_hi=26;
		UBX_payload_length_lo=0;
		UBX_payload_counter=0;

        ubx_checksum(UBX_id);
        
        break;
      case 4:
	if (UBX_payload_counter < UBX_payload_length_hi)  // We stay in this state until we reach the payload_length
        {
          UBX_buffer[UBX_payload_counter] = data;
          ubx_checksum(data);
          UBX_payload_counter++;
          if (UBX_payload_counter==UBX_payload_length_hi)
            UBX_step++;
        }
        break;
      case 5:
        UBX_ck_a=data;   // First checksum byte
        UBX_step++;
        break;
      case 6:
        UBX_ck_b=data;   // Second checksum byte
       
	  // We end the GPS read...
        if((ck_a==UBX_ck_a)&&(ck_b==UBX_ck_b))   // Verify the received checksum with the generated checksum.. 
	  		parse_ubx_gps();               // Parse the new GPS packet
        else
		  {
		  if (PrintErrors)
			Serial.println("ERR:GPS_CHK!!");
		  }
        // Variable initialization
        UBX_step=0;
        ck_a=0;
        ck_b=0;
        GPS_timer=millis(); //Restarting timer...
        break;
	  }
    }    // End for...
  // If we don´t receive GPS packets in 2 seconds => Bad FIX state
  if ((millis() - GPS_timer)>2000)
    {
	Fix = 0;
	if (PrintErrors)
	  Serial.println("ERR:GPS_TIMEOUT!!");
    }
}

/****************************************************************
 * 
 ****************************************************************/
// Private Methods //////////////////////////////////////////////////////////////
void GPS_MTK_Class::parse_ubx_gps(void)
{
  int j;
//Verifing if we are in class 1, you can change this "IF" for a "Switch" in case you want to use other UBX classes.. 
//In this case all the message im using are in class 1, to know more about classes check PAGE 60 of DataSheet.
  if(UBX_class==0x01) 
  {
    switch(UBX_id)//Checking the UBX ID
    {


    case 0x05: //ID Custom
      j=0;
      Lattitude= join_4_bytes(&UBX_buffer[j]); // lon*10000000
      j+=4;
      Longitude = join_4_bytes(&UBX_buffer[j]); // lat*10000000
      j+=4;
      Altitude = join_4_bytes(&UBX_buffer[j]);  // MSL
      j+=4;
	  Ground_Speed = join_4_bytes(&UBX_buffer[j]);
      j+=4;
	  Ground_Course = join_4_bytes(&UBX_buffer[j]);
      j+=4;
	  NumSats=UBX_buffer[j];
	  j++;
	  Fix=UBX_buffer[j];
      j++;
	  Time = join_4_bytes(&UBX_buffer[j]);
      NewData=1;
      break;

      }
    }   
}


/****************************************************************
 * 
 ****************************************************************/
 // Join 4 bytes into a long
long GPS_MTK_Class::join_4_bytes(unsigned char Buffer[])
{
  union long_union {
	int32_t dword;
	uint8_t  byte[4];
} longUnion;

  longUnion.byte[3] = *Buffer;
  longUnion.byte[2] = *(Buffer+1);
  longUnion.byte[1] = *(Buffer+2);
  longUnion.byte[0] = *(Buffer+3);
  return(longUnion.dword);
}

/****************************************************************
 * 
 ****************************************************************/
// checksum algorithm
void GPS_MTK_Class::ubx_checksum(byte ubx_data)
{
  ck_a+=ubx_data;
  ck_b+=ck_a; 
}

GPS_MTK_Class GPS;

sostituendo
#include "WProgram.h"

con

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

compila senza errori.

Il problema è che il mio modulo gps è collegato sui pin 2 e 3, allora ho pensato di utilizzare SoftwareSerial.h modificando la libreria in questo modo:

#include "GPS_MTK.h"
#include <avr/interrupt.h>
#include <SoftwareSerial.h>

#if defined(ARDUINO) && ARDUINO >= 100
	#include "Arduino.h"
#else
	#include "WProgram.h"
#endif

#define RXPIN 2
#define TXPIN 3


// Constructors ////////////////////////////////////////////////////////////////
GPS_MTK_Class::GPS_MTK_Class()
{
}


// Public Methods //////////////////////////////////////////////////////////////
void GPS_MTK_Class::Init(void)
{
	ck_a=0;
	ck_b=0;
	UBX_step=0;
	NewData=0;
	Fix=0;
	PrintErrors=0;
	GPS_timer=millis();   //Restarting timer...
	// Initialize serial port
	SoftwareSerial uart_gps(RXPIN, TXPIN);
	uart_gps.begin(38400);
}

// optimization : This code don´t wait for data, only proccess the data available
// We can call this function on the main loop (50Hz loop)
// If we get a complete packet this function calls parse_ubx_gps() to parse and update the GPS info.
void GPS_MTK_Class::Read(void)
{
  static unsigned long GPS_timer=0;
  byte data;
  int numc;
  
  numc = uart_gps.available();
  
  if (numc > 0)
    for (int i=0;i<numc;i++)  // Process bytes received
      {

        data = uart_gps.read();
 
      switch(UBX_step)     //Normally we start from zero. This is a state machine
      {
      case 0:  
   ......

Quando compilo, però ottengo una marea di errori, gli errori si riducono a 2 se nel programma principale inserisco #include <SoftwareSerial.h> e sono:

D:\Arduino\arduino-1.0.4\libraries\GPS_MTK\GPS_MTK.cpp: In member function 'void GPS_MTK_Class::Read()':
D:\Arduino\arduino-1.0.4\libraries\GPS_MTK\GPS_MTK.cpp:74: error: 'uart_gps' was not declared in this scope

Purtroppo le mie conoscenze non vanno oltre e mi sono bloccato, avete qualche suggerimento?
Grazie

Tu dichiari la variabile SoftwareSerial uart_gps(RXPIN, TXPIN); dentro la init.
Messa così è una variabile locale (è nello scope della funzione init) cioè la vedi SOLO li dentro.

Il compilatore ti avvisa che la variabile nella read non è visibile (non è nello scope)

Devi dichiarare quella variabile tra le variabili della classe GPS_MTK_Class, ovvero nella GPS_MTK_Class.h tra le variabili private.

Posta anche il GPS_MTK_Class.h per capire come è fatto.

Prova cosi:

nel .h aggiungi la parte in blu

long UBX_ecefVZ;
SoftwareSerial *uart_gps;
void parse_ubx_gps();

nella init:

  // Initialize serial port
  uart_gps= new SoftwareSerial (2, 3);           // creai ora oggetto
  uart_gps->begin(38400);

Tutti i riferimenti di uart_gps. devono diventare uart_gps->

Nid69ita, intanto ti ringrazio, questo è GPS_MTK.h:

#ifndef GPS_MTK_h
#define GPS_MTK_h

#include <inttypes.h>

#define UBX_MAXPAYLOAD 60

class GPS_MTK_Class
{
  private:
    // Internal variables
	uint8_t ck_a;     // Packet checksum
	uint8_t ck_b;
	uint8_t UBX_step;
	uint8_t UBX_class;
	uint8_t UBX_id;
	uint8_t UBX_payload_length_hi;
	uint8_t UBX_payload_length_lo;
	uint8_t UBX_payload_counter;
	uint8_t UBX_buffer[UBX_MAXPAYLOAD];
	uint8_t UBX_ck_a;
	uint8_t UBX_ck_b;
	long GPS_timer;
	long UBX_ecefVZ;
	void parse_ubx_gps();
	void ubx_checksum(unsigned char ubx_data);
	long join_4_bytes(unsigned char Buffer[]);

  public:
    // Methods
	GPS_MTK_Class();
	void Init();
	void Read();
	// Properties
	long Time;          //GPS Millisecond Time of Week
	long Lattitude;     // Geographic coordinates
	long Longitude;
	long Altitude;
	long Ground_Speed;
	long Ground_Course;
	uint8_t NumSats;      // Number of visible satelites
	uint8_t Fix;        // 1:GPS FIX   0:No FIX (normal logic)
	uint8_t NewData;    // 1:New GPS Data
	uint8_t PrintErrors; // 1: To Print GPS Errors (for debug)
};

extern GPS_MTK_Class GPS;

#endif

Come mi consigli di modificarlo?

Come ho scritto sopra, nel .h devi spostare la variabile di tipo SoftwareSerial.
Però non può essere una variabile di tipo oggetto SoftwareSerial con la sua inizializzazione immediata.
Tra le variabili di una classe (l'oggetto è reale la classe solo teorica), non puoi creare anche l'oggetto SoftwareSerial, perciò deve essere un puntatore a oggetto SoftwareSerial.
metti questo:
SoftwareSerial *uart_gps;

#ifndef GPS_MTK_h
#define GPS_MTK_h

#include <inttypes.h>

#define UBX_MAXPAYLOAD 60

class GPS_MTK_Class
{
  private:
    // Internal variables
	uint8_t ck_a;     // Packet checksum
	uint8_t ck_b;
	uint8_t UBX_step;
	uint8_t UBX_class;
	uint8_t UBX_id;
	uint8_t UBX_payload_length_hi;
	uint8_t UBX_payload_length_lo;
	uint8_t UBX_payload_counter;
	uint8_t UBX_buffer[UBX_MAXPAYLOAD];
	uint8_t UBX_ck_a;
	uint8_t UBX_ck_b;
	long GPS_timer;
	long UBX_ecefVZ;
	void parse_ubx_gps();
	void ubx_checksum(unsigned char ubx_data);
	long join_4_bytes(unsigned char Buffer[]);
        SoftwareSerial *uart_gps;                               // aggiunta NID69ITA

  public:
    // Methods
	GPS_MTK_Class();
	void Init();
	void Read();
	// Properties
	long Time;          //GPS Millisecond Time of Week
	long Lattitude;     // Geographic coordinates
	long Longitude;
	long Altitude;
	long Ground_Speed;
	long Ground_Course;
	uint8_t NumSats;      // Number of visible satelites
	uint8_t Fix;        // 1:GPS FIX   0:No FIX (normal logic)
	uint8_t NewData;    // 1:New GPS Data
	uint8_t PrintErrors; // 1: To Print GPS Errors (for debug)
};

extern GPS_MTK_Class GPS;

#endif

Avendo un puntatore e NON un oggetto inizializzato, dovrai modificare anche il file .cpp

// Initialize serial port
  uart_gps= new SoftwareSerial (2, 3);           // crei ora oggetto e lo assegni
  uart_gps->begin(38400);

Ricorda che ovunque usi uart_gps dovrai usare -> invece di .

Ciao NID69ITA,
ho fatto come mi hai consigliato, inoltre ho incluso #include <SoftwareSerial.h> nel .h, ma adesso mi da il seguente errore di compilazione

In file included from GPS_MTK_test.ino:10:
D:\Arduino\arduino-1.0.4\libraries\GPS_MTK/GPS_MTK.h:28: error: ISO C++ forbids declaration of 'SoftwareSerial' with no type
D:\Arduino\arduino-1.0.4\libraries\GPS_MTK/GPS_MTK.h:28: error: expected ';' before '*' token

Credo hai scritto qualcosa di errato.
Posta sia il file .h che il file .cpp

EDIT: forse ho dimenticato di farti mettere
#include <SoftwareSerial.h> dentro al GPS_MTK_h

Il .h

#ifndef GPS_MTK_h
#define GPS_MTK_h

#include <inttypes.h>
#include <SoftwareSerial.h>
#define UBX_MAXPAYLOAD 60

class GPS_MTK_Class
{
  private:
    // Internal variables
	uint8_t ck_a;     // Packet checksum
	uint8_t ck_b;
	uint8_t UBX_step;
	uint8_t UBX_class;
	uint8_t UBX_id;
	uint8_t UBX_payload_length_hi;
	uint8_t UBX_payload_length_lo;
	uint8_t UBX_payload_counter;
	uint8_t UBX_buffer[UBX_MAXPAYLOAD];
	uint8_t UBX_ck_a;
	uint8_t UBX_ck_b;
	long GPS_timer;
	long UBX_ecefVZ;
	void parse_ubx_gps();
	void ubx_checksum(unsigned char ubx_data);
	long join_4_bytes(unsigned char Buffer[]);
	SoftwareSerial *uart_gps; 
	
  public:
    // Methods
	GPS_MTK_Class();
	void Init();
	void Read();
	// Properties
	long Time;          //GPS Millisecond Time of Week
	long Lattitude;     // Geographic coordinates
	long Longitude;
	long Altitude;
	long Ground_Speed;
	long Ground_Course;
	uint8_t NumSats;      // Number of visible satelites
	uint8_t Fix;        // 1:GPS FIX   0:No FIX (normal logic)
	uint8_t NewData;    // 1:New GPS Data
	uint8_t PrintErrors; // 1: To Print GPS Errors (for debug)
};

extern GPS_MTK_Class GPS;

#endif

e GPS_MTK.cpp

#include "GPS_MTK.h"
//#include <avr/interrupt.h>
//#include <SoftwareSerial.h>

#if defined(ARDUINO) && ARDUINO >= 100
	#include "Arduino.h"
#else
	#include "WProgram.h"
#endif

#define RXPIN 2
#define TXPIN 3
//SoftwareSerial uart_gps(RXPIN, TXPIN);

// Constructors ////////////////////////////////////////////////////////////////
GPS_MTK_Class::GPS_MTK_Class()
{
}


// Public Methods //////////////////////////////////////////////////////////////
void GPS_MTK_Class::Init(void)
{
	ck_a=0;
	ck_b=0;
	UBX_step=0;
	NewData=0;
	Fix=0;
	PrintErrors=0;
	GPS_timer=millis();   //Restarting timer...
	
	// Initialize serial port
    uart_gps= new SoftwareSerial (2, 3);           // crei ora oggetto e lo assegni
    uart_gps->begin(38400);
	//uart_gps.begin(38400);
}

// optimization : This code don´t wait for data, only proccess the data available
// We can call this function on the main loop (50Hz loop)
// If we get a complete packet this function calls parse_ubx_gps() to parse and update the GPS info.
void GPS_MTK_Class::Read(void)
{
  static unsigned long GPS_timer=0;
  byte data;
  int numc;
  
  numc = uart_gps.available();
  
  if (numc > 0)
    for (int i=0;i<numc;i++)  // Process bytes received
      {

etc..

GPS_MTK.zip (3.05 KB)

Se metti però tutto il file .h e il file .cpp in un unico sketch a me lo compila.
Non sò perchè separato non lo compila

#include "Arduino.h"

#include <inttypes.h>
#include <SoftwareSerial.h>
#define UBX_MAXPAYLOAD 60

class GPS_MTK_Class
{
  private:
    // Internal variables
	uint8_t ck_a;     // Packet checksum
	uint8_t ck_b;
	uint8_t UBX_step;
	uint8_t UBX_class;
	uint8_t UBX_id;
	uint8_t UBX_payload_length_hi;
	uint8_t UBX_payload_length_lo;
	uint8_t UBX_payload_counter;
	uint8_t UBX_buffer[UBX_MAXPAYLOAD];
	uint8_t UBX_ck_a;
	uint8_t UBX_ck_b;
	long GPS_timer;
	long UBX_ecefVZ;
	void parse_ubx_gps();
	void ubx_checksum(unsigned char ubx_data);
	long join_4_bytes(unsigned char Buffer[]);
	SoftwareSerial* uart_gps; 
	
  public:
    // Methods
	GPS_MTK_Class();
	void Init();
	void Read();
	// Properties
	long Time;          //GPS Millisecond Time of Week
	long Lattitude;     // Geographic coordinates
	long Longitude;
	long Altitude;
	long Ground_Speed;
	long Ground_Course;
	uint8_t NumSats;      // Number of visible satelites
	uint8_t Fix;        // 1:GPS FIX   0:No FIX (normal logic)
	uint8_t NewData;    // 1:New GPS Data
	uint8_t PrintErrors; // 1: To Print GPS Errors (for debug)
};

extern GPS_MTK_Class GPS;

#define RXPIN 2
#define TXPIN 3

// Constructors ////////////////////////////////////////////////////////////////
GPS_MTK_Class::GPS_MTK_Class()
{}

// Public Methods //////////////////////////////////////////////////////////////
void GPS_MTK_Class::Init(void)
{
	ck_a=0;
	ck_b=0;
	UBX_step=0;
	NewData=0;
	Fix=0;
	PrintErrors=0;
	GPS_timer=millis();   //Restarting timer...
	
	// Initialize serial port
    uart_gps= new SoftwareSerial(2,3);           // crei ora oggetto e lo assegni
    uart_gps->begin(38400);
	//uart_gps.begin(38400);
}

// optimization : This code don´t wait for data, only proccess the data available
// We can call this function on the main loop (50Hz loop)
// If we get a complete packet this function calls parse_ubx_gps() to parse and update the GPS info.
void GPS_MTK_Class::Read(void)
{
  static unsigned long GPS_timer=0;
  byte data;
  int numc;
  
  numc = uart_gps->available();
  if (numc > 0)
    for (int i=0;i<numc;i++)  // Process bytes received
    { data = uart_gps->read();
      switch(UBX_step)     //Normally we start from zero. This is a state machine
      {
      case 0:  
        if(data==0xB5)  // UBX sync char 1
          UBX_step++;   //OH first data packet is correct, so jump to the next step
        break; 
      case 1:  
        if(data==0x62)  // UBX sync char 2
          UBX_step++;   //ooh! The second data packet is correct, jump to the step 2
        else 
          UBX_step=0;   //Nop, is not correct so restart to step zero and try again.     
        break;
      case 2:
        UBX_class=data;
        ubx_checksum(UBX_class);
        UBX_step++;
        break;
      case 3:
        UBX_id=data;
        UBX_step=4;
        UBX_payload_length_hi=26;
		UBX_payload_length_lo=0;
		UBX_payload_counter=0;

        ubx_checksum(UBX_id);
        
        break;
      case 4:
	if (UBX_payload_counter < UBX_payload_length_hi)  // We stay in this state until we reach the payload_length
        {
          UBX_buffer[UBX_payload_counter] = data;
          ubx_checksum(data);
          UBX_payload_counter++;
          if (UBX_payload_counter==UBX_payload_length_hi)
            UBX_step++;
        }
        break;
      case 5:
        UBX_ck_a=data;   // First checksum byte
        UBX_step++;
        break;
      case 6:
        UBX_ck_b=data;   // Second checksum byte
       
	  // We end the GPS read...
        if((ck_a==UBX_ck_a)&&(ck_b==UBX_ck_b))   // Verify the received checksum with the generated checksum.. 
	  		parse_ubx_gps();               // Parse the new GPS packet
        else
		  {
		  if (PrintErrors)
			Serial.println("ERR:GPS_CHK!!");
		  }
        // Variable initialization
        UBX_step=0;
        ck_a=0;
        ck_b=0;
        GPS_timer=millis(); //Restarting timer...
        break;
	  }
    }    // End for...
  // If we don´t receive GPS packets in 2 seconds => Bad FIX state
  if ((millis() - GPS_timer)>2000)
    {
	Fix = 0;
	if (PrintErrors)
	  Serial.println("ERR:GPS_TIMEOUT!!");
    }
}

// Private Methods //////////////////////////////////////////////////////////////
void GPS_MTK_Class::parse_ubx_gps(void)
{
  int j;
//Verifing if we are in class 1, you can change this "IF" for a "Switch" in case you want to use other UBX classes.. 
//In this case all the message im using are in class 1, to know more about classes check PAGE 60 of DataSheet.
  if(UBX_class==0x01) 
  {
    switch(UBX_id)//Checking the UBX ID
    {


    case 0x05: //ID Custom
      j=0;
      Lattitude= join_4_bytes(&UBX_buffer[j]); // lon*10000000
      j+=4;
      Longitude = join_4_bytes(&UBX_buffer[j]); // lat*10000000
      j+=4;
      Altitude = join_4_bytes(&UBX_buffer[j]);  // MSL
      j+=4;
	  Ground_Speed = join_4_bytes(&UBX_buffer[j]);
      j+=4;
	  Ground_Course = join_4_bytes(&UBX_buffer[j]);
      j+=4;
	  NumSats=UBX_buffer[j];
	  j++;
	  Fix=UBX_buffer[j];
      j++;
	  Time = join_4_bytes(&UBX_buffer[j]);
      NewData=1;
      break;

      }
    }   
}

// Join 4 bytes into a long
long GPS_MTK_Class::join_4_bytes(unsigned char Buffer[])
{
  union long_union {
	int32_t dword;
	uint8_t  byte[4];
} longUnion;

  longUnion.byte[3] = *Buffer;
  longUnion.byte[2] = *(Buffer+1);
  longUnion.byte[1] = *(Buffer+2);
  longUnion.byte[0] = *(Buffer+3);
  return(longUnion.dword);
}

// checksum algorithm
void GPS_MTK_Class::ubx_checksum(byte ubx_data)
{
  ck_a+=ubx_data;
  ck_b+=ck_a; 
}

GPS_MTK_Class GPS;

void setup()
{}
  
void loop()
{}

Cosi funziona ma è strano, il compilatore sembra arrabbiarsi perchè richiamiamo troppe volte (sembra) il file h di softwareserial.
L'include SoftwareSerial.h viene fatto nel file GPS_MTK.h e poi lo rifacevamo anche in GPS_MTK.cpp che richiama anche GPS_MTK.h
Ora è corretto ma non mi spiego perchè siamo costretti a mettere quella prima riga nello sketch (include di SoftwareSerial.h)
Se la togli hai il famigerato errore. Fatto così a me compila.

1.sketch

#include <SoftwareSerial.h>
#include <GPS_MTK.h>

void setup()
{}

void loop()
{}

2.file .h

#include "Arduino.h"

#ifndef GPS_MTK_h
#define GPS_MTK_h
#include <SoftwareSerial.h>
#include <inttypes.h>

#define UBX_MAXPAYLOAD 60

class GPS_MTK_Class
{ private:
    // Internal variables
	uint8_t ck_a;     // Packet checksum
	uint8_t ck_b;
	uint8_t UBX_step;
	uint8_t UBX_class;
	uint8_t UBX_id;
	uint8_t UBX_payload_length_hi;
	uint8_t UBX_payload_length_lo;
	uint8_t UBX_payload_counter;
	uint8_t UBX_buffer[UBX_MAXPAYLOAD];
	uint8_t UBX_ck_a;
	uint8_t UBX_ck_b;
	long GPS_timer;
	long UBX_ecefVZ;
	void parse_ubx_gps();
	void ubx_checksum(unsigned char ubx_data);
	long join_4_bytes(unsigned char Buffer[]);
	SoftwareSerial* uart_gps; 
  public:
    // Methods
	GPS_MTK_Class();
	void Init();
	void Read();
	// Properties
	long Time;          //GPS Millisecond Time of Week
	long Lattitude;     // Geographic coordinates
	long Longitude;
	long Altitude;
	long Ground_Speed;
	long Ground_Course;
	uint8_t NumSats;      // Number of visible satelites
	uint8_t Fix;        // 1:GPS FIX   0:No FIX (normal logic)
	uint8_t NewData;    // 1:New GPS Data
	uint8_t PrintErrors; // 1: To Print GPS Errors (for debug)
};

extern GPS_MTK_Class GPS;
#endif

3.file .cpp

#include "Arduino.h"

#include <inttypes.h>
#define UBX_MAXPAYLOAD 60
#include <GPS_MTK.h>

#define RXPIN 2
#define TXPIN 3

// Constructors ////////////////////////////////////////////////////////////////
GPS_MTK_Class::GPS_MTK_Class()
{}

// Public Methods //////////////////////////////////////////////////////////////
void GPS_MTK_Class::Init(void)
{
	ck_a=0;
	ck_b=0;
	UBX_step=0;
	NewData=0;
	Fix=0;
	PrintErrors=0;
	GPS_timer=millis();   //Restarting timer...
	
	// Initialize serial port
    uart_gps= new SoftwareSerial(2,3);           // crei ora oggetto e lo assegni
    uart_gps->begin(38400);
	//uart_gps.begin(38400);
}

// optimization : This code don´t wait for data, only proccess the data available
// We can call this function on the main loop (50Hz loop)
// If we get a complete packet this function calls parse_ubx_gps() to parse and update the GPS info.
void GPS_MTK_Class::Read(void)
{
  static unsigned long GPS_timer=0;
  byte data;
  int numc;
  
  numc = uart_gps->available();
  if (numc > 0)
    for (int i=0;i<numc;i++)  // Process bytes received
    { data = uart_gps->read();
      switch(UBX_step)     //Normally we start from zero. This is a state machine
      {
      case 0:  
        if(data==0xB5)  // UBX sync char 1
          UBX_step++;   //OH first data packet is correct, so jump to the next step
        break; 
      case 1:  
        if(data==0x62)  // UBX sync char 2
          UBX_step++;   //ooh! The second data packet is correct, jump to the step 2
        else 
          UBX_step=0;   //Nop, is not correct so restart to step zero and try again.     
        break;
      case 2:
        UBX_class=data;
        ubx_checksum(UBX_class);
        UBX_step++;
        break;
      case 3:
        UBX_id=data;
        UBX_step=4;
        UBX_payload_length_hi=26;
		UBX_payload_length_lo=0;
		UBX_payload_counter=0;

        ubx_checksum(UBX_id);
        
        break;
      case 4:
	if (UBX_payload_counter < UBX_payload_length_hi)  // We stay in this state until we reach the payload_length
        {
          UBX_buffer[UBX_payload_counter] = data;
          ubx_checksum(data);
          UBX_payload_counter++;
          if (UBX_payload_counter==UBX_payload_length_hi)
            UBX_step++;
        }
        break;
      case 5:
        UBX_ck_a=data;   // First checksum byte
        UBX_step++;
        break;
      case 6:
        UBX_ck_b=data;   // Second checksum byte
       
	  // We end the GPS read...
        if((ck_a==UBX_ck_a)&&(ck_b==UBX_ck_b))   // Verify the received checksum with the generated checksum.. 
	  		parse_ubx_gps();               // Parse the new GPS packet
        else
		  {
		  if (PrintErrors)
			Serial.println("ERR:GPS_CHK!!");
		  }
        // Variable initialization
        UBX_step=0;
        ck_a=0;
        ck_b=0;
        GPS_timer=millis(); //Restarting timer...
        break;
	  }
    }    // End for...
  // If we don´t receive GPS packets in 2 seconds => Bad FIX state
  if ((millis() - GPS_timer)>2000)
    {
	Fix = 0;
	if (PrintErrors)
	  Serial.println("ERR:GPS_TIMEOUT!!");
    }
}

// Private Methods //////////////////////////////////////////////////////////////
void GPS_MTK_Class::parse_ubx_gps(void)
{
  int j;
//Verifing if we are in class 1, you can change this "IF" for a "Switch" in case you want to use other UBX classes.. 
//In this case all the message im using are in class 1, to know more about classes check PAGE 60 of DataSheet.
  if(UBX_class==0x01) 
  {
    switch(UBX_id)//Checking the UBX ID
    {


    case 0x05: //ID Custom
      j=0;
      Lattitude= join_4_bytes(&UBX_buffer[j]); // lon*10000000
      j+=4;
      Longitude = join_4_bytes(&UBX_buffer[j]); // lat*10000000
      j+=4;
      Altitude = join_4_bytes(&UBX_buffer[j]);  // MSL
      j+=4;
	  Ground_Speed = join_4_bytes(&UBX_buffer[j]);
      j+=4;
	  Ground_Course = join_4_bytes(&UBX_buffer[j]);
      j+=4;
	  NumSats=UBX_buffer[j];
	  j++;
	  Fix=UBX_buffer[j];
      j++;
	  Time = join_4_bytes(&UBX_buffer[j]);
      NewData=1;
      break;

      }
    }   
}

// Join 4 bytes into a long
long GPS_MTK_Class::join_4_bytes(unsigned char Buffer[])
{
  union long_union {
	int32_t dword;
	uint8_t  byte[4];
} longUnion;

  longUnion.byte[3] = *Buffer;
  longUnion.byte[2] = *(Buffer+1);
  longUnion.byte[1] = *(Buffer+2);
  longUnion.byte[0] = *(Buffer+3);
  return(longUnion.dword);
}

// checksum algorithm
void GPS_MTK_Class::ubx_checksum(byte ubx_data)
{
  ck_a+=ubx_data;
  ck_b+=ck_a; 
}

GPS_MTK_Class GPS;