Here's the interesting part. query() is called once by setup() and requests time/location info from the GPS using readline(). That's the only time it's used. The rest of the code is given below.
void query(){
gpsSerial.begin(4800); // 4800 baud rate
// send instructions to GPS about data needed
gpsSerial.print(SERIAL_SET); delay(250);
gpsSerial.print(DDM_OFF); delay(250);
gpsSerial.print(GGA_ON); delay(250);
gpsSerial.print(GLL_OFF); delay(250);
gpsSerial.print(GSA_OFF); delay(250);
gpsSerial.print(GSV_OFF); delay(250);
gpsSerial.print(RMC_OFF); delay(250);
gpsSerial.print(VTG_OFF); delay(250);
gpsSerial.print(WAAS_OFF); delay(250);
int done = 0;
while(!done){
readline(); // this reads serial input and updates the buffer
if(strncmp(buffer, "$GPGGA",6) == 0){
Serial.print(millis()); Serial.print(","); Serial.println(buffer);
outfile.print(millis()); outfile.print(","); outfile.println(buffer);
done = 1;
}
}
}
/////////////////////////////////////////////////////////////////////
void readline() { // this reads serial input and updates the buffer
char c;
uint8_t bufferidx = 0;
digitalWrite(red, HIGH);
int n = 0;
while (1) {
n++; if(n > 10000){break;}
if(gpsSerial.available()){
c = gpsSerial.read();
if (c == -1){
continue;
}
if (c == '\n'){
continue;
}
if ((bufferidx == 90-1) || (c == '\r')) { // buffer size 90
buffer[bufferidx] = 0;
return;
}
buffer[bufferidx++]= c;
}
else{
}
}
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
} // end of readline
Full code:
// user settings
#define SAMPLE_INT 25 // number of ms between samples
#define FLUSH_INT 1000 // number of ms between writing buffer to SD
#define USE_SERIAL 1 // if 1, print info to serial connection at 115200
#define AREF 3.3 //
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
#include <SD.h>
#include <GPSconfig.h>
#include <SoftwareSerial.h>
// digital pins for LEDs
#define red 6
#define green 5
// measurement pins
#define CHAN1_PIN 0
#define CHAN2_PIN 1
#define CHAN3_PIN 2
#define CHAN1_GND 3 // these are for the pins fixed at 0 volts
#define CHAN2_GND 4
#define CHAN3_GND 5
#define POWERPIN 7 // for GPS
#define CHIPSELECT 10 // required for SD card use
// Vcc measurement stuff
#define BANDGAPREF 14 // special indicator that we want to measure the bandgap
#define aref_voltage 3.3 // we tie 3.3V to ARef and measure it with a multimeter!
#define bandgap_voltage 1.1 // this is not super guaranteed but its not -too- off
// initialize global variables
uint32_t t = 0;
uint32_t lastflush = 0;
File outfile;
SoftwareSerial gpsSerial = SoftwareSerial(3, 4);
char buffer[90];
volatile uint32_t pps = 0;
/////////////////////////////////////////////////////////////////////
void readline() { // this reads serial input and updates the buffer
char c;
uint8_t bufferidx = 0;
digitalWrite(red, HIGH);
int n = 0;
while (1) {
n++; if(n > 10000){break;}
if(gpsSerial.available()){
c = gpsSerial.read();
if (c == -1){
continue;
}
if (c == '\n'){
continue;
}
if ((bufferidx == 90-1) || (c == '\r')) { // buffer size 90
buffer[bufferidx] = 0;
return;
}
buffer[bufferidx++]= c;
}
else{
}
}
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
} // end of readline
/////////////////////////////////////////////////////////////////////
void query(){
gpsSerial.begin(4800); // 4800 baud rate
// send instructions to GPS about data needed
gpsSerial.print(SERIAL_SET); delay(250);
gpsSerial.print(DDM_OFF); delay(250);
gpsSerial.print(GGA_ON); delay(250);
gpsSerial.print(GLL_OFF); delay(250);
gpsSerial.print(GSA_OFF); delay(250);
gpsSerial.print(GSV_OFF); delay(250);
gpsSerial.print(RMC_OFF); delay(250);
gpsSerial.print(VTG_OFF); delay(250);
gpsSerial.print(WAAS_OFF); delay(250);
int done = 0;
while(!done){
readline(); // this reads serial input and updates the buffer
if(strncmp(buffer, "$GPGGA",6) == 0){
Serial.print(millis()); Serial.print(","); Serial.println(buffer);
outfile.print(millis()); outfile.print(","); outfile.println(buffer);
done = 1;
}
}
}
/////////////////////////////////////////////////////////////////////
void error(char *str)
{
#if USE_SERIAL
Serial.print("error: ");
Serial.println(str);
#endif
outfile.println(); outfile.println(str);
outfile.flush();
digitalWrite(red, HIGH);
while(1);
}
void PPS(void)
{
pps++;
}
/*
ISR(INT0_vect)
{
pps++;
}
*/
//////////////////////////////////////////////////////////////////////
void setup(void)
{
// start LEDs
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
// start ground pins for analog channels
analogWrite(CHAN1_GND, 0);
analogWrite(CHAN2_GND, 0);
analogWrite(CHAN3_GND, 0);
// start serial connection, if necessary
#if USE_SERIAL
Serial.begin(115200);
Serial.println();
Serial.print("SD card setup...");
#endif
// setup card
pinMode(CHIPSELECT, OUTPUT);
if(!SD.begin(CHIPSELECT)){
error("No SD card detected!");
}
#if USE_SERIAL
Serial.print("detected...");
#endif
// create a new file
char filename[] = "RECORD00.txt";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
outfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if(!outfile) {
error("Failed to open file!");
}
#if USE_SERIAL
Serial.print("writing to file ");
// Serial.println(filename);
#endif
// GPS stuff:
pinMode(3, INPUT);
pinMode(4, OUTPUT);
pinMode(POWERPIN, OUTPUT);
digitalWrite(POWERPIN, LOW);
// set a PPS interrupt (pin 2)
/* EICRA = _BV(ISC01); //external interrupt on falling edge
EIFR = _BV(INTF0); //clear the interrupt flag
EIMSK = _BV(INT0); //enable external interrupt
*/
Serial.println("Ready!");
delay(2000);
query(); // request GPS time
attachInterrupt(0, PPS, RISING);
outfile.println("time(ms),chan1,chan2,chan3,vcc,ppstime");
#if USE_SERIAL
Serial.println("time(ms),chan1,chan2,chan3,vcc,ppstime,flush");
#endif
}
void loop(void)
{
// delay for the amount of time we want between readings
if((millis() - t) < SAMPLE_INT){ // JFA 2013/1/25 14:28--try to avoid skipped samples by only delaying if it hasn't already reached the next one
delay((SAMPLE_INT - 1) - (millis() % SAMPLE_INT));
}
// log milliseconds since starting
t = millis();
outfile.print(t); outfile.print(", ");
#if USE_SERIAL
Serial.print(t); Serial.print(", ");
#endif
// read analog channels
analogRead(CHAN1_PIN); delay(1); int chan1 = analogRead(CHAN1_PIN);
analogRead(CHAN2_PIN); delay(1); int chan2 = analogRead(CHAN2_PIN);
analogRead(CHAN3_PIN); delay(1); int chan3 = analogRead(CHAN3_PIN);
// Log the estimated 'VCC' voltage by measuring the internal 1.1v ref
analogRead(BANDGAPREF); delay(1); int refReading = analogRead(BANDGAPREF);
float supplyvoltage = (bandgap_voltage * 1024) / refReading;
// write to SD card buffer
outfile.print(chan1); outfile.print(",");
outfile.print(chan2); outfile.print(",");
outfile.print(chan3); outfile.print(",");
outfile.print(supplyvoltage); outfile.print(",");
outfile.print(pps);
outfile.println();
// write to the serial connection
#if USE_SERIAL
Serial.print(chan1); Serial.print(",");
Serial.print(chan2); Serial.print(",");
Serial.print(chan3); Serial.print(",");
Serial.print(supplyvoltage); Serial.print(",");
Serial.print(pps);
#endif
// check to see if it's time to flush SD buffer. If yes, flush it. This transfers 2048 bytes.
if ((millis() - lastflush) < FLUSH_INT){
#if USE_SERIAL
Serial.println(",0");
#endif
}
else{
lastflush = millis();
// blink red LED to indicate flush
digitalWrite(red, HIGH);
outfile.flush();
digitalWrite(red, LOW);
#if USE_SERIAL
Serial.println(",1");
#endif
}
}
The dependency GPSconfig.h is attached.
GPSconfig.h (1.8 KB)