Day: April 20, 2018💾

📽️ Videos

Arduino GPS Logger Code I Wrote

This is the code current version of the code I use for my GPS logger, which is powered by a Neo 6M GPS unit, an Arduino SD Card Reader with an 8 GB MicroSD Card, and an Arduino Nano. It logs a wide variety of information about my current location, speed of travel, and other information so I can easily look back at my trip.

Below is the current version of the code I use for my GPS logger, which is powered by a Neo 6M GPS unit, an Arduino SD Card Reader with an 8 GB MicroSD Card, and an Arduino Nano. It logs a wide variety of information about my current location, speed of travel, and other information so I can easily look back at my trip.

 GPS Logger

/*
   GPS Logger

      SD card attached to SPI bus as follows:
    *  ** CS - pin 10
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13

*/

#include <TinyGPS++.h>
char p_buffer[100];
#define P(str) (strcpy_P(p_buffer, PSTR(str)), p_buffer)

#define HOMELAT  42.614277
#define HOMELNG -73.851662

#include <SoftwareSerial.h>

// The serial connection to the GPS module
SoftwareSerial ss(4, 3);

// The TinyGPS++ object
TinyGPSPlus gps;

// Line Buffer to Save to File
char lnBuffer[115];

// Decimal to Number Char String Buffer
char numStr[30];

// delay
uint8_t prevSecond;

// data logger
#include <SPI.h>
#include <SD.h>

const uint8_t chipSelect = 10;

// location of previous location, used
// to calculate distance traveled
float prevLat = 0;
float prevLng = 0;
float prevAlt = 0; // stored in meters
float prevSpeed = 0; // stored in meters per second
float prevTime = 0;

// keep a running total of miles since last boot
float milesSinceBoot = 0;

// filename
char fileName[13];

// don't do anything if card is bad
bool cardWorks = false;

void setup() {
  Serial.begin(115200);
  ss.begin(9600);
  for (uint8_t i = 6; i < 9; i++) {
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }


  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println(F("Card failed, or not present"));
    digitalWrite(8, HIGH); //red
    cardWorks = false;

    // don't do anything more:
    return;
  }

  cardWorks = true;
  Serial.println(F("card initialized."));
  digitalWrite(6, HIGH);  // green

  fileName[0] = '\0';
}

void loop() {
  if (!cardWorks) {

    return;
  }

  while (ss.available() > 0) {
    gps.encode(ss.read());
  }

  // if no GPS blink red LED
  if (millis() > 5000 && gps.charsProcessed() < 10 && millis() % 1000 == 0) {
    digitalWrite(8, HIGH); //red
  }
  else if (millis() > 5000 && gps.charsProcessed() < 10 && millis() % 500 == 0) {
    digitalWrite(8, LOW); // red
  }

  // check if we have a valid location and blink yellow if invalid
  if (gps.location.isValid()) {
    digitalWrite(7, LOW);  // yellow
  }
  // next two lines will blink yellow (eye catching!)
  else if (!gps.location.isValid() && millis() % 1000 == 0) {
    digitalWrite(7, HIGH);  // yellow
  }
  else if (!gps.location.isValid() && millis() % 500 == 0) {
    digitalWrite(7, LOW);  // yellow
  }

  if (gps.location.isValid() && gps.time.second() != prevSecond) {

    // before we forget, log previous second
    prevSecond = gps.time.second();

    // if no file name, create
    if (fileName[0] == '\0') {
      // create filename
      // Example Filename = 03140201 (year=17, month=03, date=14, hour=02, tripnumber = 0
      uint8_t trip = 1;
      sprintf(fileName, P("%02d%02d%02d%02d.CSV"), gps.date.year() - 2000, gps.date.month(), gps.date.day(), trip);

      // well, if we have made 99 trips today (usually due to bad power connection) only write final trip
      while (SD.exists(fileName) && trip < 99) {
        trip++;
        sprintf(fileName, P("%02d%02d%02d%02d.CSV"), gps.date.year() - 2000, gps.date.month(), gps.date.day(), trip);
      }

      // print to serial where this data is being saved
      Serial.print(P("Writing to ... "));
      Serial.print(fileName);
      Serial.print(P("\n"));

      // write header to file
      File dataFileHead = SD.open(fileName, FILE_WRITE);

      // if not able to write, then turn LED red
      if (!dataFileHead) {
        digitalWrite(6, LOW);  // green
        digitalWrite(8, HIGH); //red
      }

      if (dataFileHead && trip != 99) {
        dataFileHead.println(P("year,month,day,hour,minute,second,sat,latitude,longitude,elev,mph,dir,cdir,grade,accel,trip,mihm,dirhm"));
        Serial.println( P("year,month,day,hour,minute,second,sat,latitude,longitude,elev,mph,dir,cdir,grade,accel,trip,mihm,dirhm"));
        lnBuffer[0] = '\0';
        dataFileHead.close();

        digitalWrite(6, HIGH);  // green
        digitalWrite(8, LOW); //red
      }

    }

    // dont log if no satellites found
    if (!gps.satellites.value()) return;

    sprintf(numStr, P("%04d,%02d,%02d,%02d,%02d,%02d, "), gps.date.year(), gps.date.month(), gps.date.day(), gps.time.hour(), gps.time.minute(), gps.time.second());
    strcat(lnBuffer, numStr);


    dtostrf(gps.satellites.value(), 3, 0, numStr);
    if (gps.satellites.isValid())
      strcat(lnBuffer, numStr);
    strcat(lnBuffer, P(", "));


    dtostrf(gps.location.lat(), 10, 6, numStr);
    if (gps.location.isValid())
      strcat(lnBuffer, numStr);

    strcat(lnBuffer, P(", "));


    dtostrf(gps.location.lng(), 10, 6, numStr);

    if (gps.location.isValid())
      strcat(lnBuffer, numStr);

    strcat(lnBuffer, P(", "));

    if (gps.altitude.isValid())
      dtostrf(gps.altitude.feet(), 5, 0, numStr);

    strcat(lnBuffer, numStr);

    // we only add the additional info if we have enough buffer space
    // as occassionally before I was accidentially causing the buffer to
    // overflow. In an idea world, I'd use a bigger buffer but RAM is limited
    // e.g. if (strlen(lnBuffer) < 100)

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, P(", "));

    dtostrf(gps.speed.mph(), 0, 1, numStr);

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, numStr);

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, P(", "));

    dtostrf(gps.course.deg(), 0, 1, numStr);

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, numStr);

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, P(", "));

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, TinyGPSPlus::cardinal(gps.course.deg()));

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, P(", "));

    // calculate current grade -- if we have a change in altitude
    // and we've traveled some kind of distance

    if (gps.altitude.isValid() && (gps.altitude.meters() - prevAlt) != 0 && TinyGPSPlus::distanceBetween(
          gps.location.lat(),
          gps.location.lng(),
          prevLat,
          prevLng) != 0) {


      dtostrf(
        (gps.altitude.meters() - prevAlt) /
        TinyGPSPlus::distanceBetween(
          gps.location.lat(),
          gps.location.lng(),
          prevLat,
          prevLng)

        , 5, 2, numStr);

      if (strlen(lnBuffer) < 100)
        strcat(lnBuffer, numStr);
    }
    else {
      if (strlen(lnBuffer) < 100)
        strcat(lnBuffer, P("0.00"));
    }

    // acceleration
    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, P(", "));

    dtostrf((gps.speed.mps() - prevSpeed) / (millis() - prevTime), 7, 4, numStr);

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, numStr);

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, P(", "));



    // total milage of trip at this part of logging
    // only increment when moving to minimize
    // "idle" gps hop

    if (prevLat && gps.speed.mph() > 1) {
      milesSinceBoot +=  TinyGPSPlus::distanceBetween(
                           gps.location.lat(),
                           gps.location.lng(),
                           prevLat,
                           prevLng) * 0.00062137112; // meters to miles
    }

    dtostrf( milesSinceBoot, 5, 2, numStr);

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, numStr);

    if (strlen(lnBuffer) < 100)
      strcat(lnBuffer, P(", "));

    // miles from home
    dtostrf( TinyGPSPlus::distanceBetween(
               gps.location.lat(),
               gps.location.lng(),
               HOMELAT, HOMELNG) * 0.00062137112, 5, 2, numStr);

    if (strlen(lnBuffer) < 105)
      strcat(lnBuffer, numStr);

    // direction from home (for shits and giggles)

    if (strlen(lnBuffer) < 105)
      strcat(lnBuffer, P(", "));

    if (strlen(lnBuffer) < 110)
      strcat(lnBuffer,     TinyGPSPlus::cardinal(TinyGPSPlus::courseTo(
               HOMELAT, HOMELNG,
               gps.location.lat(),
               gps.location.lng()
             )));


    // save previous lat/lng/alt
    prevLat = gps.location.lat();
    prevLng = gps.location.lng();
    prevAlt = gps.altitude.meters();
    prevSpeed = gps.speed.mps();
    prevTime = millis();

    File dataFile = SD.open(fileName, FILE_WRITE);

    if (dataFile) {
      dataFile.println(lnBuffer);
      dataFile.close();

      // print to the serial port too:
      Serial.println(lnBuffer);
      digitalWrite(6, HIGH);  // green
      digitalWrite(8, LOW); //red
    }
    // if the file isn't open, pop up an error:
    else {
      Serial.print(F("error opening "));
      Serial.print(fileName);
      Serial.print("\n");

      digitalWrite(6, LOW);  // green
      digitalWrite(8, HIGH); //red

    }

    // clear buffer
    lnBuffer[0] = '\0';

  }
}
Map: Jackson Hill State Forest
Map: Pinckney State Forest
Map: Battery Diagram

New York Daily News

New York Daily News

"Sen. Chuck Schumer is also pushing to decriminalize marijuana after President Trump endorsed letting states decide how to regulate the drug."