Using NeoGps with NeoHWSerial

I am currently experimenting with the NeoGPS library.

I have spent a long loooong time learning from absolutely no knowledge in programming to having a working autopilot on my 17’ motor boat.

The GPS part of my project is based on the TinyGps++ library which has worked pretty well for me so far.
However i am now at the stage of my project to start tidying things up and making my code run efficiently as possible.

I calculate that the loop speed of my sketch to be in the region of 800 - 970 m/seconds.

(There is alot going on in the sketch , many calculations, loading images to a 4.3" touchscreen, streaming bluetooth data, displaying all the gps info, pid calculations, writing to servos and relay boards and so on…)
All of this on one Mega board :slight_smile:

I really should be considering using multiple boards for this project, but although a 800-970m/s loop sounds slow it is still operating well enough for my needs but i would still like it to run at full potential.

After some research i am under the impression that by implementing the NeoGPS/NeoHWSerial libraries instead of tinyGps++ i could shave off some millis but I am having some problems…

I can run all the examples with no problems , i have changed the last sentence received to suit my gps module , and i have undefined/defined the sentences i need to use etc.

the problem comes when i ‘go away and do other stuff’ as my loop takes so long to complete it loses data which results in no fix and no good data.

After some more research i installed the neoHWSerial library which im sure will sort this problem but i need a little guidance on the best approach.

I am new to interrupts and how they operate, i am not entirely sure how i should go about adding the rest of my code.

Where in this basic sketch would i carry out my time consuming tasks?

I have just been adding delays to mimic my time consuming tasks…is this an acceptable approach for testing purposes?

#define gpsPort NeoSerial1
#define DEBUG_PORT NeoSerial
#define GPS_PORT_NAME "MyGPS"

//======================================================================
//  Program: NMEA_isr.ino
//
//  Prerequisites:
//     1) NMEA.ino works with your device
//
//  Description:  This minimal program parses the GPS data during the 
//     RX character interrupt.  The ISR passes the character to
//     the GPS object for parsing.  The GPS object will add gps_fix 
//     structures to a buffer that can be later read() by loop().
//
//  License:
//    Copyright (C) 2014-2017, SlashDevin
//
//    This file is part of NeoGPS
//
//    NeoGPS is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    NeoGPS is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with NeoGPS.  If not, see <http://www.gnu.org/licenses/>.
//
//======================================================================

//#include <GPSport.h>

#include <Streamers.h>

// Check configuration

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

static NMEAGPS   gps;

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

static void GPSisr( uint8_t c )
{
  gps.handle( c );

} // GPSisr

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

void setup()
{
  DEBUG_PORT.begin(9600);
  while (!DEBUG_PORT)
    ;

  DEBUG_PORT.print( F("NMEA_isr.INO: started\n") );
  DEBUG_PORT.print( F("fix object size = ") );
  DEBUG_PORT.println( sizeof(gps.fix()) );
  DEBUG_PORT.print( F("NMEAGPS object size = ") );
  DEBUG_PORT.println( sizeof(gps) );
  DEBUG_PORT.println( F("Looking for GPS device on " GPS_PORT_NAME) );

  trace_header( DEBUG_PORT );

  DEBUG_PORT.flush();

  gpsPort.attachInterrupt( GPSisr );
  gpsPort.begin( 38400 );
}

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

void loop()
{
  if (gps.available()) {
    // Print all the things!
    trace_all( DEBUG_PORT, gps, gps.read() );

    delay(600);  // Is this a suitable place to call my time delaying tasks?
  }

  if (gps.overrun()) {
    gps.overrun( false );
    DEBUG_PORT.println( F("DATA OVERRUN: took too long to print GPS data!") );
  }
  
}

Where i have added ‘delay(600);’ seems to work pretty well but every second Debug print contains the gpsoverrun warning, is this a problem? every other sentence contains good data though.

anywhere else i add the delay seems to make the ratio of good data vs gpsoverrun worse.

Am i doing this all wrong? :confused:

I really should be considering using multiple boards for this project, but although a 800-970m/s loop sounds slow it is still operating well enough for my needs but i would still like it to run at full potential.

I hope you meant 800-970ms/loop as 800-970m/s (meter per second) is a bit fast for a motor boat with an auto pilot.

Where in this basic sketch would i carry out my time consuming tasks?

You should make your time consuming task interruptible. I'm quite sure your task don't actually take almost a second to run but that there is a lot of waiting in these tasks. You can also call just one task per loop round if that helps. This is too much guessing as we haven't seen your code yet. Post your complete code, we might have some solutions to make a loop run much faster.

pylon:
I hope you meant 800-970ms/loop as 800-970m/s (meter per second) is a bit fast for a motor boat with an auto pilot.

Hehe yes i meant ms, i am not brave enough nor do i trust my coding skills (or lack of them) to be going that fast.

I totally agree that there will be loads of room for improvement in my code and that alot of time is spent waiting, i am sure the way I handle the bluetooth data transfer is slowing things down too.

Btw the bluetooth function is for android capability, i have written an android app that deals with the navigation part, I just pick a place on the android map to add it to the waypoints, the android app then sends the target heading to the arduino and then the arduino uses this info as the PID set point.

I would love some advice regarding my main code as i'm sure there is LOADS of room for improvement.

I didnt upload this code initially as its still based on the tinyGps library and my question was related to the NeoGps library.

The coding is bad and the structure is probably worse, but hopefully you will get the idea.

It seems my code is too large to post in the normal way. I will try to send it separately.

I had to post it as an attachment, here it is …

GPS_MODULE_87_Posted_To_Forum.ino (65.4 KB)

I seem to making a little progress....
I swapped out tinyGps with the neoGps and neoHwSerial libraries even although I was getting the overrun error in the tests I seem to be getting pretty good results, at first glance loop time has reduced to between 670 and 790 in full autopilot mode ie, Bluetooth streaming and calculating the PID output.

even although I am making progress I would still appreciate all the help I can get to make this code even more efficient.

Sorry for any confusion, I seem to have logged into an old profile on my smartphone :slightly_frowning_face:

I forgot I even created that one :-\

At least 210ms are just wasted in the loop with delays. You might have to insert more measurement points to check how much time you loose in the different areas.

pylon:
At least 210ms are just wasted in the loop with delays. You might have to insert more measurement points to check how much time you loose in the different areas.

ill make that my next task, thanks pylon.

I still have to go through everything again and rewrite my early sections of code (I am at update 87 of my sketch and I still have code in it that i wrote in the early updates when I first started learning)

I will tidy things up and ill set up counters for each task.

Can I ask how you managed to get the 210ms calculation?

More progress....
I added in numerous counters as suggested by pylon, and with some more tweaks I have got the total loop time down to 550 - 650ms.

The most time consuming task is writing text to the lcd display. A whopping 300ms just to keep the screen populated with speed, sats, lat,lng and warning messages etc.
I have reduced this to to 150ms by significantly reducing the amount of text being printed to the display but this is just a temporary measure.

I will have to look into the utft library and see if there is any way to speed things up, failing that I might have to hunt for a different library.

has anyone any suggestions on this or alternative libraries?

ian160981:
has anyone any suggestions on this

Switch to an Arduino DUE, its plug compatible and 5 times faster.

Assuming the screen is supported.

srnet:
Switch to an Arduino DUE, its plug compatible and 5 times faster.

Assuming the screen is supported.

That could be the answer, I will look into compatibility with the screen.

Thanks

has anyone any suggestions on this or alternative libraries?

Does the complete screen have to be updated in every loop? It might be worthy to update only sections that had a change from last update.