GPS Logging with Teensy 2

Status
Not open for further replies.

subsix

New member
Hello everybody,

I have a Teensy 2, and i want to be able to log the NMEA message from a EM406 GPS

I have take the sketch from http://www.ladyada.net/make/gpsshield/download.html
and i want to use with HardwareSerial Uart for the serial btw gps and teensy

The compilation seem to be good, the teensy run correctly (16 or 8mhz/sdcard), create the log file fine ... but log only ONE sequence in the file, or sometimes, nothing.

If you have any suggestion ...

Code:
#include <SD.h>
#include "GPSconfig.h"

const int buttonPin = 17;     // Declare PIN 17 for USB mass-storage/charging control
int buttonState = 0;          // State button int

// what to log
#define LOG_RMC 1 // RMC-Recommended Minimum Specific GNSS Data, message 103,04

HardwareSerial Uart = HardwareSerial(); // Pin7 Rx Pin8 Tx

// Set the pins used 
#define led1Pin 15 // Green LED GPS valid position
#define led2Pin 14 // Red LED Writing data on SDcard
#define pin16 16 // USB and charging mode control
#define chipSelect 0

#define BUFFSIZE 90
char buffer[BUFFSIZE];
uint8_t bufferidx = 0;
bool fix = false;
bool gotGPRMC;
uint8_t i;
File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// blink out an error code
void error(uint8_t errno) {
/*
  if (SD.errorCode()) {
    putstring("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  */
  while(1) {
    for (i=0; i<errno; i++) {
      digitalWrite(led1Pin, HIGH);
      delay(100);
      digitalWrite(led2Pin, HIGH);
      delay(100);
      digitalWrite(led1Pin, LOW);
      delay(100);
      digitalWrite(led2Pin, LOW);
      delay(100);
    }
    for (; i<10; i++) {
      delay(200);
    }
  }  
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // Set input button pin & pull-up on analog pin 17
  //Serial.begin(9600);
  //Serial.println("\r\nGPSlogger");
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
 
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(0, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    //Serial.println("Card init. failed!");
    error(1);
  }
  strcpy(buffer, "GPSLOG00.LOG");
  for (i = 0; i < 100; i++) {
    buffer[6] = '0' + i/10;
    buffer[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(buffer)) {
      break;
    }
  }
  logfile = SD.open(buffer, FILE_WRITE);
  if( ! logfile ) {
    //Serial.print("Couldnt create "); Serial.println(buffer);
    error(3);
  }
  //Serial.print("Writing to "); Serial.println(buffer); 
  //Serial.println("Ready!");
  
  Uart.begin(4800);
  delay(250);

#if (LOG_RMC == 1)
    Serial.print(RMC_ON);
#else
    Serial.print(RMC_OFF);
#endif
  delay(250);
}

void loop() {
    char c;
    uint8_t sum;    

    buttonState = digitalRead(buttonPin); // Read button state
    if (buttonState == LOW) {
    digitalWrite(pin16, HIGH); // Enabling charging mode to LTC4054
    Serial.begin(9600);  // Start serial.begin, open SDCARD to get log
    delay(20000);
    } 
    else {
    Serial.end();  // Normal mode, disable USB for power saving (4ma off)
    }
  
  // read one 'line'
  if (Uart.available()) {
    c = Uart.read();
#if ARDUINO >= 100
    //Serial.write(c);
#else
    //Serial.print(c, BYTE);
#endif
    if (bufferidx == 0) {
      while (c != '$')
        c = Uart.read(); // wait till we get a $
    }
    buffer[bufferidx] = c;

#if ARDUINO >= 100
    //Serial.write(c);
#else
    //Serial.print(c, BYTE);
#endif
    if (c == '\n') {
      //putstring_nl("EOL");
      //Serial.print(buffer);
      buffer[bufferidx+1] = 0; // terminate it

      if (buffer[bufferidx-4] != '*') {
        // no checksum?
        Serial.print('*');
        bufferidx = 0;
        return;
      }
      // get checksum
      sum = parseHex(buffer[bufferidx-3]) * 16;
      sum += parseHex(buffer[bufferidx-2]);

      // check checksum
      for (i=1; i < (bufferidx-4); i++) {
        sum ^= buffer[i];
      }
      if (sum != 0) {
        //putstring_nl("Cxsum mismatch");
        //Serial.print('~');
        bufferidx = 0;
        return;
      }
      // got good data!
      gotGPRMC = strstr(buffer, "GPRMC");
      if (strstr(buffer, "GPRMC")) {
        // find out if we got a fix
        char *p = buffer;
        p = strchr(p, ',')+1;
        p = strchr(p, ',')+1;       // skip to 3rd item

        if (p[0] == 'V') {
          digitalWrite(led1Pin, LOW);
          delay(100);
          fix = false;
        } else {
          digitalWrite(led1Pin, HIGH);
          delay(100);
          digitalWrite(led1Pin, LOW);    // set the LED off
          delay(100);              // wait for a second
          fix = true;
        }
      }
      // rad. lets log it!
      //Serial.print(buffer);
      //Serial.print('#');
      
      if (gotGPRMC)      //If we have a GPRMC string
      {
        // Bill Greiman - need to write bufferidx + 1 bytes to getCR/LF
        bufferidx++;
        
      digitalWrite(led2Pin, HIGH);      // sets the digital pin as output
      delay(100);
            // Bill Greiman - need to write bufferidx + 1 bytes to getCR/LF
    
      logfile.write((uint8_t *) buffer, bufferidx);
      logfile.flush();
      /*
      if( != bufferidx) {
         putstring_nl("can't write!");
         error(4);
      }
      */
      digitalWrite(led2Pin, LOW);
      bufferidx = 0;
      }
       return;
      }
    }
    bufferidx++;
    if (bufferidx == BUFFSIZE-1) {
       Serial.print('!');
       bufferidx = 0;
    }
   }
/* End code */
 
Not sure if I can help, but I do have a suggestion you could try (its an easy one too).

I use the Adafruit Ultimate GPS (MTK3339 not EM406) on a Teensy 3.0, and only I receive partial NMEA messages unless I set:
Code:
Serial.begin(115200);
 
Not sure if I can help, but I do have a suggestion you could try (its an easy one too).

I use the Adafruit Ultimate GPS (MTK3339 not EM406) on a Teensy 3.0, and only I receive partial NMEA messages unless I set:
Code:
Serial.begin(115200);

thx ZTiK.nl

the default baudrate of MTK3339 is 115200 ?
because my EM406 use 4800 default u know

u set it before receiving data ?
 
Yeah I do, this is how I coded my setup() loop:
Code:
void setup()  
{
  Serial.begin(115200); // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  Serial.println("Adafruit GPS library basic test!");

  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // turn on RMC (recommended minimum)
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // Set the update rate
  Serial.println(PMTK_Q_RELEASE); // Ask for firmware version
}


This is straight out of the example ino file for my gps module.
Not saying this HAS to work for you, but it would be a shame if this turned out to be the issue after many days troubleshooting :x

Ow, my GPS module runs at 9600br as you can see above
I have the GPS mod running at 9600br, but the Serial interface at 115200br
 
Last edited:
finally rewrite the code with AltSerialSoft, and it work fine

Code:
#include <SD.h>
#include <AltSoftSerial.h>

const int buttonPin = 17;     // Declare PIN 17 for charging control
int buttonState = 0;          // State button int

// Set the pins used 
#define led2Pin 15 //Get data from GPS
#define pin16 16  //PILOT CHARGING
ADCSRA = 0;   // shut off ADC

AltSoftSerial gpsSerial;

const int chipSelect = 0;

#define BUFFSIZE 90
char buffer[BUFFSIZE];
uint8_t bufferidx = 0;
bool fix = false; // current fix data
bool gotGPRMC;    //true if current data is a GPRMC strinng
//bool gotGPVTG;    //true if current data is a GPRMC strinng
//bool gotGPGGA;    //true if current data is a GPRMC strinng
uint8_t i;
File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// blink out an error code
void error(uint8_t errno) {
/*
  if (SD.errorCode()) {
    putstring("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  */
  while(1) {
    for (i=0; i<errno; i++) {
      digitalWrite(led2Pin, HIGH);
      delay(100);
      digitalWrite(led2Pin, LOW);
      delay(100);
    }
    for (; i<10; i++) {
      delay(200);
    }
  }
}

void setup() {
  Serial.begin(9600);
  gpsSerial.begin(4800);
  gpsSerial.print("$PSRF103,04,00,255,01*25\r\n"); // 
  //gpsSerial.print("$PSRF103,00,01,60,00*25"); // 
    
  Serial.println("\r\nStarting...");
  pinMode(led2Pin, OUTPUT);
  pinMode(pin16, OUTPUT);
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(0, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card init. failed!");
    error(1);
  }

  strcpy(buffer, "GPSLOG00.TXT");
  for (i = 0; i < 100; i++) {
    buffer[6] = '0' + i/10;
    buffer[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(buffer)) {
      break;
    }
  }

  logfile = SD.open(buffer, FILE_WRITE);
  if( ! logfile ) {
    Serial.print("Couldnt create"); 
    Serial.println(buffer);
    error(3);
  }
  Serial.print("Starting to log on ..."); 
  Serial.println(buffer);
  pinMode(buttonPin, INPUT_PULLUP); // Set input buttonpin & pull-up on analog pin 17
}

void loop() {
  //Serial.println(Serial.available(), DEC);
  char c;
  uint8_t sum;

  // read one 'line'
  if (gpsSerial.available()) {
    c = gpsSerial.read();

    if (bufferidx == 0) {
      while (c != '$')
        c = gpsSerial.read(); // wait till we get a $
    }
    buffer[bufferidx] = c;

    if (c == '\n') {

      buffer[bufferidx+1] = 0; // terminate it

      if (buffer[bufferidx-4] != '*') {
        // no checksum?
        Serial.print('*');
        bufferidx = 0;
        return;
      }
      // get checksum
      sum = parseHex(buffer[bufferidx-3]) * 16;
      sum += parseHex(buffer[bufferidx-2]);

      // check checksum
      for (i=1; i < (bufferidx-4); i++) {
        sum ^= buffer[i];
      }
      if (sum != 0) {
        //putstring_nl("Cxsum mismatch");
        Serial.print('~');
        bufferidx = 0;
        return;
      }
      // got good data!

      gotGPRMC = strstr(buffer, "GPRMC");
      if (gotGPRMC)
      {
        // find out if we got a fix
        char *p = buffer;
        p = strchr(p, ',')+1;
        p = strchr(p, ',')+1;       // skip to 3rd item
        
        if (p[0] == 'A') {
          fix = false;
        } else {
          fix = true;
        }
      }      
      
      // rad. lets log it!
      
      Serial.print(buffer);    //first, write it to the serial monitor
      Serial.print('#');
      
      if (gotGPRMC)      //If we have a GPRMC string
      {
        // Bill Greiman - need to write bufferidx + 1 bytes to getCR/LF
        bufferidx++;
        delay(10000); //Write the sentence every 10 sec
        digitalWrite(led2Pin, HIGH);      // Turn on LED 2 (indicates write to SD)

        logfile.write((uint8_t *) buffer, bufferidx);    //write the string to the SD file
        logfile.flush();
        /*
        if( != bufferidx) {
           putstring_nl("can't write!");
           error(4);
        }
        */

        digitalWrite(led2Pin, LOW);    //turn off LED2 (write to SD is finished)
        bufferidx = 0;    //reset buffer pointer
        return;
      }//if (gotGPRMC)
      
    }
    bufferidx++;
    if (bufferidx == BUFFSIZE-1) {
       Serial.print('!');
       bufferidx = 0;
    }
  } else {

  }
  
    buttonState = digitalRead(buttonPin); // Read button state
    if (buttonState == LOW) {
    digitalWrite(pin16, HIGH); // Enabling charging mode to LTC4054
    }

}
/* End code */
 
Status
Not open for further replies.
Back
Top