I use a Adafruit Ultimate GPS. Using either the Adafruit Library or the TinyGPS++ library, I follow a set procedure to get data from the GPS unit.
The procedure I use is to have one routine, either interrupt driven or a freeRTOS task, running at 1ms asking the gps for a gps data read. In the main loop or another task I ask if the data read was successful and to read/parse the data.
code snippets:
In example for the non-freeRTOS procedure:
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <MsTimer2.h>
//pin3 to GPS rx - yellow wire
//pin2 to GPS tx - orange wire
SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
void GPSSIGNAL()
{
//cause a GPS data read so that the
//if (GPS.newNMEAreceived())
//can do its thing
GPS.read();
}
void setup() {
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // has speed n altitude
// Note you must send both commands below to change both the output rate (how often the position
// is written to the serial line), and the position fix rate.
// 1 Hz update rate
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
GPS.sendCommand(PMTK_API_SET_FIX_CTL_1HZ);
//turn off antenna data being sent
GPS.sendCommand("$PGCMD,33,0*6D/r/n");
//speed threshold level
//0/0.2/0.4/0.5/0.8/1.0/1.5/2.0 m/s
//GPS.sendCommand("$PMTK397,0.2*3F/r/n");
// //set time on ms for overflow, each overflow causes xFunc, void w no parameters, to be called
MsTimer2::set(1, GPSSIGNAL);
//enable interrupt
MsTimer2::start();
//disable interrupt
//MsTimer2::stop()
}
void loop() {
//leave this code alone!!!!!!!!!!!!!!!!!!!!!
//query GPS: has a new complete chunk of data been received?
if (GPS.newNMEAreceived())
{
//if received cause parse data
if (!GPS.parse(GPS.lastNMEA()))
//else exit routine
return;
}
// other code below to read the parsed data if the above is successful
}
My freeRTOS code using TinyGPSplus
#include <TinyGPS++.h>
#include <HardwareSerial.h>
#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#define GPS_Parse ( 1 << 4 ) //10000
EventGroupHandle_t eg;
HardwareSerial GPSSerial(2);
// Connect to the GPS on the hardware port
// The TinyGPS++ object
TinyGPSPlus GPS;
/* create a hardware timer */
hw_timer_t * timer = NULL;
// timer ISR callback set at 1000X a second
void IRAM_ATTR onTimer()
{
BaseType_t xHigherPriorityTaskWoken;
//
if ( (xSemaphoreTakeFromISR(sema_GPS_Gate, &xHigherPriorityTaskWoken)) == pdTRUE ) // grab semaphore, no wait
{
xEventGroupSetBitsFromISR(eg, GPS_Parse, &xHigherPriorityTaskWoken); // trigger every 1mS, if not already processing
}
} // void IRAM_ATTR onTimer()
void setup()
{
eg = xEventGroupCreate();
//
GPSSerial.begin( GPS_DataBits ); // begin GPS hardwareware serial
//
vTaskDelay( pdMS_TO_TICKS( OneK ) ); // delay one second
timer = timerBegin( TIMER_FOUR, TimerDivider, true );
timerAttachInterrupt( timer, &onTimer, true );
timerAlarmWrite(timer, OneK, true);
timerAlarmEnable(timer);
xTaskCreatePinnedToCore( fGPS_Parse, "fGPS_Parse", TaskStack10K2, NULL, Priority4, NULL, TaskCore0 ); // assigned to core 0
} //void setup() // runs on core 1
///////////////////////////
void loop() {} // runs on core 1
void fGPS_Parse( void * parameter )
{
TickType_t xDoDistanceExpireTicks;
struct stuTime *pxTime;
struct stuPosit pxPosit;
struct stuDistance pxDistance;
struct stuSpeed pxSpeed;
float Alti;
float Hdg;
int Sats;
float LatNow;
float LonNow;
float LatPast;
float LonPast;
int DoDistanceTicks = 5000;
////
xDoDistanceExpireTicks = xTaskGetTickCount() + pdMS_TO_TICKS( DoDistanceTicks ); // add DoDistanceTicks mS worth of ticks to current tick count
for (;;)
{
xEventGroupWaitBits (eg, GPS_Parse, pdTRUE, pdTRUE, portMAX_DELAY) ;
//query GPS: has a new complete chunk of data been received?
if ( GPSSerial.available() > 1 )
{
if ( GPS.encode(GPSSerial.read()) )
{
// }
//parse code follows, exceeds the 9K character limit.
} // for (;;)
vTaskDelete( NULL );
} // void fGPS_Parse( void *pdata )
In either case the routine to cause a gps data read is done at a much higher rate then the code to actually parse the data.
If your gps module has a built in RTC, I’d suggest getting a battery for the RTC for faster gps acquisition.
If our gps is not running an internal rtc, place the gps near a window and wait for up to an hour for the first acquisition.