2

I have a GPS code that I need to run only once, but every different try gives me errors, including placing the whole code in void setup(). Is there any way that this code can be run just once? As of now, the code repeats itself, putting out data over and over again - I need just one set, right when the code is activated.

Here is the code:

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO  true
boolean usingInterrupt = false;
void useInterrupt(boolean); 

void setup() {
  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);  
  GPS.sendCommand(PGCMD_ANTENNA);
  useInterrupt(true);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
}

SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();
void loop() {                  // run over and over again
  if (! usingInterrupt) {
    char c = GPS.read();
    if (GPSECHO)
      if (c) Serial.print(c);
  }
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA()))   
      return;

  if (timer > millis())
    timer = millis();

  if (millis() - timer > 2000) { 
    timer = millis(); // reset the timer
    Serial.print("\nTime: ");
    Serial.print(GPS.hour, DEC); Serial.print(':');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.println(GPS.milliseconds);
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality); 
    if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", "); 
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
      Serial.print("Location (in degrees, works with Google Maps): ");
      Serial.print(GPS.latitudeDegrees, 4);
      Serial.print(", "); 
      Serial.println(GPS.longitudeDegrees, 4);
      Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
    }
  }
  }
}

I've been trying to get this for a while, and I'm new to programming!

1
  • How is the code 'activated'?
    – sa_leinad
    Nov 26, 2016 at 2:10

2 Answers 2

0

Here's your sketch, modified to use my library, NeoGPS. It is smaller, faster, more reliable and more accurate than all other libraries.

I added a waitForFix routine that, well, waits for the GPS to get a fix. Then it calls printFix, just once:

#include <NMEAGPS.h>
#include <NeoSWSerial.h>

NeoSWSerial gpsSerial(3, 2);
NMEAGPS     GPS;
gps_fix     fix;

void setup()
{
  Serial.begin(115200);
  Serial.println( F("Run once!") ); // F macro saves RAM!

  gpsSerial.begin(9600);
  gpsSerial.println( F("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28") ); // RMC & GGA only
  gpsSerial.println( F("$PMTK220,1000*1F") ); // 1Hz update rate

  waitForFix();
  printFix();
}

void loop()
{
}

void waitForFix()
{
  uint8_t fixes = 0;

  do {
    if (GPS.available( gpsSerial )) {
      fix = GPS.read();
      fixes++;
    }
  } while ((fixes < 2) && !fix.valid.location);

} // waitForFix

void printFix()
{
  Serial.print( F("Time: ") );
  if (fix.valid.time) {
    if (fix.dateTime.hours < 10)
      Serial.print( '0' );
    Serial.print(fix.dateTime.hours);
    Serial.print(':');
    if (fix.dateTime.hours < 10)
      Serial.print( '0' );
    Serial.print(fix.dateTime.minutes);
    Serial.print(':');
    if (fix.dateTime.hours < 10)
      Serial.print( '0' );
    Serial.print(fix.dateTime.seconds);
    Serial.print('.');
    if (fix.dateTime_cs < 10)
      Serial.print( '0' );
    Serial.print(fix.dateTime_cs);
  }
  Serial.println();

  Serial.print( F("Date: ") );
  if (fix.valid.date) {
    Serial.print(fix.dateTime.day);
    Serial.print('/');
    Serial.print(fix.dateTime.month);
    Serial.print('/');
    Serial.print( fix.dateTime.full_year() );
  }
  Serial.println();

  Serial.print( F("Fix status: ") );
  if (fix.valid.status)
    Serial.print( (int) fix.status );
  Serial.println();

  if (fix.valid.location) {
    Serial.print( F("Location: ") );
    Serial.print( fix.latitude(), 4 );
    Serial.print( F(", ") );
    Serial.println(fix.longitude(), 4);
  }

  if (fix.valid.speed) {
    Serial.print("Speed (knots): ");
    Serial.println( fix.speed() );
  }

  if (fix.valid.heading) {
    Serial.print( F("Angle: ") );
    Serial.println( fix.heading() );
  }

  if (fix.valid.altitude) {
    Serial.print( F("Altitude: ") );
    Serial.println( fix.altitude() );
  }

  if (fix.valid.satellites) {
    Serial.print( F("Satellites: ") );
    Serial.println( fix.satellites );
  }
}

The NeoGPS library waits for a complete batch of sentences, because the speed is in one sentence (RMC) and the altitude is in another sentence (see this table). NeoGPS provides complete "fixes", as assembled from all the sentences your GPS device sends. The fixes are available once per second, or whatever you have configured your device to provide.

You may also notice that I used another library I maintain, NeoSWSerial. SoftwareSerial is very inefficient because it disables interrupts for long periods of time. This can interfere with other parts of your sketch or other libraries.

If you can put the GPS on pins 8 & 9, AltSoftSerial would be even better. It only works on those two pins.

Your original sketch uses 12124 bytes of program space and 1031 bytes of RAM.

The NeoGPS version uses 10680 bytes of program space and 446 bytes of RAM. A significant savings!

4
  • But when trying to verify this sketch, I still get the same error, that the timer wasn't declared.
    – JMacris
    Nov 17, 2016 at 20:25
  • Sorry, that wasnt the error, got mixed up.
    – JMacris
    Nov 17, 2016 at 20:44
  • The error says; #include <NeoSWSerial.h> ^ compilation terminated. exit status 1 Error compiling for board Arduino/Genuino Uno.
    – JMacris
    Nov 17, 2016 at 20:44
  • Did you download and install NeoSWSerial from the link? It's a standard Arduino library that you download, unzip, and copy the NeoSWSerial-master directory to a new Arduino/Libraries/NeoSWSerial subdirectory.
    – slash-dev
    Nov 17, 2016 at 21:00
0

Put everything from your void loop() into your void setup. Put them AFTER the original setup and you should be good to go.

DO NOT DELETE THE VOID LOOP!! ONLY KEEP IT EMPTY!!

Here, try this:

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>


SoftwareSerial mySerial(3, 2);



Adafruit_GPS GPS(&mySerial);



#define GPSECHO  true


boolean usingInterrupt = false;
void useInterrupt(boolean);

void setup()
{


  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");


  GPS.begin(9600);


  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);



  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);


  GPS.sendCommand(PGCMD_ANTENNA);


  useInterrupt(true);

  delay(1000);

  mySerial.println(PMTK_Q_RELEASE);

  if (! usingInterrupt) {

    char c = GPS.read();

    if (GPSECHO)
      if (c) Serial.print(c);
  }


  if (GPS.newNMEAreceived()) {


    if (!GPS.parse(GPS.lastNMEA()))
      return;


    if (timer > millis())  timer = millis();


    if (millis() - timer > 2000) {
      timer = millis(); // reset the timer

      Serial.print("\nTime: ");
      Serial.print(GPS.hour, DEC); Serial.print(':');
      Serial.print(GPS.minute, DEC); Serial.print(':');
      Serial.print(GPS.seconds, DEC); Serial.print('.');
      Serial.println(GPS.milliseconds);
      Serial.print("Date: ");
      Serial.print(GPS.day, DEC); Serial.print('/');
      Serial.print(GPS.month, DEC); Serial.print("/20");
      Serial.println(GPS.year, DEC);
      Serial.print("Fix: "); Serial.print((int)GPS.fix);
      Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
      if (GPS.fix) {
        Serial.print("Location: ");
        Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
        Serial.print(", ");
        Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
        Serial.print("Location (in degrees, works with Google Maps): ");
        Serial.print(GPS.latitudeDegrees, 4);
        Serial.print(", ");
        Serial.println(GPS.longitudeDegrees, 4);

        Serial.print("Speed (knots): "); Serial.println(GPS.speed);
        Serial.print("Angle: "); Serial.println(GPS.angle);
        Serial.print("Altitude: "); Serial.println(GPS.altitude);
        Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
      }
    }
  }
}



SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();

#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;

#endif
}

void useInterrupt(boolean v) {
  if (v) {

    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {

    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

void loop()                     // run over and over again
{
}
4
  • Dat Ha... After uploading this code, i recieved the error ' timer' was not declared in this scope, in this line if (millis() - timer > 2000) {
    – JMacris
    Nov 15, 2016 at 21:08
  • Do you know what might be causing this??
    – JMacris
    Nov 15, 2016 at 21:08
  • void setup is a loop that run once. void loop is a code that runs and repeat. Open a blank sketch a see what happens. If it works, please consider accepting the answer to mark this question as resolved.
    – Dat Ha
    Nov 15, 2016 at 21:11
  • 1
    Well, the error tells you that the variabele 'timer' was not declared... Which basically means you're missing your declaration of the timer variable: 'uint32_t timer = millis();'
    – Paul
    Nov 15, 2016 at 21:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.