NeoGPS library example fails to compile

Trying to use the NeoGPS library. Using their NMEAdiagnostic.ino file.

Included both the NeoGPS and Arduino libraries (it uses both).

When compiling the project getting the following error:

Processing  gps6.ino
Checking library NeoGPS...
Checking library Arduino...
Installing library Arduino 0.0.10 to lib/Arduino ...
Installing library NeoGPS 4.1.3 to lib/NeoGPS ...
Library Arduino 0.0.10 installed.
Library NeoGPS 4.1.3 installed.
make -C ../modules/electron/user-part all
make[1]: Entering directory '/firmware/modules/electron/user-part'
make -C ../../../user 
make[2]: Entering directory '/firmware/user'
Building cpp file: src/gps6.cpp
Invoking: ARM GCC CPP Compiler
mkdir -p ../build/target/user/platform-10-msrc/
arm-none-eabi-gcc -DSTM32_DEVICE -DSTM32F2XX -DPLATFORM_THREADING=1 -DPLATFORM_ID=10 -DPLATFORM_NAME=electron -DUSBD_VID_SPARK=0x2B04 -DUSBD_PID_DFU=0xD00A -DUSBD_PID_CDC=0xC00A -DSPARK_PLATFORM -g3 -gdwarf-2 -Os -mcpu=cortex-m3 -mthumb -DINCLUDE_PLATFORM=1 -DPRODUCT_ID=10 -DPRODUCT_FIRMWARE_VERSION=65535 -DUSE_STDPERIPH_DRIVER -DDFU_BUILD_ENABLE -DSYSTEM_VERSION_STRING=0.6.0 -DRELEASE_BUILD -I./inc -I../wiring/inc -I../system/inc -I../services/inc -I../communication/src -I../hal/inc -I../hal/shared -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/include -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/portable/GCC/ARM_CM3 -I../hal/src/electron -I../hal/src/stm32f2xx -I../hal/src/stm32 -I../platform/shared/inc -I../platform/MCU/STM32F2xx/STM32_USB_Host_Driver/inc -I../platform/MCU/STM32F2xx/STM32_StdPeriph_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_OTG_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_Device_Driver/inc -I../platform/MCU/STM32F2xx/SPARK_Firmware_Driver/inc -I../platform/MCU/shared/STM32/inc -I../platform/MCU/STM32F2xx/CMSIS/Include -I../platform/MCU/STM32F2xx/CMSIS/Device/ST/Include -I../dynalib/inc -Isrc -I./libraries -Isrc -Isrc -Ilib/NeoGPS/src -Ilib/Arduino/src -I. -MD -MP -MF ../build/target/user/platform-10-msrc/gps6.o.d -ffunction-sections -fdata-sections -Wall -Wno-switch -Wno-error=deprecated-declarations -fmessage-length=0 -fno-strict-aliasing -DSPARK=1 -DPARTICLE=1 -DSTART_DFU_FLASHER_SERIAL_SPEED=14400 -DSTART_YMODEM_FLASHER_SERIAL_SPEED=28800 -DSPARK_PLATFORM_NET=UBLOXSARA -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc  -DLOG_INCLUDE_SOURCE_INFO -DUSE_SPI=SPI -DUSE_CS=A2 -DUSE_SPI=SPI -DUSE_CS=A2 -DUSER_FIRMWARE_IMAGE_SIZE=0x20000 -DUSER_FIRMWARE_IMAGE_LOCATION=0x8080000 -DMODULAR_FIRMWARE=1 -DMODULE_VERSION=4 -DMODULE_FUNCTION=5 -DMODULE_INDEX=1 -DMODULE_DEPENDENCY=4,2,102 -D_GNU_SOURCE -D_WINSOCK_H -DLOG_MODULE_CATEGORY="\"app\""  -fno-exceptions -fno-rtti -fcheck-new -std=gnu++11 -c -o ../build/target/user/platform-10-msrc/gps6.o src/gps6.cpp
gps6.ino:32:52: fatal error: SoftwareSerial.h: No such file or directory
compilation terminated.
../build/module.mk:261: recipe for target '../build/target/user/platform-10-msrc/gps6.o' failed
make[2]: Leaving directory '/firmware/user'
make[2]: *** [../build/target/user/platform-10-msrc/gps6.o] Error 1
../../../build/recurse.mk:11: recipe for target 'user' failed
make[1]: *** [user] Error 2
make[1]: Leaving directory '/firmware/modules/electron/user-part'
../build/recurse.mk:11: recipe for target 'modules/electron/user-part' failed

The code for the project is:
// This #include statement was automatically added by the Particle IDE.

#include <Arduino.h>
#include <NMEAGPS.h>

//======================================================================
//  Program: NMEAdiagnostic.ino
//
//  Description:  This program tries different baud rates until
//    valid NMEA sentences are detected.  Some GPS devices may
//    have a binary mode that does not emit NMEA sentences.  You
//    may have to send a special command or use a utility program
//    to configure it to emit NMEA sentences instead of binary messages.
//
//  Prerequisites:
//     1) Your GPS device has been correctly powered.
//          Be careful when connecting 3.3V devices.
//     2) Your GPS device is correctly connected to an Arduino serial port.
//          See GPSport.h for the default connections.
//
//  'Serial' is for debug output to the Serial Monitor window.
//
//======================================================================

#if defined( UBRR1H ) | defined( ID_USART0 )
  // Default is to use Serial1 when available.

#else  
  // Only one serial port is available, uncomment one of the following:
  //#include <AltSoftSerial.h>
  //#include <NeoSWSerial.h> /* ONLY WORKS AT 9600, 19200 and 38400 */
  #include <SoftwareSerial.h> /* NOT RECOMMENDED */
#endif
#include "GPSport.h"

#include "Streamers.h"
#define DEBUG_PORT Serial

// Check configuration

#ifndef NMEAGPS_RECOGNIZE_ALL
  #error You must define NMEAGPS_RECOGNIZE_ALL in NMEAGPS_cfg.h!
#endif

#ifdef NMEAGPS_IMPLICIT_MERGING
  #error You must *undefine* NMEAGPS_IMPLICIT_MERGING in NMEAGPS_cfg.h! \
   Please use EXPLICIT or NO_MERGING.
#endif

#ifdef NMEAGPS_INTERRUPT_PROCESSING
  #error You must *NOT* define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!
#endif

static NMEAGPS  gps          ; // This parses received characters
static gps_fix  all_data     ; // A composite of all GPS data fields
static uint32_t last_rx = 0UL; // The last millis() time a character was
                               // received from GPS.
static uint32_t valid_sentence_received = 0UL;
static bool     last_sentence_received  = false;
static uint32_t baudStartTime = 0UL;
static uint8_t  warnings = 0;
static uint8_t  errors   = 0;

//--------------------------

static void hang()
{
  DEBUG_PORT.println( F("\n** NMEAdiagnostic completed **\n") );

  if (warnings) {
    DEBUG_PORT.print( warnings );
    DEBUG_PORT.print( F(" warnings") );
  }
  if (warnings && errors)
    DEBUG_PORT.print( F(" and ") );
  if (errors) {
    DEBUG_PORT.print( errors );
    DEBUG_PORT.print( F(" errors") );
  }
  if (warnings || errors)
    DEBUG_PORT.println();

  DEBUG_PORT.flush();

  for (;;)
    ;

} // hang

//--------------------------
// Baud rates to check

static long  baud_table[] =
  { 1200, 2400, 4800, 9600, 14400, 19200, 28800, 31250, 38400, 
    57600, 115200 };
static const uint8_t num_bauds          = sizeof(baud_table)/sizeof(baud_table[0]);
static const uint8_t INITIAL_BAUD_INDEX = 3; // 9600
static       uint8_t baud_index         = INITIAL_BAUD_INDEX;
static       bool    triedDifferentBaud = false;

//--------------------------

static void tryBaud()
{
  long baud = baud_table[baud_index];
  DEBUG_PORT.print( F("\n____________________________\n\nChecking ") );
  DEBUG_PORT.print( baud );
  DEBUG_PORT.print( F(" baud...\n") );
  DEBUG_PORT.flush();

//if (baud == 9600) baud = 17000;
  gps_port.begin( baud );
  baudStartTime = millis();

} // tryBaud

//--------------------------

static void tryAnotherBaudRate()
{
  gps_port.end();
  while (gps_port.available())
    gps_port.read();

  if (baud_index == INITIAL_BAUD_INDEX) {
    baud_index = 0;

  } else {
    baud_index++;
    if (baud_index == INITIAL_BAUD_INDEX)
      baud_index++; // skip it, we already tried it

    if (baud_index >= num_bauds) {
      baud_index = INITIAL_BAUD_INDEX;
      DEBUG_PORT.print( F("\n  All baud rates tried!\n") );
      hang();
    }
  }

  tryBaud();

  triedDifferentBaud = true;

} // tryAnotherBaudRate

//------------------------------------

static const uint16_t MAX_SAMPLE = 256;
static uint8_t        someChars[ MAX_SAMPLE ];
static uint16_t       someCharsIndex = 0;

static void dumpSomeChars()
{
  if (someCharsIndex > 0) {
    DEBUG_PORT.print( F("Received data:\n") );

    const uint16_t  bytes_per_line = 32;
          char      ascii[ bytes_per_line ];
          uint8_t  *ptr            = &someChars[0];

    for (uint16_t i=0; i<someCharsIndex; ) {
      uint16_t j;
      
      for (j=0; (i<someCharsIndex) && (j<bytes_per_line); i++, j++) {
        uint8_t c = *ptr++;
        if (c < 0x10)
          DEBUG_PORT.print('0');
        DEBUG_PORT.print( c, HEX );
        if ((' ' <= c) && (c <= '~'))
          ascii[ j ] = c;
        else
          ascii[ j ] = '.';
      }

      uint16_t jmax = j;
      while (j++ < bytes_per_line)
        DEBUG_PORT.print( F("  ") );
      DEBUG_PORT.print( ' ' );
      
      for (j=0; j<jmax; j++)
        DEBUG_PORT.print( ascii[ j ] );
      DEBUG_PORT.print( '\n' );
    }
    DEBUG_PORT.flush();

    someCharsIndex = 0;
  }
} // dumpSomeChars

//----------------------------------------------------------------

void displaySentences()
{
  // We received one or more sentences, display the baud rate
  DEBUG_PORT.print( F("\n\n**** NMEA sentence(s) detected!  ****\n") );
  dumpSomeChars();
  DEBUG_PORT << F("\nDevice baud rate is ") <<
    baud_table[ baud_index ] << '\n';

  DEBUG_PORT.print( F("\nGPS data fields received:\n\n  ") );
  trace_header( DEBUG_PORT );
  DEBUG_PORT.print( F("  ") );
  trace_all( DEBUG_PORT, gps, all_data );

  if (!last_sentence_received) {
    warnings++;
    DEBUG_PORT.print( F("\nWarning: LAST_SENTENCE_IN_INTERVAL defined to be ") );
    DEBUG_PORT.print( gps.string_for( LAST_SENTENCE_IN_INTERVAL ) );
    DEBUG_PORT.println( F(", but was never received.\n"
                      "  Please use NMEAorder.ino to determine which sentences your GPS device sends, and then\n"
                      "  use the last one for the definition in NMEAGPS_cfg.h.") );
  }

} // displaySentences

//----------------------------------------------------------------
//  Listen to see if the GPS device is correctly 
//  connected and functioning.

static void listenForSomething()
{
  uint32_t current_ms         = millis();
  uint32_t ms_since_last_rx   = current_ms - last_rx;
  bool     waited_long_enough = (current_ms - baudStartTime) > 1000UL;

  if ((ms_since_last_rx > 5) && waited_long_enough) {

    // The GPS device has not sent any characters for at least 5ms.
    //   See if we've been getting chars sometime during the last second.
    //   If not, the GPS may not be working or connected properly.

    bool getting_chars = (someCharsIndex > 0);

    // Try to diagnose the problem
    
    static uint8_t tries = 1;
    bool           tryNext = false;

    if (!getting_chars) {

      if (tries++ >= 3) {
        errors++;
        DEBUG_PORT.println( F("\nCheck GPS device and/or connections.  No data received.\n") );
        tryNext = true;
      }

    } else if (valid_sentence_received) {
      uint8_t s  = valid_sentence_received/1000;
      uint8_t ms = valid_sentence_received - s*1000;

      DEBUG_PORT.print( F("Valid sentences were received ") );
      DEBUG_PORT.print( s );
      DEBUG_PORT.print( '.' );
      if (ms < 100)
        DEBUG_PORT.print( '0' );
      if (ms < 10)
        DEBUG_PORT.print( '0' );
      DEBUG_PORT.print( ms );
      DEBUG_PORT.println(
        F(" seconds ago.\n"
          "  The GPS update rate may be lower than 1Hz,\n"
          "  or the connections may be bad." ) );
      displaySentences();
      hang();

    } else {
        DEBUG_PORT.println(
          F("No valid sentences, but characters are being received.\n"
            "  Check baud rate or device protocol configuration.\n" ) );

      dumpSomeChars();
      delay( 2000 );
      tryNext = true;
    }

    if (tryNext) {
      tries = 1;
      tryAnotherBaudRate();
      valid_sentence_received = 0UL;
    }
  }
  
} // listenForSomething

//------------------------------------

static void GPSloop()
{
  while (gps_port.available()) {
    last_rx = millis();

    uint8_t c = gps_port.read();

    if (someCharsIndex < MAX_SAMPLE)
      someChars[ someCharsIndex++ ] = c;

    if (gps.decode( c ) == NMEAGPS::DECODE_COMPLETED) {
      all_data |= gps.fix();
      valid_sentence_received = last_rx;

      if (gps.nmeaMessage == LAST_SENTENCE_IN_INTERVAL)
        last_sentence_received = true;

      DEBUG_PORT.print( F("Received ") );
      DEBUG_PORT.println( gps.string_for( gps.nmeaMessage ) );

      static uint8_t sentences_printed = 0;
             bool    long_enough       = (millis() - baudStartTime > 3000);

      if (long_enough ||
          (
            (sentences_printed++ >= 20) &&
            (someCharsIndex      >= MAX_SAMPLE)
          ) ) {
        displaySentences();
        hang();
      }
    }
  }

  if (!valid_sentence_received ||
      (millis() - valid_sentence_received > 3000UL))
    listenForSomething();

} // GPSloop

//--------------------------

void setup()
{
  // Start the normal trace output
  DEBUG_PORT.begin(9600);
  while (!DEBUG_PORT)
    ;

  DEBUG_PORT.print( F("NMEAdiagnostic.INO: started\n") );
  DEBUG_PORT.println( F("Looking for GPS device on " USING_GPS_PORT) );

  if (sizeof(gps_fix) <= 2) {
    warnings++;
    DEBUG_PORT.print( F("\nWarning: no fields are enabled in GPSfix_cfg.h.\n  Only the following information will be displayed:\n    ") );
    trace_header( DEBUG_PORT );
  }

  #if !defined( NMEAGPS_PARSE_GGA ) & !defined( NMEAGPS_PARSE_GLL ) & \
      !defined( NMEAGPS_PARSE_GSA ) & !defined( NMEAGPS_PARSE_GSV ) & \
      !defined( NMEAGPS_PARSE_RMC ) & !defined( NMEAGPS_PARSE_VTG ) & \
      !defined( NMEAGPS_PARSE_ZDA ) & !defined( NMEAGPS_PARSE_GST )
    warnings++;
    DEBUG_PORT.println( F("\nWarning: no messages are enabled for parsing in NMEAGPS_cfg.h.\n  No fields will be valid, including the 'status' field.") );
  #endif

  DEBUG_PORT.flush();

  // Start the UART for the GPS device
  tryBaud();

} // setup

//--------------------------

void loop()
{
  GPSloop();
}

That might be an issue :wink:

Yes, but how do I get that in there?

I guess you need to ask the original contributor of this library (who seems to have chosen not disclose his identity ;-))

The reason is here

#if defined( UBRR1H ) | defined( ID_USART0 )
  // Default is to use Serial1 when available.

#else  
  // Only one serial port is available, uncomment one of the following:
  //#include <AltSoftSerial.h>
  //#include <NeoSWSerial.h> /* ONLY WORKS AT 9600, 19200 and 38400 */
  #include <SoftwareSerial.h> /* NOT RECOMMENDED */
#endif

neither UBRR1H nor ID_USART0 are defined in the Particle world, so consequently the #else branch hits.
BTW, not sure if this shouldn’t rather be #if defined( UBRR1H ) || defined( ID_USART0 ) anyway.

2 Likes

So then it seems it’s permanently busted… Sigh, thanks for the effort of looking in to this.

It's not busted, it just needs to be ported! I'll take a look this weekend to see what I can do.

@r0b0tn1k, this portion is actually in the .ino so you can edit it yourself.

1 Like

@r0b0tn1k, to get the example to compile, at the top of the file you need to replace:

#if defined( UBRR1H ) | defined( ID_USART0 )
  // Default is to use Serial1 when available.

#else  
  // Only one serial port is available, uncomment one of the following:
  //#include <AltSoftSerial.h>
  //#include <NeoSWSerial.h> /* ONLY WORKS AT 9600, 19200 and 38400 */
  #include <SoftwareSerial.h> /* NOT RECOMMENDED */
#endif
#include "GPSport.h"

with:

#define gps_port    Serial1
#define USING_GPS_PORT "Serial1"

:wink:

1 Like

This is the missing directory that needs to be defined.If using hardware serials ports define as well as mentioned by peekay123

You can use the ParticleSoftSerial library instead of SoftSerial too.