GPS no satellites

  1. I am getting Latitude: 39,957431 and Longitude: -860180660.01

If you print the latitude with this:

    Serial.print( fix.latitude(), 6 );

... it will print the latitude as floating-point degrees. Positive values are north of the equator, and negative values are south of the equator.

The float type can only retain ~7 significant digits, so seeing "39.957431" on the Serial Monitor window is a little misleading. The last digit, a '1', is not useful, because it is an 8th digit.

Because of this limitation, NeoGPS stores lat/lon values as a scaled 32-bit integer, degrees * 10000000. For example, it stores 39.957431 as 399574310, internally. When you call the latitude() function, NeoGPS takes the integer, converts it to a float (dropping 2 significant digits), and divides by 10000000.0.

The code you posted will not print "-860180660.01". It might print "-86.018066".

If your code were this:

    Serial.print( (float) fix.latitudeL() );

... it would print "-860180660.01". Don't do that.

If you want the full 10 significant digits that NeoGPS can provide, you must print the scaled 32-bit integer as if it were a float. Basically, you need to print a '.' character at the right place. See NMEAloc.ino for a utility routine to do just that: printL. There are other methods for printing lat/lon as degrees/minutes/seconds (DMS), or degrees/minutes/fractional minutes.

Cheers, /dev

P.S. Be sure to use code tags around any code in your posts. Put a [code] tag before the code, and put a [/code] tag after the code,

  so it looks

  like this.

hr2guy: 2. Is there a source of commands for the GPS so I can change units, i.e. Meters to Feet, etc?

These are not GPS commands, they are conversion factors. Simply google "meters to feet", and it shows "1 meters = 3.28084 feet". That's the conversion factor:

    Serial.print( fix.altitude() * 3.28084 );

The number you see will be the altitude in feet.

  1. I am trying to use this GPS for location while I record "g" loads and occasionally add location. Is there a simple way to ask for elapsed time so that every 10 seconds I could have it stop recording and start over?

Please read the General Design section of the Useful Links. It shows how to use millis() to measure elapsed time.

Basically, you take a timestamp at some point of the sketch. Then you compare that timestamp with millis() to see if the difference is big enough (i.e., it has been long enough):

    if (millis() - myTimestamp >= INTERVAL)

For example:

uint32_t myTimestamp;

void loop()
{
  if (millis() - myTimestamp >= 10000) { // ms = 10s
     ... do something special, like stop the recording and re-start...

    myTimeStamp += 10000; // step to the next time
  }
}

You can also use the GPS fixes as a 1-second "clock":

uint8_t fixCount; // can measure up to 255 second intervals

void loop()
{
  if (gps.available( gpsPort )) {
    fix = gps.read();

    fixCount++;

    ... print a few things, or whatever ...
  }

  if (fixCount - myTimestamp >= 10) { // seconds
     ... do something special, like stop the recording and re-start...

    myTimeStamp = fixCount; // record when we did this
  }
}

I would recommend the latter approach when the intervals are long (seconds) and you want to stay "in sync" with the GPS clock (recording locations).

If the intervals are short (or you need fractions of a second) or the timed process is not in synch with the GPS clock, use the former millis() technique. Very common approach.

Cheers, /dev

Hi dev,

Extensive delay -- I guess I must have shorted out the 5v supply out of the Uno. I finally checked the Vout and it doesn't show anything so I ordered another Uno. I will now be very careful to wire 5v as a last hookup. Any idea of how to re-fuse it or make it output 5v again or do I just trash it. The 3.3 v doesn't read anything either. Then I can continue with your great suggestions. Thank you. JBB

Any idea of how to re-fuse it or make it output 5v again or do I just trash it.

It is possible to replace the 5V and 3.3V regulator on the UNO board, but this is not a beginner's project. Since you called it the "5V supply out of the UNO", I have to assume that you are a beginner.

I will now be very careful to wire 5v as a last hookup.

You should show us a schematic of what you are hooking up. Maybe there's a wiring error that damaged your UNO. Please don't use Fritzing. :P

You could use an image editing program, like Paint, GIMP or IrfanView to draw boxes and lines. Save the drawing as a PNG or JPG file, and attach it to your post.

Or you could use a free schematic editors: Schemeit, CircuitLab (used by electronics.stackexchange) and CircuitBee. See additional notes below. Some of them let you export the schematic as a JPG/PNG file. If they don't,

(1) capture a screenshot of the schematic (ctrl-alt-Print Screen), (2) paste it into an image editing program, (3) save it as a JPG/PNG file, and (4) attach it to your post.

Or, go old school and draw it on a napkin and take a pic. :) Use your image editor to reduce the resolution to about 800x1000 and attach it to your post.

An important question: What GPS device are you using? Some are 3.3V only, and you should not connect the Arduino to the GPS RX pin with just a wire.

Cheers, /dev


NOTES on schematic editors:

* Scheme-it is ok, but most of it's overkill. Select the "Custom Symbols" on the left. In "Symbol Primitives", choose "Box" and drop a few on the grid. Select one of the boxes, and you can change the labels in the right pane.

Then grab a few "Pin Right" or "Pin Left" and drop them on the boxes. Click on the pins to change their name. To connect the pins with a wire, press the Left mouse button on one pin and move to another pin, and release it.

Resistors are under "Schematic Symbols -> Passives -> Resistors -> General".

* I like CircuitLab, but it costs money now. :( You can create an account at stackexchange, and start to ask a question on the electronics site. There's an icon in the post editor that allows you to enter a schematic, using a subset of the CircuitLab capabilities. Take a screenshot when you're done and DON'T POST THE QUESTION YOU STARTED.

* CircuitBee is pretty easy, too. Create an account and give it a whirl.

Thank you for that info.

I'm using the Adafruit Ultimate GPS Breakout v3. I am powering the breadboard power bus with the 5v pin from the Uno. That's why I called it the "5v supply out of the Uno."

I'm using and wiring just from schematics on the Uno sites like Adafruit or from YouTube so I'm not inventing circuits of my own.

And yes, thanks to the help here I might be able to be relabeled someday. Right now I'm "Beginner." he he.

This is a great learning experience and thank you for your help.

JBB

A quick question: I'm a little confused as to what commands in a required library file are doing during my programming of a sketch. For a typical .h or .cpp library file, is there a way to take a look inside to see what it is doing? What if the library file recommended for a typical breakout like the MMA8451 3D acceleration board was doing something you would like to change? Can I do that? Thank you. JBB

I’m a little confused as to what commands in a required library file are doing during my programming of a sketch. For a typical .h or .cpp library file, is there a way to take a look inside to see what it is doing? What if the library file recommended for a typical breakout like the MMA8451 3D acceleration board was doing something you would like to change? Can I do that?

Of course. You are free to read and change any library in the Arduino/Libraries subdirectories. However…

I would not change any of a library’s code until you understand how it works, completely. Some libraries expect you to change configuration items (usually constants or #define statements). Work through as many examples as you can so you have a good understanding of how the device works and how the library deals with the device. Read the spec sheet for the device.

If you think there is a problem with the library, you should probably post a question here to see if others have encountered the same problem. They may have a fix or different library for you to try.

If you do edit a library, you can always delete it and re-download it to start from scratch.

  1. Thank you for that answer. I guess my more basic question is not so much that I want to modify a library but rather wanting to study it and figure out what it is doing.

  2. I'm not sure how to look into the .h or .cpp file. Which software do I use? All I get is a jumbled mess and am obviously not using the right program to look.

Thank you.

  1. I’m not sure how to look into the .h or .cpp file. Which software do I use? All I get is a jumbled mess and am obviously not using the right program to look.

Notepad is not the program you seek. Here’s a list of editors.

I hear lots of good things about emacs, Notepad++, vi/vim, Eclipse, Sublime (more advanced). Visual Studio is huge… I would not recommend it for you at this point.

You can also browse the source code from the library website (search on github for the library name).

Hi dev,

I have 2 simple questions (for you):

  1. I don't understand what the "F" on these Serial.print statements means. Is there a place I can read about this?

Serial.print(F("/"));

Serial.print(gps.date.day());

Serial.print(F("/"));

  1. Also, what does these statements mean? I'm now trying to make millisecond and GPS time work and see these sometimes.

uint32_t myTimestamp;

uint8_t fixCount;

Thank you

F is a macro to make strings in flash memory (to save RAM) uint32_t is "unsigned int 32 bit type", etc - these are portable ways in C/C++ so say exactly what size of storage to use for integer variables. "int", "long int", "short int" are not necessary the same size on different machines

hr2guy:

  1. I don’t understand what the “F” on these Serial.print statements means. Is there a place I can read about this?

There is a good explanation here. The basic idea is that it prevents your sketch from using RAM for that constant value. RAM is precious; FLASH is (usually) plentiful.

BTW, for 1-character strings, it is a little more efficient to use the single-quoted character constant:

  Serial.print( F("abc") );  <-- Optimal for multiple characters: only uses 4 bytes of FLASH
  Serial.print( '/' );       <-- Optimal for single characters
  Serial.print( 'abc' );     <-- NEVER with single quotes.  Compiles ok, but incorrect usage!
  Serial.print( "abc" );     <-- allowed, but also uses 4 bytes of RAM
  1. Also, what do these statements mean? I’m now trying to make millisecond and GPS time work and see these sometimes.
    uint32_t myTimestamp;

uint8_t fixCount;

These are more specific alternatives to unsigned long and unsigned short. The language is a little vague about what values can be represented by those types. On the Arduino, int is defined to be 2 bytes (16 bits), long is 4 bytes (32 bits), and short is 1 byte (8 bits). The number of bits determines the range of values:

16 bits can hold values from -32768 to 32767 (signed) or 0 to 65535 (unsigned)
8 bits can values from -128 to 127 (signed) or 0 to 255 (unsigned)
32 bits can hold values from -2147483648 to 2147483647 (signed) or 0 to 4294967295 (unsigned)
1 bit can hold 2 values, 0 or 1. In the case of the bool type, the values are false or true. (NB: bool variables are usually stored in 1 byte, but there are ways to pack multiple bools into one byte.)

There is a standard header file, stdint.h, that contains these specifically-sized types.

In that code, the storage size of each variable is obvious to the reader. This immediately identifies the valid range of values. For intervals, this determines the maximum interval that can be measured. For the count, this determines when the counter rolls over to zero.

Hey -dev

Awesome answer. Thank you.

Hey Guys,

I am collecting accel data at 1Khz for up to 5 seconds, which obviously would be up to about 5,000 values. They can be 3 or 4 digit int. How do I store these so I can go back and do operations to them after the collection is done? - i.e. the high value, the low value, etc?

I could also collect fewer samples if memory is a problem because that's not the real question I have. I just want to gather the data and store it so I could then go back and look at it and do math things to it. Thank you.

You have to write the samples to an external storage device as you read them. Most people use an SD card... they're cheap, pretty fast, but you may need some RAM buffers for when the SD card takes a little longer to complete a write (up to 100ms, which is 100 samples). You also need to perform level-shifting to convert the UNO's 5V to/from the SD card 3.3V. Some SD card modules can do the shifting, but be sure to get a module that uses transistors (FETs), not just resistors.

You won't be able to do 1KHz with an UNO. If each sample is 24 bytes (binary), 100 samples would take 2400 bytes of RAM. It might work with a Mega, which has 8K RAM. For a 1KHz sample rate, you should probably consider a faster processor (e.g., a Teensy). It also has more RAM.

Another project here has successfully logged accelerometer data, 2 wheel speed sensors and GPS at 100Hz. That required careful programming. I don't think you're to that level yet, so 1KHz is probably beyond your current capabilities.

I would suggest a new post for this new project.

Thank you for that explanation and you're absolutely correct on the speed thing. Turns out 10Hz will probably do it. I will start a new section for the questions I will have as you are correct again, I am at the very beginning level. Thank you and I will use this for the GPS questions.

Hi Guys,

I know there is a way to post sketch code properly but this didn’t seem to work. The sketch didn’t work either. I was trying to use setup() to get one GPS fix and then use loop() to do other things. Can you give me an idea of why the GPS didn’t report the data? Thank you.

#include <SoftwareSerial.h>
#include “TinyGPS++.h”

TinyGPSPlus gps; //This is the GPS object

SoftwareSerial serial_connection(8,9); //RX=pin 8, TX=pin 9

void setup()
{
Serial.begin(9600); //This opens up comm to the Serial monitor in the Arduino IDE
serial_connection.begin(9600); //This opens up communications to the GPS
Serial.println(“GPS Start”); //Shows the monitor that the sketch has started

Serial.print("Start time = "); Serial.println(millis());

while(serial_connection.available()) //While there are characters to come from the GPS
{
gps.encode(serial_connection.read()); //This gets the serial NMEA data
}
delay(5000);

Serial.println();
Serial.print("Sats: ");
Serial.println(gps.satellites.value());
Serial.print(“Lat: “);
Serial.println(gps.location.lat(), 6);
Serial.print(“Lon: “);
Serial.println(gps.location.lng(), 6);
Serial.print(“Alt(ft): “);
Serial.println(gps.altitude.feet());
Serial.print(“Time: “);
Serial.print(gps.time.hour());Serial.print(”:”);
Serial.print(gps.time.minute());Serial.print(”:”);
Serial.print(gps.time.second());
Serial.println();
Serial.print(gps.date.month());Serial.print(”/”);
Serial.print(gps.date.day());Serial.print(”/”);
Serial.print(gps.date.year()-2000);
Serial.println();
Serial.println(millis());
}
void loop() {}

Guys, I think I found how to post code. Is this right? Thank you.

#include <SoftwareSerial.h>
#include "TinyGPS++.h"

TinyGPSPlus gps;                           //This is the GPS object
                                           
SoftwareSerial serial_connection(8,9);     //RX=pin 8, TX=pin 9

void setup() 
{
  Serial.begin(9600);                     //This opens up comm to the Serial monitor in the Arduino IDE
  serial_connection.begin(9600);          //This opens up communications to the GPS
  Serial.println("GPS Start");            //Shows the monitor that the sketch has started
  
    Serial.print("Start time = "); Serial.println(millis());
  
 while(serial_connection.available())                 //While there are characters to come from the GPS  
  { 
    gps.encode(serial_connection.read());             //This gets the serial NMEA data 
  }  
    delay(5000);
  
    Serial.println();
    Serial.print("Sats: ");
    Serial.println(gps.satellites.value());
    Serial.print("Lat: ");
    Serial.println(gps.location.lat(), 6);
    Serial.print("Lon: ");
    Serial.println(gps.location.lng(), 6);
    Serial.print("Alt(ft): ");
    Serial.println(gps.altitude.feet());
    Serial.print("Time: ");
    Serial.print(gps.time.hour());Serial.print(":");
    Serial.print(gps.time.minute());Serial.print(":");
    Serial.print(gps.time.second());
    Serial.println();
    Serial.print(gps.date.month());Serial.print("/"); 
    Serial.print(gps.date.day());Serial.print("/"); 
    Serial.print(gps.date.year()-2000);
    Serial.println();
    Serial.println(millis());
}
void loop() {}

You have made a very common mistake. You're assuming that data will come from the GPS in a continuous stream that your while loop will consume. The arduino is very very fast compared to serial comnmunication, particularly at a slow speed like 9600 baud.

Your while loop will consume a character or two (perhaps none at all) and then go looking for another, which will not have arrived yet. At that point the loop will end and the gps class will not have processed enough data to generate a fix.

There are several ways to solve this. The obvious but dangerous one is to put a delay inside the loop. Better, you could loop until you see a LF character. Better still, loop until the gps object tells you it is done when you call encode. Even there, you probably need to time out after ten seconds or so without a fix, as will probably happen indoors.

wildbill:
Better still, loop until the gps object tells you it is done

+1

hr2guy:
Is this right?

No.

I don’t know why you’re using SoftwareSerial. You should read Reply #3 above, or read this.

And I don’t know why you switched back TinyGPS, after all the discussion about NeoGPS. Here’s a NeoGPS version that waits in setup until a valid location is received:

#include <NMEAGPS.h>
#include <AltSoftSerial.h>
AltSoftSerial gpsPort; // GPS TX to pin 8 (on an UNO).
    //  Do not connect GPS RX, because you may need level shifting (just like for the SD card)

NMEAGPS gps;
gps_fix fix;

void setup()
{
  Serial.begin(9600);
  gpsPort.begin(9600);
  
  Serial.println( F("GPS Start") );  // F macro saves RAM

  Serial.print( F("Start time = ") );
  Serial.println( millis() );

  // Wait for a valid location
  for (;;) {
    if (gps.available( gpsPort )) {
      fix = gps.read();
      if (fix.valid.location) {
        printFix();
        break; // got one!
      }
      Serial.print( '.' );
    }
  }

  Serial.println( F("setup completed") );
}

void loop()
{
  //  Print new fixes when they arrive
//  if (gps.available( gpsPort )) {
//    fix = gps.read();
//    printFix();
//  }
}

void printFix()
{
  Serial.print( F("millis(): ") );
  Serial.print( millis() );

  Serial.print( F("\nSats:") );
  if (fix.valid.satellites)
    Serial.print( fix.satellites );

  Serial.print( F("\nLat:") );
  if (fix.valid.location)
    Serial.print( fix.latitude(), 6 );

  Serial.print( F("\nLon:") );
  if (fix.valid.location)
    Serial.print( fix.longitude(), 6 );

  Serial.print( F("\nAlt(m):") );
  if (fix.valid.altitude)
    Serial.print( fix.altitude());

  Serial.print( F("\nDate:") );
  if (fix.valid.date) {
    Serial.print(fix.dateTime.month);
    Serial.print( '/' );
    Serial.print(fix.dateTime.date);
    Serial.print( '/' );
    Serial.print(fix.dateTime.full_year());
  }

  Serial.print( F("\nTime:") );
  if (fix.valid.time) {
    if (fix.dateTime.hours < 10) Serial.print( '0' );
    Serial.print(fix.dateTime.hours);
    Serial.print( ':' );
    if (fix.dateTime.minutes < 10) Serial.print( '0' );
    Serial.print(fix.dateTime.minutes);
    Serial.print( ':' );
    if (fix.dateTime.seconds < 10) Serial.print( '0' );
    Serial.print(fix.dateTime.seconds);
    Serial.print( '.' );
    if (fix.dateTime_cs < 10) Serial.print( '0' );
    Serial.print(fix.dateTime_cs);
  }
  Serial.println();

} // printFix