Ultimate Gps w/ other sensors

Breakout boards, sensors, other Adafruit kits, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
rovdude
 
Posts: 4
Joined: Fri Aug 09, 2013 11:51 pm

Ultimate Gps w/ other sensors

Post by rovdude »

So I'm making an underwater ROV which can sends data to my laptop. I'm using 6 simple switch-thingys to tell me when it runs into something. I do have camera feed, but that's separate. Im using the Ultimate GPS with a temperature sensor(arduino just reads the resistance), a Honeywell pressure sensor(arduino also just reads resistance) and the TSL light sensor. I want to collect data from each of these objects every second. Everything is working good until I add the GPS. The GPS alone works good, and the rest of the sensors alone work good, When I ask for both together, not all of the data comes in.

Code: Select all

#include <Wire.h>
#include <Adafruit_GPS.h>
#include <Adafruit_TSL2561.h>
#include <SoftwareSerial.h>
#include <Adafruit_Sensor.h>
#include <AFMotor.h>

Adafruit_GPS GPS(&Serial1);
Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345);
AF_DCMotor motor(2);

#define GPSECHO  false //RAW GPS SENTENCES

boolean usingInterrupt = false; //Keeps track of whether we are using the interrupt
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

float tempC, tempVal, tempF, tempVolt, depthVolt, depthPsi, depthFeet;
float GPSDepth = 0;
float testDepth = 100;
boolean contact1, contact2, contact3, contact4, contact5, contact6;
int tempSensor = 1;
int depthSensor = 6;
int contact_1 = 22;
int contact_2 = 23;
int contact_3 = 24;
int contact_4 = 25;
int contact_5 = 26;
int contact_6 = 27;
long waitUntilSensors = 5000; // Wait 5 seconds
long waitUntilMotor = 0;
long waitUntilGPS = 5000;
String lat = "";
String latDir = "";
String longit = "";
String longitDir = "";
const float PSI_TO_FEET= 2.30665873688;

void setup()
{
  Wire.begin();
  Serial.begin(115200);
  GPS.begin(9600);
  tsl.setGain(TSL2561_GAIN_16X); //Allows sensor to adapt to lowlight situation                                                     
  tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);
  motor.setSpeed(255);
  motor.run(RELEASE);

  //____________________________________________________________________________________GPS_______________________________________________________________________
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // Recommended minimum and GGA(fix datta) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); //Recommended minimum only
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate, can change to 5 or 10, for parsing need 1 Hz
  //GPS.sendCommand(PGCMD_ANTENNA); //Sends data on antenna status

  useInterrupt(true);

  delay(1000);
  // Ask for firmware version
  Serial1.println(PMTK_Q_RELEASE);
}

// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
  // writing direct to UDR0 is much much faster than Serial.print 
  // but only one character can be written at a time. 
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF; //GPS address
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } 
  else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

void loop()
{
  if (digitalRead(contact_1)== HIGH) 
  {
    contact1 = true;
  } 

  if (digitalRead(contact_2) == HIGH)
  {
    contact2 = true;
  } 
  if (digitalRead(contact_3) == HIGH)
  {
    contact3 = true;
  } 
  if (digitalRead(contact_4) == HIGH)
  {
    contact4 = true;
  } 
  if (digitalRead(contact_5) == HIGH)
  {
    contact5 = true;
  } 
  if (digitalRead(contact_6) == HIGH)
  {
    contact6 = true;
  } 

  if (! usingInterrupt) {
    // read data from the GPS in the 'main loop'
    char c = GPS.read();
    // if you want to debug, this is a good time to do it!
    if (GPSECHO)
      if (c) Serial.print(c);
  }

  if (millis() >= waitUntilSensors)    //Print analog sensors once every second
  {
    sensors_event_t event;
    tsl.getEvent(&event);

    tempVal= analogRead(tempSensor);
    tempVolt = tempVal * 5.0;
    tempVolt /= 1024;
    tempC = (tempVolt - .5) * 100;
    tempF = (tempC * 9.0/5.0) + 32.0;
    depthVolt = analogRead(depthSensor) * 5; //Takes 0-1023 reading and converts to volts by finding volts per unit
    depthVolt /= 1024;//FIXED WIERD MATH PROBLEMS!!
    depthPsi = (depthVolt/0.04)-12.5; // Depth Sensor Honeywell A Calibration: 10%-90% of supply voltage
    depthFeet = (depthPsi-14.7) * PSI_TO_FEET; //(PSI) * conversion factor
    Serial.print(contact1); 
    Serial.print(",");
    Serial.print(contact2);
    Serial.print(",");
    Serial.print(contact3);
    Serial.print(",");
    Serial.print(contact4);
    Serial.print(",");
    Serial.print(contact5);
    Serial.print(",");
    Serial.print(contact6);
    Serial.print(",");
    contact1 = false;
    contact2 = false;
    contact3 = false;
    contact4 = false;
    contact5 = false;
    contact6 = false;
    Serial.print(depthFeet); 
    Serial.print(",");
    Serial.print(depthPsi); 
    Serial.print(",");
    Serial.print(tempF); 
    Serial.print(",");
    if (event.light)
    {
      Serial.print(event.light); 
      Serial.print(",");
    }
    if (GPS.newNMEAreceived() && millis() > waitUntilGPS) {
      String sentence = GPS.lastNMEA();
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);                  
      Serial.print(","); 
      Serial.print(GPS.longitude, 4); Serial.print(GPS.lon);
      Serial.println(",");    
      //}
      
    }
    waitUntilSensors = millis()+ 1000;
  }

  /*if(GPSDepth < testDepth && millis() > timer)
  {
    motor.run(FORWARD);
    timer += 500;
    GPSDepth += 1.02;
  }
  else if(GPSDepth > testDepth && millis() > timer)
  {
    motor.run(BACKWARD);
    timer += 500;
    GPSDepth -= 1.02;
  }*/
}


I apologize if my code is messy. To help clear things up, the commented section at the bottom is to run a motor to keep the gps above the water, but that is not important in what I am running. I'm very lost on what can make the data come in together on the correct timing(once every second, all the data together). I am running this on an Arduino Mega2560 R3. I also have an Arduino Uno R3 where I tried running a master/slave setup with the gps on the uno, but that was even worse. Maybe there is something I can do with the uno and I was not doing it correctly. Maybe I can use an interrupt for the job(I don't know how these work). Any suggestions are very appreciated. If I left something out, I will be glad to give that information. Thanks in advance!

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Ultimate Gps w/ other sensors

Post by adafruit_support_rick »

I think your problem may be here:

Code: Select all

    if (GPS.newNMEAreceived() && millis() > waitUntilGPS) {
which is inside of this conditional:

Code: Select all

  if (millis() >= waitUntilSensors)    //Print analog sensors once every second
So, you're locking your test for a complete GPS sentence to your waitUntilSensors timer.
The GPS is coming in at 1Hz, and the sensor timer is also running at 1Hz, but they are not synchronized. When the timer expires, you might have half a sentence in the GPS input buffer. The next time the timer expires, that sentence will have completed, but the next sentence will have started and it will over-write the first sentence in the GPS input buffer.

waitUntilSensors will drift fairly rapidly relative to the GPS input rate, and every so often the timers will line up and you will get your sentence. But then the timers will drift apart, and you'll start missing sentences again.

Does that sound like what you're seeing?

Also, the waitUntilGPS timer does nothing - you initialize it but never update it (and you don't want a timer like that, anyway).

rovdude
 
Posts: 4
Joined: Fri Aug 09, 2013 11:51 pm

Re: Ultimate Gps w/ other sensors

Post by rovdude »

Thank you. That is what I am seeing. And this did help slightly, but I am still having the problem. Here's my new code:

Code: Select all

#include <Wire.h>
#include <Adafruit_GPS.h>
#include <Adafruit_TSL2561.h>
#include <SoftwareSerial.h>
#include <Adafruit_Sensor.h>
#include <AFMotor.h>

Adafruit_GPS GPS(&Serial1);
Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345);
AF_DCMotor motor(2);

#define GPSECHO  false //RAW GPS SENTENCES

boolean usingInterrupt = false; //Keeps track of whether we are using the interrupt
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

float tempC, tempVal, tempF, tempVolt, depthVolt, depthPsi, depthFeet;
float GPSDepth = 0;
float testDepth = 100;
boolean contact1, contact2, contact3, contact4, contact5, contact6;
int tempSensor = 1;
int depthSensor = 6;
int contact_1 = 22;
int contact_2 = 23;
int contact_3 = 24;
int contact_4 = 25;
int contact_5 = 26;
int contact_6 = 27;
long waitUntilSensors = 5000; // Wait 5 seconds
long waitUntilMotor = 0;
long waitUntilGPS = 5000;
String lat = "";
String latDir = "";
String longit = "";
String longitDir = "";
const float PSI_TO_FEET= 2.30665873688;

void setup()
{
  Wire.begin();
  Serial.begin(115200);
  GPS.begin(9600);
  tsl.setGain(TSL2561_GAIN_16X); //Allows sensor to adapt to lowlight situation                                                     
  tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);
  motor.setSpeed(255);
  motor.run(RELEASE);

  //____________________________________________________________________________________GPS_______________________________________________________________________
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // Recommended minimum and GGA(fix datta) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); //Recommended minimum only
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate, can change to 5 or 10, for parsing need 1 Hz
  //GPS.sendCommand(PGCMD_ANTENNA); //Sends data on antenna status

  useInterrupt(true);

  delay(1000);
  // Ask for firmware version
  Serial1.println(PMTK_Q_RELEASE);
}

// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
  // writing direct to UDR0 is much much faster than Serial.print 
  // but only one character can be written at a time. 
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF; //GPS address
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } 
  else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

void loop()
{
  if (digitalRead(contact_1)== HIGH) 
  {
    contact1 = true;
  } 

  if (digitalRead(contact_2) == HIGH)
  {
    contact2 = true;
  } 
  if (digitalRead(contact_3) == HIGH)
  {
    contact3 = true;
  } 
  if (digitalRead(contact_4) == HIGH)
  {
    contact4 = true;
  } 
  if (digitalRead(contact_5) == HIGH)
  {
    contact5 = true;
  } 
  if (digitalRead(contact_6) == HIGH)
  {
    contact6 = true;
  } 

  if (! usingInterrupt) {
    // read data from the GPS in the 'main loop'
    char c = GPS.read();
    // if you want to debug, this is a good time to do it!
    if (GPSECHO)
      if (c) Serial.print(c);
  }
if (GPS.newNMEAreceived()) {
      String sentence = GPS.lastNMEA();
      //Manual Parsing
      int sentIndex = sentence.indexOf("$GPRMC");
      lat = sentence.substring(sentIndex + 20, sentIndex + 29);
      latDir = sentence.substring(sentIndex + 30,sentIndex + 31);
      longit = sentence.substring(sentIndex + 32, sentIndex + 42);
      longitDir = sentence.substring(sentIndex + 43, sentIndex + 44);
      if(longitDir != "")//Make sure sentence was grabbed
      {
        Serial.print(lat);
        Serial.print(latDir);
        Serial.print(",");
        Serial.print(longit);
        Serial.print(longitDir);
        Serial.print(",");  
      }
      
    }
  if (millis() >= waitUntilSensors)    //Print analog sensors once every second
  {
    sensors_event_t event;
    tsl.getEvent(&event);

    tempVal= analogRead(tempSensor);
    tempVolt = tempVal * 5.0;
    tempVolt /= 1024;
    tempC = (tempVolt - .5) * 100;
    tempF = (tempC * 9.0/5.0) + 32.0;
    depthVolt = analogRead(depthSensor) * 5; //Takes 0-1023 reading and converts to volts by finding volts per unit
    depthVolt /= 1024;//FIXED WIERD MATH PROBLEMS!!
    depthPsi = (depthVolt/0.04)-12.5; // Depth Sensor Honeywell A Calibration: 10%-90% of supply voltage
    depthFeet = (depthPsi-14.7) * PSI_TO_FEET; //(PSI) * conversion factor
    Serial.print(contact1); 
    Serial.print(",");
    Serial.print(contact2);
    Serial.print(",");
    Serial.print(contact3);
    Serial.print(",");
    Serial.print(contact4);
    Serial.print(",");
    Serial.print(contact5);
    Serial.print(",");
    Serial.print(contact6);
    Serial.print(",");
    contact1 = false;
    contact2 = false;
    contact3 = false;
    contact4 = false;
    contact5 = false;
    contact6 = false;
    Serial.print(depthFeet); 
    Serial.print(",");
    Serial.print(depthPsi); 
    Serial.print(",");
    Serial.print(tempF); 
    Serial.print(",");
    if (event.light)
    {
      Serial.print(event.light); 
      Serial.print(",");
    }
    Serial.println();
    
    waitUntilSensors = millis()+ 1000;
  }

  /*if(GPSDepth < testDepth && millis() > timer)
  {
    motor.run(FORWARD);
    timer += 500;
    GPSDepth += 1.02;
  }
  else if(GPSDepth > testDepth && millis() > timer)
  {
    motor.run(BACKWARD);
    timer += 500;
    GPSDepth -= 1.02;
  }*/
}
For some reason the parsing function that comes with the GPS wasn't working, which I have had trouble with before so I manually parsed it.

I took a screen capture of the serial monitor. (Now that everyone knows where I live :lol:)... Left to right the numbers are: Latitude, Longitude, switch 1, switch 2, switch 3, switch 4, switch 5, switch 6, depth(it's reading a few inches above water, that's ok), PSI, temperature F, and Light lux. The error though is significantly less.
Attachments
data.jpg
data.jpg (285.24 KiB) Viewed 2297 times

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Ultimate Gps w/ other sensors

Post by adafruit_support_rick »

Right. Your problem is still that GPS.newNMEAreceived() is not synchronized with waitUntilSensors.

When this becomes true

Code: Select all

  if (millis() >= waitUntilSensors)    //Print analog sensors once every second
you proceed to do some integer and gloating point math, a couple of analog reads, and a whooole bunch 'o Serial.prints. That all takes time - I'll guess it's around 33ms. You don't set your next timeout value in waitUntilSensors until after you do all of that.

So, your update interval for the sensors is 1033ms, while the GPS updates every 1000ms. Every 30 seconds or so, the GPS update will occur immediately after the sensor update, which means that it will occur again immediately before the next sensor update. And that's why you see two GPS updates in a row in your output.

The thing to do is to reset waitUntilSensors as the first thing in the conditional.

Code: Select all

  if (millis() >= waitUntilSensors)    //Print analog sensors once every second
  {
    sensors_event_t event;
    waitUntilSensors = millis()+ 1000;

    tsl.getEvent(&event);
The better thing to do is to not use millis(). Just add 1000 the the value you already have. That way, it's guaranteed to expire every 1000 ticks, with no possibility of drift:

Code: Select all

  if (millis() >= waitUntilSensors)    //Print analog sensors once every second
  {
    sensors_event_t event;
    waitUntilSensors += 1000;

    tsl.getEvent(&event);
But neither of those will actually solve the problem. The Arduino's internal timer will inevitably drift relative to the GPS timer.
The right thing to do is to forget about waitUntilSensors entirely. It adds no value, because you already have a 1-second timer in (GPS.newNMEAreceived()). So, just read your sensors right after you do your GPS thing. That guarantees your GPS output and your sensor output will always be synchronized.

rovdude
 
Posts: 4
Joined: Fri Aug 09, 2013 11:51 pm

Re: Ultimate Gps w/ other sensors

Post by rovdude »

Wow using the GPS true clock should have been obvious to me. Thanks a lot its working great now! Hopefully I will be able to post pictures and maybe video of my ROV once its done. After over a year's work I have high hopes :D !

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Ultimate Gps w/ other sensors

Post by adafruit_support_rick »

rovdude wrote:Hopefully I will be able to post pictures and maybe video of my ROV once its done.
Please do! It sounds like a cool project. Can you tell us more about it? Is it for research, or for fun? Or for both?

rovdude
 
Posts: 4
Joined: Fri Aug 09, 2013 11:51 pm

Re: Ultimate Gps w/ other sensors

Post by rovdude »

It's an underwater ROV that will be able to reach a depth of 100 feet. This all started from a summer class I had to take a year ago where we built a basic Sea perch ROV kit (just a frame and motors) and we then took it to the Northrop Grumman Naval Testing facility. I noticed a few problems with the ROV and thought what else could I do with it. So what started as a minor overhaul of adding slightly faster motors turned into me building a brand new ROV, equipped with two sets of LED lights, a camera with a custom pan and tilt system, and the sensors I have already mentioned above. The frame is PVC pipe, and the thrusters are 12V 15,000 RPM motors with 2.8" carbon fiber propellers on them. There's four thrusters, two vertical and one on the left and right. I have also looked into making magnetic couplers with rare earth magnets so the motors stay out of the water, helping them run more efficiently(Currently I use WD40 to protect the motors from rust after they are in the water). It's a lot of custom machining, but I think it would be worth it. The GPS is something that hasn't even been done in the industry because signals from satellites can't reach underwater. So I have the GPS on a float attached to a reel that is on my ROV, and is controlled by a motor through the Arduino, with the hopeful result of it staying on the surface of the water, and the reel tight enough so the GPS doesn't drift from above the ROV. All my data coming in is then logged and overlaid onto the camera feed through a Processing program I wrote. So is it fun or research? I would say both :D . It's a lot of fun, and yet none of this is taught in school. I have learned so much, from electrical systems with the thrusters, how motors work, about materials, magnetic couplings, and tons of electronics, and some good practice coding. It's currently apart to get a paint job, but I will have a picture of most of it completed soon.

moquin
 
Posts: 5
Joined: Tue Aug 06, 2013 8:21 pm

Re: Ultimate Gps w/ other sensors

Post by moquin »

I am having the same problem with a navigation system I am setting up. Could you post the final code that is working? Thank you.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Ultimate Gps w/ other sensors

Post by adafruit_support_rick »

moquin wrote:I am having the same problem with a navigation system I am setting up. Could you post the final code that is working? Thank you.
His code is going to be specific to his application - it probably won't help you very much.

What exactly is the problem you are having? Can you post your code?

moquin
 
Posts: 5
Joined: Tue Aug 06, 2013 8:21 pm

Re: Ultimate Gps w/ other sensors

Post by moquin »

I am programming a Arduino Fio with a Xbee s2 module. There is a Adafruit Triple-axis Accelerometer+Magnetometer (Compass) Board LSM303DLHC and a Adafruit Ultimate GPS Breakout - 66 channel w/10 Hz updates - Version 3 connected. I can read both but I am getting NMEA messages garbled every once in a while. I did find another thread http://forums.adafruit.com/viewtopic.php?f=19&t=28438 that addresses this same problem.

It would just be nice when people finally get their problem fixed if they would post the final code so everyone else can benefit from it.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Ultimate Gps w/ other sensors

Post by adafruit_support_rick »

There were a few problems and solutions discussed in that other thread.

If you post your code, I'll have a look at it.

moquin
 
Posts: 5
Joined: Tue Aug 06, 2013 8:21 pm

Re: Ultimate Gps w/ other sensors

Post by moquin »

I got it working right now. The code isn't finished as the only thing I want it to do is send NMEA sentences to the controller via XBee and receive commands from the controller.

Here is the code as it is working:

Code: Select all

#include <Wire.h>
#include <LSM303.h>
#include <Adafruit_GPS.h>

// ******** Settings for the compass module **************
LSM303 compass;
// ******** End of settings for compass module **************

#if ARDUINO >= 100
  #include <SoftwareSerial.h>
#else
  // Older Arduino IDE requires NewSoftSerial, download from:
  // http://arduiniana.org/libraries/newsoftserial/
  #include <NewSoftSerial.h>
  // DO NOT install NewSoftSerial if using Arduino 1.0 or later!
#endif

#if ARDUINO >= 100
  SoftwareSerial mySerial(3, 2);
#else
  NewSoftSerial mySerial(3, 2);
#endif

Adafruit_GPS GPS(&mySerial);
// If using hardware serial (e.g. Arduino Mega), comment
// out the above six lines and enable this line instead:
//Adafruit_GPS GPS(&Serial1);


// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO  true

// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

void setup()  
{    
  Serial.begin(57600);
  Wire.begin();
  compass.init();
  compass.enableDefault();
  Wire.beginTransmission(0x3C >> 1);
  Wire.write(0x01);
  // see table 62 in the datasheet for other gain_setting values
  Wire.write(0x60); 
  Wire.endTransmission();
  
  // Calibration values. Use the Calibrate example program to get the values for
  // your compass.
  compass.m_min.x = -256; compass.m_min.y = -172; compass.m_min.z = -236;
  compass.m_max.x = +104; compass.m_max.y = +181; compass.m_max.z = +133;
  
  // connect at 57600 so we can read the GPS fast enuf and
  // also spit it out

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

  // 9600 NMEA is the default baud rate for MTK - some use 4800
  GPS.begin(9600);
  
  // You can adjust which sentences to have the module emit, below
  
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  // GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data for high update rates!
  // GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // uncomment this line to turn on RMC (recommended minimum) and GSV () including altitude
  // GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGSV);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGAGSV);
  // uncomment this line to turn on all the available data - for 9600 baud you'll want 1 Hz rate
  // GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_ALLDATA);
  
  // Set the update rate
  // 1 Hz update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
  // 5 Hz update rate- for 9600 baud you'll have to set the output to RMC or RMCGGA only (see above)
  // GPS.sendCommand(PMTK_SET_NMEA_UPDATE_5HZ);
  // 10 Hz update rate - for 9600 baud you'll have to set the output to RMC only (see above)
  // GPS.sendCommand(PMTK_SET_NMEA_UPDATE_10HZ);

/*
  // the nice thing about this code is you can have a timer0 interrupt go off
  // every 1 millisecond, and read data from the GPS for you. that makes the
  // loop code a heck of a lot easier!
  useInterrupt(true);
*/  
  delay(1000);

}

/*
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
  if (GPSECHO)
    if (c) UDR0 = c;  
    // writing direct to UDR0 is much much faster than Serial.print 
    // but only one character can be written at a time. 
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}
*/

char nmeastr[17]; // HCHDG,000.00,,,,*
int checksum;
char hs[6]; // 000.00


void loop()                     // run over and over again
{
  while (mySerial.available()) {                 //while data available from GPS
      Serial.print((char)mySerial.read());    //copy data to console
  }
  while (Serial.available()) {                    //while data available from console
      mySerial.print((char)Serial.read());   //copy data to GPS
  }

  compass.read();
  int heading = compass.heading((LSM303::vector){0,-1,0});
  strcpy(nmeastr,"HCHDG,");
  
  //dtostrf(FLOAT,WIDTH,PRECSISION,BUFFER);
  dtostrf(heading, 5, 2, hs); 
		
  strcat(nmeastr,hs);
  strcat(nmeastr,",,,,");

  //add a checksum
  checksum=0;
  for (int n=0; n < strlen(nmeastr); n++) {
    checksum ^= nmeastr[n];
  }


  Serial.print("$");
  Serial.print(nmeastr);
  Serial.print("*");
  Serial.println(checksum, HEX);
  //Serial.println(heading);
}
I do need to figure out how to have the heading printed only once when the GPS sentences are sent.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Ultimate Gps w/ other sensors

Post by adafruit_support_rick »

adafruit_support_rick wrote:I do need to figure out how to have the heading printed only once when the GPS sentences are sent.
You mean that you get one or more compass headings interleaved with the GPS data, right?

What you want to do is look at how it's done in the shield_sdlog sketch. That sketch accumulates GPS input until it detects a complete sentence. It parses the sentence, and then checks to see if it's an RMC sentence. If it is, then it flushes the logfile.

You want to do something similar. As each sentence is completed, you want to dump it to the log, and then check to see if it's the last sentence you expect in the current report (would that be the RMC?). If it is, then you do your compass heading, dump that to the file, and flush the file.

I trimmed the shield_sdlog loop function down a bit (and eliminated some of the error checking for clarity)

Code: Select all

void loop() 
{
  char c = GPS.read();
  if (GPSECHO)
    if (c)   Serial.print(c);


  if (GPS.newNMEAreceived()) //if a sentence is received, we can check the checksum and log it
  {
    char *stringptr = GPS.lastNMEA();  // GPS.lastNMEA() also sets the newNMEAreceived() flag to false
    if (GPS.parse(stringptr))   //see if the sentence is valid
    {
      logfile.write((uint8_t *)stringptr, strlen(stringptr));    //write the string to the SD file
      if (strstr(stringptr, "RMC"))    //The last sentence we expect in a report is RMC
      {
        <**** Do your compass heeading here ****>
        logfile.flush();
      }
    }
  }
}

User avatar
ikerarb
 
Posts: 3
Joined: Tue Mar 31, 2015 3:24 pm

Re: Ultimate Gps w/ other sensors

Post by ikerarb »

Hi moquin do you happen to have the code with xbee complete? I need it for a project I am working on to send weather balloons to my laptop with gps.

moquin
 
Posts: 5
Joined: Tue Aug 06, 2013 8:21 pm

Re: Ultimate Gps w/ other sensors

Post by moquin »

The code is really simple. XBee is treated like a serial port. I am using a Arduino FIO. I have attached the main program that the XBee setup and usage.
Attachments
NAV_v0_2.3.txt
(10.95 KiB) Downloaded 149 times

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Products from Adafruit”