Hi all,
I have been using the NeoGPS.h example NMEASDlog.ino successfully to save gps data to an SD card using an Arduino Uno. I wanted to add a push button to be able to turn logging on and off and start a new file. I also wanted to add some LED's to help display the current state of the program when out and about.
I know NeoGPS uses some unorthodox method of both receiving GPS data through the Rx (pin 0), while still using Serial Monitor as an output, simulating the SD save data if that define is enabled. The only catch is that the gps has to be disconnected from the Rx pin in order for the uno to download a new code or "listen" to any information from IDE or anything serial. This works fine for both compiling and running in the example NMEASDlog.ino as shown here:
#include <Arduino.h>
#include <NMEAGPS.h>
//======================================================================
// Program: NMEASDlog.ino
//
// Description: This program is an interrupt-driven GPS logger.
// It uses the alternative serial port libraries NeoHWSerial,
// NeoSWSerial, or NeoICSerial.
//
// Prerequisites:
// 1) You have completed the requirements for NMEA_isr.ino
// 2) You have connected an SPI SD card and verified it is working
// with other SD utilities.
// 3) For logging faster than the default 1Hz rate, you have
// identified the required commands for your GPS device.
//
// 'Serial' is for debug output to the Serial Monitor window.
//
// 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/>.
//
//======================================================================
// SDFat examples work
// NEMA and NEMAisr both work
#include <GPSport.h>
#include <Streamers.h>
//----------------------------------------------------------------
// Check configuration
#if !defined( GPS_FIX_TIME ) || !defined( GPS_FIX_LOCATION )
#error You must define TIME and LOCATION in GPSfix_cfg.h
#endif
#if !defined( NMEAGPS_PARSE_RMC )
#error You must define NMEAGPS_PARSE_RMC in NMEAGPS_cfg.h!
#endif
#ifndef NMEAGPS_INTERRUPT_PROCESSING
#error You must define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!
#endif
static const int ErrorLED = 3;
static NMEAGPS gps;
//----------------------------------------------------------------
// SD card includes and declarations
#include <SPI.h>
#include <SdFat.h>
SdFat SD;
const int chipSelect = 10;
//----------------------------------------------------------------
// Simulate SD For testing, it may be more convenient to simply print the
// GPS fix fields to the Serial Monitor. Simply uncomment
// this define to skip all SD operations. An SD card module
// does not have to be connected.
#define SIMULATE_SD
#ifdef SIMULATE_SD
auto &logfile = DEBUG_PORT;
#else
File logfile;
#endif
//----------------------------------------------------------------
// Utility to print a long integer like it's a float
// with 9 significant digits.
void printL( Print & outs, int32_t degE7 )
{
// Extract and print negative sign
if (degE7 < 0) {
degE7 = -degE7;
outs.print( '-' );
}
// Whole degrees
int32_t deg = degE7 / 10000000L;
outs.print( deg );
outs.print( '.' );
// Get fractional degrees
degE7 -= deg*10000000L;
// Print leading zeroes, if needed
if (degE7 < 10L)
outs.print( F("000000") );
else if (degE7 < 100L)
outs.print( F("00000") );
else if (degE7 < 1000L)
outs.print( F("0000") );
else if (degE7 < 10000L)
outs.print( F("000") );
else if (degE7 < 100000L)
outs.print( F("00") );
else if (degE7 < 1000000L)
outs.print( F("0") );
// Print fractional degrees
outs.print( degE7 );
}
//----------------------------------------------------------------
// Because the SD write can take a long time, GPSisr will store
// parsed data in the NMEAGPS 'buffer' array until GPSloop can get to it.
//
// The number of elements you should have in the array depends on
// two things: the speed of your SD card, and the update rate you
// have chosen.
//
// For an update rate of 10Hz (100ms period), two fixes are probably
// enough. Most cards take ~100ms to complete a write of 512 bytes.
// With FIX_MAX=2, two complete fixes can be stored, which were
// received in 200ms. A third fix can be started, giving a little
// more time before an overrun occurs, a total of about 250ms.
//
// If your card is slower or your update rate is faster, you should
// first build and run this program to determine the speed of your
// card. The time it takes to log one record is printed to the log
// file.
//
// After the program has run for a minute or two, remove the
// card and examine the loggingTimes. You may see that an interval
// was skipped, and you will also see an OVERRUN message on the
// DEBUG_PORT (usually Serial).
//
// You should calculate a new FIX_MAX from the maximum loggingTime
// you see in the log file:
//
// FIX_MAX = (max loggingTime)/(update period) + 1;
//
// For example, if the max loggingTime is 160ms, and the update period is
// 100ms (10Hz), then FIX_MAX = 160/100 + 1 = 2.
//
// Change the FIX_MAX value, build and run the program again. The
// SD log file should now contain all records, and no OVERRUN
// messages should have been printed on the DEBUG_PORT.
//
// If you do see an OVERRUN message, examine the loggingTime to see
// if it exceeded the maximum value from the previous build, and
// increase FIX_MAX.
//
// If you are also printing data to a Serial device, you could be
// printing too much information. In general, you must print less than
// (baudrate/10) characters per second. For example, if your baudrate
// is 9600, you must print less than 960 characters per second. And if
// the update rate is 10Hz, you must print no more than 96 characters
// per update.
//
// There are also restrictions on how much you should print to Serial in one
// section of code. If you print more than 64 characters (the output buffer
// size), then some prints will block until all characters can be stored in the
// output buffer.
//
// For example, if you try to print 80 characters, the first 64 characters
// will be immediately stored in the output buffer. However, the last 16
// characters must wait until the output buffer has room for 16 more
// characters. That takes 16 * (10/baudrate) milliseconds. At 9600 baud
// that will take 17ms. The loggingTimes will show no less than 17ms per
// record, and will occasionally include the longer SD write time of ~100ms.
//----------------------------------------------------------------
static void GPSloop()
{
if (gps.available()) {
gps_fix fix = gps.read();
// Log the fix information if we have a location and time
if (fix.valid.location && fix.valid.time) {
static uint16_t lastLoggingTime = 0;
uint16_t startLoggingTime = millis();
// If you like the CSV format implemented in Streamers.h,
// you could replace all these prints with
trace_all( logfile, gps, fix ); // uncomment include Streamers.h
/*
printL( logfile, fix.latitudeL() );
logfile.print( ',' );
printL( logfile, fix.longitudeL() );
logfile.print(',');
if (fix.dateTime.hours < 10)
logfile.print( '0' );
logfile.print(fix.dateTime.hours);
logfile.print( ':' );
if (fix.dateTime.minutes < 10)
logfile.print( '0' );
logfile.print(fix.dateTime.minutes);
logfile.print( ':' );
if (fix.dateTime.seconds < 10)
logfile.print( '0' );
logfile.print(fix.dateTime.seconds);
logfile.print( '.' );
if (fix.dateTime_cs < 10)
logfile.print( '0' ); // leading zero for .05, for example
logfile.print(fix.dateTime_cs);
logfile.print(',');
logfile.print( lastLoggingTime ); // write how long the previous logging took
logfile.println();
*/
// flush() is used to empty the contents of the SD buffer to the SD.
// If you don't call flush, the data will fill up the SdFat buffer
// of 512bytes and flush itself automatically.
//
// To avoid losing data or corrupting the SD card file system, you must
// call flush() at least once (or close()) before powering down or pulling
// the SD card.
//
// It is *strongly* recommended that you use some external event
// to close the file. For example, staying within 50m of the moving
// average location for 1 minute, or using a switch to start and stop
// logging. It would also be good to provide a visual indication
// that it is safe to power down and/or remove the card, perhaps via
// the LED.
//
// To reduce the amount of data that may be lost by an abnormal shut down,
// you can call flush() periodically.
//
// Depending on the amount of data you are printing, you can save
// *a lot* of CPU time by not flushing too frequently. BTW, flushing
// every time at 5Hz is too frequent.
// This shows how to flush once a second.
static uint16_t lastFlushTime = 0;
if (startLoggingTime - lastFlushTime > 1000) {
lastFlushTime = startLoggingTime; // close enough
logfile.flush();
}
#ifdef SIMULATE_SD
// Simulate the delay of writing to an SD card. These times are
// very long. This is intended to show (and test) the overrun detection.
//
// On a 1Hz GPS, delaying more than 2 seconds here, or more than
// 2 seconds in two consecutive updates, will cause OVERRUN.
//
// Feel free to try different delays to simulate the actual behavior
// of your SD card.
uint16_t t = random(0,5); // 0..4
t += 3; // 3..7
t = t*t*t*t; // 81..2401ms
delay( t ); // cause an OVERRUN
#endif
// All logging is finished, figure out how long that took.
// This will be written in the *next* record.
lastLoggingTime = (uint16_t) millis() - startLoggingTime;
}
}
} // GPSloop
//----------------------------------------------------------------
void GPSisr( uint8_t c )
{
gps.handle( c );
} // GPSisr
//----------------------------------------------------------------
// This routine waits for GPSisr to provide
// a fix that has a valid location.
//
// The LED is slowly flashed while it's waiting.
static void waitForFix()
{
DEBUG_PORT.print( F("Waiting for GPS fix...") );
uint16_t lastToggle = millis();
for (;;) {
if (gps.available()) {
if (gps.read().valid.location)
break; // Got it!
}
// Slowly flash the LED until we get a fix
if ((uint16_t) millis() - lastToggle > 500) {
lastToggle += 500;
digitalWrite( ErrorLED, !digitalRead(ErrorLED) );
DEBUG_PORT.write( '.' );
}
}
DEBUG_PORT.println();
digitalWrite( ErrorLED, LOW );
gps.overrun( false ); // we had to wait a while...
} // waitForFix
//----------------------------------------------------------------
void setup()
{
DEBUG_PORT.begin(9600);
while (!DEBUG_PORT)
; // wait for serial port to connect.
DEBUG_PORT.println();
DEBUG_PORT.println( F("NMEASDlog_UnoWORKS.ino started!") );
DEBUG_PORT.print( F("fix object size = ") );
DEBUG_PORT.println( sizeof(gps_fix()) );
DEBUG_PORT.println( NMEAGPS_FIX_MAX );
DEBUG_PORT.print( F("NMEAGPS object size = ") );
DEBUG_PORT.println( sizeof(gps) );
DEBUG_PORT.println( F("Looking for GPS device on " GPS_PORT_NAME) );
DEBUG_PORT.println( F(" GPS updates can be buffered. ") );
trace_header( DEBUG_PORT );
DEBUG_PORT.flush(); // including this fixed the code!!
if (gps.merging != NMEAGPS::EXPLICIT_MERGING)
DEBUG_PORT.println( F("Warning: EXPLICIT_MERGING should be enabled for best results!") );
gpsPort.attachInterrupt( GPSisr );
gpsPort.begin( 9600 );
// Configure the GPS. These are commands for MTK GPS devices. Other
// brands will have different commands.
//gps.send_P( &gpsPort, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only for MTK GPS devices
//I think the below line is what fried the GPS unit
//gps.send_P( &gpsPort, F("PMTK220,100") ); // 10Hz update rate for MTK GPS devices
// Enable the LED for blinking feedback
pinMode( ErrorLED, OUTPUT );
initSD();
waitForFix();
} // setup
//----------------------------------------------------------------
void loop()
{
GPSloop();
if (gps.overrun()) {
gps.overrun( false );
DEBUG_PORT.println( F("DATA OVERRUN: fix data lost!") );
}
}
//----------------------------------------------------------------
void initSD()
{
#ifdef SIMULATE_SD
DEBUG_PORT.println( F(" Simulating SD.") );
#else
DEBUG_PORT.println( F("Initializing SD card...") );
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
DEBUG_PORT.println( F(" SD card failed, or not present") );
// don't do anything more:
// Flicker the LED
while (true) {
digitalWrite(ErrorLED,HIGH);
delay(75);
digitalWrite(ErrorLED,LOW);
delay(75);
}
}
DEBUG_PORT.println( F(" SD card initialized.") );
// Pick a numbered filename, 00 to 99.
char filename[15] = "data_##.txt";
for (uint8_t i=0; i<100; i++) {
filename[5] = '0' + i/10;
filename[6] = '0' + i%10;
if (!SD.exists(filename)) {
// Use this one!
break;
}
}
logfile = SD.open(filename, FILE_WRITE);
if (!logfile) {
DEBUG_PORT.print( F("Couldn't create ") );
DEBUG_PORT.println(filename);
// If the file can't be created for some reason this leaves the LED on
// so I know there is a problem
digitalWrite(ErrorLED,HIGH);
while (true) {}
}
DEBUG_PORT.print( F("Writing to ") );
DEBUG_PORT.println(filename);
// GPS Visualizer requires a header to identify the CSV fields.
// If you are saving other data or don't need this, simply remove/change it
//logfile.println( F("latitude,longitude,time,loggingTime") );
trace_header( logfile ); // and uncomment #include Streamers.h
logfile.flush();
#endif
} // initSD
But when I update the file to include the button and LED's I get the following error when verifying:
"HardwareSerial0.cpp.o (symbol from plugin): In function Serial': (.text+0x0): multiple definition of __vector_18'
C:\Users\vogtmich\AppData\Local\Temp\arduino\sketches\BF06DFA7C8B2478606FFB219E5E2D8EE\libraries\NeoHWSerial-master\NeoHWSerial0.cpp.o (symbol from plugin):(.text+0x0): first defined here
HardwareSerial0.cpp.o (symbol from plugin): In function Serial': (.text+0x0): multiple definition of __vector_19'
C:\Users\vogtmich\AppData\Local\Temp\arduino\sketches\BF06DFA7C8B2478606FFB219E5E2D8EE\libraries\NeoHWSerial-master\NeoHWSerial0.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
exit status 1
Compilation error: exit status 1"
Here is the code that returns that error:
#include <Arduino.h>
#include <NMEAGPS.h>
//======================================================================
// Program: NMEASDlog.ino, highly editied to include:
//
// ErrorLED on pin 3
// Activation button double push with debounce on pin 2
//
// Description: This program is an interrupt-driven GPS logger.
// It uses the alternative serial port libraries NeoHWSerial,
// NeoSWSerial, or NeoICSerial.
//
// Prerequisites:
// 1) You have completed the requirements for NMEA_isr.ino
// 2) You have connected an SPI SD card and verified it is working
// with other SD utilities.
// 3) For logging faster than the default 1Hz rate, you have
// identified the required commands for your GPS device.
//
// 'Serial' is for debug output to the Serial Monitor window.
//
// 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/>.
//
//======================================================================
// SDFat examples work
// NMEA and NEMAisr both work
// NMEASDlog_UnoWORKS also works, as does StateChangeDetection_wDebounce_Sandbox.ino
#include <GPSport.h>
#include <Streamers.h>
//----------------------------------------------------------------
// Check configuration
#if !defined( GPS_FIX_TIME ) || !defined( GPS_FIX_LOCATION )
#error You must define TIME and LOCATION in GPSfix_cfg.h
#endif
#if !defined( NMEAGPS_PARSE_RMC )
#error You must define NMEAGPS_PARSE_RMC in NMEAGPS_cfg.h!
#endif
#ifndef NMEAGPS_INTERRUPT_PROCESSING
#error You must define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!
#endif
static NMEAGPS gps;
//----------------------------------------------------------------
// SD card includes and declarations
#include <SPI.h>
#include <SdFat.h>
SdFat SD;
const int chipSelect = 10;
//----------------------------------------------------------------
// Simulate SD For testing, it may be more convenient to simply print the
// GPS fix fields to the Serial Monitor. Simply uncomment
// this define to skip all SD operations. An SD card module
// does not have to be connected.
#define SIMULATE_SD
#ifdef SIMULATE_SD
auto &logfile = DEBUG_PORT;
#else
File logfile;
#endif
//----------------------------------------------------------------
// Simulate errors for LED testing purposes
//#define Simulate_Error // uncomment this line to simulate errors
//----------------------------------------------------------------
// Constants won't change:
const int buttonPin = 5; // the pin that the pushbutton is attached to
static const int GreenLED = 4; // the pin that the greenLED is attached to
const int ErrorLED = 3; // the pin that the error LED is attached to
// Variables will change:
int buttonPushCounter = 1; // counter for the number of button presses
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
// Bool variables:
bool running = false; // used to decide when to create a new file
// Unsigned Longs
unsigned long lastEvent = 0; // set a variable to record the last button press time
unsigned long debounce = 50; // set a debounce time
//----------------------------------------------------------------
void printL( Print & outs, int32_t degE7 ) {
// Extract and print negative sign
if (degE7 < 0) {
degE7 = -degE7;
outs.print( '-' );
}
// Whole degrees
int32_t deg = degE7 / 10000000L;
outs.print( deg );
outs.print( '.' );
// Get fractional degrees
degE7 -= deg*10000000L;
// Print leading zeroes, if needed
if (degE7 < 10L)
outs.print( F("000000") );
else if (degE7 < 100L)
outs.print( F("00000") );
else if (degE7 < 1000L)
outs.print( F("0000") );
else if (degE7 < 10000L)
outs.print( F("000") );
else if (degE7 < 100000L)
outs.print( F("00") );
else if (degE7 < 1000000L)
outs.print( F("0") );
// Print fractional degrees
outs.print( degE7 );
} // ^ Utility to print a long integer like it's a float
// with 9 significant digits.
//----------------------------------------------------------------
// Because the SD write can take a long time, GPSisr will store
// parsed data in the NMEAGPS 'buffer' array until GPSloop can get to it.
//
// The number of elements you should have in the array depends on
// two things: the speed of your SD card, and the update rate you
// have chosen.
//
// For an update rate of 10Hz (100ms period), two fixes are probably
// enough. Most cards take ~100ms to complete a write of 512 bytes.
// With FIX_MAX=2, two complete fixes can be stored, which were
// received in 200ms. A third fix can be started, giving a little
// more time before an overrun occurs, a total of about 250ms.
//
// If your card is slower or your update rate is faster, you should
// first build and run this program to determine the speed of your
// card. The time it takes to log one record is printed to the log
// file.
//
// After the program has run for a minute or two, remove the
// card and examine the loggingTimes. You may see that an interval
// was skipped, and you will also see an OVERRUN message on the
// DEBUG_PORT (usually Serial).
//
// You should calculate a new FIX_MAX from the maximum loggingTime
// you see in the log file:
//
// FIX_MAX = (max loggingTime)/(update period) + 1;
//
// For example, if the max loggingTime is 160ms, and the update period is
// 100ms (10Hz), then FIX_MAX = 160/100 + 1 = 2.
//
// Change the FIX_MAX value, build and run the program again. The
// SD log file should now contain all records, and no OVERRUN
// messages should have been printed on the DEBUG_PORT.
//
// If you do see an OVERRUN message, examine the loggingTime to see
// if it exceeded the maximum value from the previous build, and
// increase FIX_MAX.
//
// If you are also printing data to a Serial device, you could be
// printing too much information. In general, you must print less than
// (baudrate/10) characters per second. For example, if your baudrate
// is 9600, you must print less than 960 characters per second. And if
// the update rate is 10Hz, you must print no more than 96 characters
// per update.
//
// There are also restrictions on how much you should print to Serial in one
// section of code. If you print more than 64 characters (the output buffer
// size), then some prints will block until all characters can be stored in the
// output buffer.
//
// For example, if you try to print 80 characters, the first 64 characters
// will be immediately stored in the output buffer. However, the last 16
// characters must wait until the output buffer has room for 16 more
// characters. That takes 16 * (10/baudrate) milliseconds. At 9600 baud
// that will take 17ms. The loggingTimes will show no less than 17ms per
// record, and will occasionally include the longer SD write time of ~100ms.
//----------------------------------------------------------------
static void GPSloop() {
if (gps.available()) {
gps_fix fix = gps.read();
// Log the fix information if we have a location and time
if (fix.valid.location && fix.valid.time) {
static uint16_t lastLoggingTime = 0;
uint16_t startLoggingTime = millis();
// If you like the CSV format implemented in Streamers.h,
// you could replace all these prints with
trace_all( logfile, gps, fix ); // uncomment include Streamers.h
// flush() is used to empty the contents of the SD buffer to the SD.
// If you don't call flush, the data will fill up the SdFat buffer
// of 512bytes and flush itself automatically.
//
// To avoid losing data or corrupting the SD card file system, you must
// call flush() at least once (or close()) before powering down or pulling
// the SD card.
//
// It is *strongly* recommended that you use some external event
// to close the file. For example, staying within 50m of the moving
// average location for 1 minute, or using a switch to start and stop
// logging. It would also be good to provide a visual indication
// that it is safe to power down and/or remove the card, perhaps via
// the LED.
//
// To reduce the amount of data that may be lost by an abnormal shut down,
// you can call flush() periodically.
//
// Depending on the amount of data you are printing, you can save
// *a lot* of CPU time by not flushing too frequently. BTW, flushing
// every time at 5Hz is too frequent.
// This shows how to flush once a second.
static uint16_t lastFlushTime = 0;
if (startLoggingTime - lastFlushTime > 1000) {
lastFlushTime = startLoggingTime; // close enough
logfile.flush();
}
#ifdef SIMULATE_SD
// Simulate the delay of writing to an SD card. These times are
// very long. This is intended to show (and test) the overrun detection.
//
// On a 1Hz GPS, delaying more than 2 seconds here, or more than
// 2 seconds in two consecutive updates, will cause OVERRUN.
//
// Feel free to try different delays to simulate the actual behavior
// of your SD card.
uint16_t t = random(0,5); // 0..4
t += 3; // 3..7
t = t*t*t*t; // 81..2401ms
delay( t ); // cause an OVERRUN
#endif
// All logging is finished, figure out how long that took.
// This will be written in the *next* record.
lastLoggingTime = (uint16_t) millis() - startLoggingTime;
}
}
} // GPSloop
//----------------------------------------------------------------
void GPSisr( uint8_t c ) {
gps.handle( c );
} // GPSisr
//----------------------------------------------------------------
static void waitForFix() {
DEBUG_PORT.print( F("Waiting for GPS fix...") );
uint16_t lastToggle = millis();
for (;;) {
if (gps.available()) {
if (gps.read().valid.location)
break; // Got it!
}
// Slowly flash the LED until we get a fix
if ((uint16_t) millis() - lastToggle > 500) {
lastToggle += 500;
digitalWrite( ErrorLED, !digitalRead(ErrorLED) );
DEBUG_PORT.write( '.' );
}
}
DEBUG_PORT.println();
digitalWrite( ErrorLED, LOW );
gps.overrun( false ); // we had to wait a while...
} // waitForFix
// ^ This routine waits for GPSisr to provide
// a fix that has a valid location.
//
// The ErrorLED is slowly flashed while it's waiting.
//----------------------------------------------------------------
void setup() {
// initialize serial communication:
DEBUG_PORT.begin(9600);
while (!DEBUG_PORT)
; // wait for serial port to connect.
DEBUG_PORT.println();
DEBUG_PORT.println( F("GPSSDlog_StateChangeDetection_wDebounce_Sandbox.ino started!") );
DEBUG_PORT.print( F("fix object size = ") );
DEBUG_PORT.println( sizeof(gps_fix()) );
DEBUG_PORT.println( NMEAGPS_FIX_MAX );
DEBUG_PORT.print( F("NMEAGPS object size = ") );
DEBUG_PORT.println( sizeof(gps) );
DEBUG_PORT.println( F("Looking for GPS device on " GPS_PORT_NAME) );
DEBUG_PORT.println( F(" GPS updates can be buffered. ") );
trace_header( DEBUG_PORT );
DEBUG_PORT.flush(); // including this fixed the code!!
if (gps.merging != NMEAGPS::EXPLICIT_MERGING)
DEBUG_PORT.println( F("Warning: EXPLICIT_MERGING should be enabled for best results!") );
// initialize gps communications
gpsPort.attachInterrupt( GPSisr );
gpsPort.begin( 9600 );
// initialize the button pin as a input:
pinMode(buttonPin, INPUT);
// initialize the LED as an output:
pinMode(GreenLED, OUTPUT);
//start the program with the light off.
digitalWrite(GreenLED, LOW);
// initialize error LED for blinking feedback
pinMode(ErrorLED, OUTPUT);
digitalWrite(ErrorLED, LOW);
// initialize SD card writing, file creation, and header-rows
//initSD();
//waitForFix();
} // setup
//----------------------------------------------------------------
void loop() {
// read the pushbutton input pin:
buttonState = digitalRead(buttonPin); // this could go in the checkButton function
checkButton(); // check the button state
ButtonAction(); // do the button thing
//checkError(); // check for and report simulated errors
}
void checkButton() {
// compare the buttonState to its previous state & take into account debounce
if (buttonState != lastButtonState && millis() - lastEvent > debounce) {
//record the time of the last "good" event
lastEvent = millis();
// if the state has changed, increment the counter
if (buttonState == HIGH) {
// if the current state is HIGH then the button went from off to on:
buttonPushCounter++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter);
} else {
// if the current state is LOW then the button went from on to off:
Serial.println("off");
}
}
// save the current state as the last state, for next time through the loop
lastButtonState = buttonState;
} // check if the button was pressed
void ButtonAction() {
// turns on the LED every 3 button pushes by checking the modulo of the
// button push counter. the modulo function gives you the remainder of the
// division of two numbers:
if (buttonPushCounter % 3 == 0) {
digitalWrite(GreenLED, HIGH);
if (running == false) {
initSD();
waitForFix();
running = true; // only do these once when triggered
}
GPSloop();
if (gps.overrun()) {
gps.overrun( false );
DEBUG_PORT.println( F("DATA OVERRUN: fix data lost!") );
}
} else {
digitalWrite(GreenLED, LOW); // should I also logfile.flush() and close the file here?
running = false;
}
} // initiateSD and log gps data when turned on, reset when off.
void checkError() {
// simulate an error state by dividing buttonPushCounter by 7
#ifdef Simulate_Error
if (buttonPushCounter % 7 == 0) {
digitalWrite(ErrorLED, HIGH);
} else {
digitalWrite(ErrorLED, LOW);
}
#endif
} // check for simulated errors
void initSD() {
#ifdef SIMULATE_SD
DEBUG_PORT.println( F(" Simulating SD.") );
#else
DEBUG_PORT.println( F("Initializing SD card...") );
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
DEBUG_PORT.println( F(" SD card failed, or not present") );
// don't do anything more:
// Flicker the LED
while (true) {
digitalWrite(ErrorLED,HIGH);
delay(75);
digitalWrite(ErrorLED,LOW);
delay(75);
}
}
DEBUG_PORT.println( F(" SD card initialized.") );
// Pick a numbered filename, 00 to 99.
char filename[15] = "data_##.txt";
for (uint8_t i=0; i<100; i++) {
filename[5] = '0' + i/10;
filename[6] = '0' + i%10;
if (!SD.exists(filename)) {
// Use this one!
break;
}
}
logfile = SD.open(filename, FILE_WRITE);
if (!logfile) {
DEBUG_PORT.print( F("Couldn't create ") );
DEBUG_PORT.println(filename);
// If the file can't be created for some reason this leaves the LED on
// so I know there is a problem
digitalWrite(ErrorLED,HIGH);
while (true) {}
}
DEBUG_PORT.print( F("Writing to ") );
DEBUG_PORT.println(filename);
// GPS Visualizer requires a header to identify the CSV fields.
// If you are saving other data or don't need this, simply remove/change it
//logfile.println( F("latitude,longitude,time,loggingTime") );
trace_header( logfile ); // and uncomment #include Streamers.h
logfile.flush();
#endif
} // initSD
I'm not sure where vector 18 and vector 19 are defined or how to fix this error. Is this a problem with the logic of my updated code or is this a problem with the way the NeoGPS is using Rx as a serial input and the IDE as a serial output? and if it is a problem with the libraries, where and how can I fix it? And so I can more deeply understand and write better code in the future, why does it cause an error in the second code, but not in the first?
Thank you for any direction you can give!