GPS troubleshooting.. *Edit - Fixed! 'twas a coding problem.. (EM406-A serial)

Hi all,

Some backgorund:
New to arduino, although not new to electronics… New to c-style coding (wiring), not new to coding.

Anyway, I’m trying to get a 406A GPS chip to output the current latitude and longitude for a reverse geocache project I need to have done by next weekend… I have all the parts in place, but I’m really struggling to get an output…

Here’s my code thus far. Is anyone able to babysit me through the first little bit at all? I’d be greatly indebted to you… Obviously there’s some preamble before this (including the other half of void setup) like declarations and so on. Variable/pin names should all be logical…

 SerialIO.begin(4800);  //Start serial
  
  delay(3000);  // Wait 3 seconds, then begin
}
// END SETUP


// MAIN
void loop()
{
  lcd.clear();
 
  lcd.print("up..");
  while (SerialIO.available())  //is serial available?
  {
    lcd.print("looking");
    int c = SerialIO.read();
    if (gps.encode(c))          //have we received a valid stream?
    {
      lcd.print("stream..");
      delay(500);
                                                        //Display current pos and fix age on LCD
      float CurLat;
      float CurLon;
      unsigned long fix_age;
      gps.f_get_position(&CurLat, &CurLon, &fix_age);
      lcd.clear();
      lcd.print(fix_age);
      lcd.print("|");
      lcd.print(CurLat);
      lcd.print("|");
      lcd.print(CurLon);
      delay(5000);
    }
  }

  //  shutdown()

}
// END MAIN

Thanks again in advance to anyone who can help me out with my valentines day present :cold_sweat: :slight_smile:

As an aside… Is it really this difficult to get the location back from the GPS?

In my head, by now at least, it should just be a matter of:

init Serial
init GPS
is there a GPS fix?
what's my location?
how far away am i from the target location?
>2km do foo
<2km do bar

I thought there would be extremely simple function calls to do the three questions… ‘Do i have a fix? where am I? how far from target?’

So yeah, any assistance would be amazing, thanks guys.

You need to post all of your code. What is a SerialIO? What is a gps?

Add some Serial.print() statements. to show what serial data you have read. Are you reading any data?

sure thing paul:

#include <TinyGPS.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include <Servo.h>
// #include <math.h>				REMOVE IF UNNEEDED
#include <EEPROM.h>
// #include <avr/interrupt.h>			REMOVE IF UNNEEDED

/* CONSTANTS

Pin 2 and 3 are GPS
Pin 4 is for the LED ring on the pushbutton
Pin 5 is the lid servo
Pin 6-11 are the LCD screen
Pin 12 is for the pololu switch (bring high to kill)
Pin 13 is the Arduino board LED

LocMargin is the distance from the GPS target that you
are allowed to be and still open the box (in metres)

END CONSTANTS */


const int TXPIN = 2;
const int RXPIN = 3;
const int LEDRINGPIN = 4;
const int SRVPIN = 5;
const int LCDPIN1 = 6;
const int LCDPIN2 = 7;
const int LCDPIN3 = 8;
const int LCDPIN4 = 9;
const int LCDPIN5 = 10;
const int LCDPIN6 = 11;
const int POLOLU = 12;
const int BOARDLED = 13;

const int LocMargin = 2;

const int ADDR_ATTEMPTS = 0;

const float FARM_LAT = -34.18586;
const float FARM_LON = 149.85697;
float CurLat = 0;
float CurLon = 0;

TinyGPS gps;
Servo lidServo;
LiquidCrystal lcd(LCDPIN1, LCDPIN2, LCDPIN3, LCDPIN4, LCDPIN5, LCDPIN6);

// Initialise Serial and GPS
SoftwareSerial SerialIO(RXPIN, TXPIN);

  
  
// END OF DECLARATIONS


// SETUP
void setup()
{
  lidServo.attach(SRVPIN);  // set up and lock the servo
  lidServo.write(5);
  lcd.begin(16, 2);  // Initialise the display and show intro text

  // check code goes here to see if the box has ever been opened, alters text

  lcd.setCursor(0, 0);
  lcd.print("   A   Puzzle   ");
  lcd.setCursor(0, 1);
  lcd.print("   For  Laura   ");
  
  pinMode(POLOLU, OUTPUT);  //Initialise the pin that we'll use later to turn the system off
  
  SerialIO.begin(4800);  //Start serial
  
  delay(3000);  // Wait 3 seconds, then begin
}
// END SETUP


// MAIN
void loop()
{
  lcd.clear();
 
  lcd.print("up..");
  while (SerialIO.available())  //is serial available?
  {
    lcd.print("looking");
    int c = SerialIO.read();
    if (gps.encode(c))          //have we received a valid stream?
    {
      lcd.print("stream..");
      delay(500);
      //Calculate distance to the farm
      float CurLat;
      float CurLon;
      unsigned long fix_age;
      lcd.print("calc..");
      gps.f_get_position(&CurLat, &CurLon, &fix_age);
      lcd.clear();
      lcd.print(fix_age);
      lcd.print("|");
      lcd.print(CurLat);
      lcd.print("|");
      lcd.print(CurLon);
      delay(5000);
      /*
      if (gps.distance_between(FARM_LAT, FARM_LON, CurLat, CurLon) > 2) //yep, 2 metres, ie, always enter this 'if'
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(CurLat);
        lcd.setCursor(0, 1);
        lcd.print(CurLon);
        delay(30000);
        */
    }
  }
  
  
  
  
  //  shutdown()

}
// END MAIN




// FUNCTIONS =================================================================

void openLid()
{
lidServo.write(100);
delay(1000);
}

void lockLid()
{
lidServo.write(5);
delay(1000);
}

void initEEPROM()
{
  EEPROM.write(ADDR_ATTEMPTS, 50);
}

void shutdown()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("    Sleeping    ");
  delay(1000);
  lcd.setCursor(1,0);
  lcd.print("    .");
  delay(333);
  lcd.print(".");
  delay(333);
  lcd.print(".");
  delay(666);
  lcd.print("zzz");
  delay(666);
  digitalWrite(POLOLU, HIGH);
  delay(180000);
  openLid();
}

The data is via serial from the gps, and should go straight from there into the tinygps library from what i understand…

I’ve forgotten if i mentioned that I was building a reverse geocache… In any case, that’s what this project is. I’m basically trying to follow the frustromantic code here: http://newbrightidea.com/?p=63 although there’s a lot of extraneous code compared to my project.

thanks for replying paul, i know it can get tiresome answering the seemingly basic questions, but we’re all beginners once :stuck_out_tongue:

Cheers,
Dan

SoftwareSerial is obsolete. It does not properly implement the available() method. Try using NewSoftSerial, instead.

Add a Serial.begin(9600); statement to setup(), and Serial.print(c); after

     int c = SerialIO.read();

in loop(), to confirm that the GPS IS sending data.

Thanks Paul,

Already using NewSoftwareSerial, so that’s ticked that box - as of beta 11 it’s just named SoftwareSerial (see here: NewSoftSerial 11 (beta) | Arduiniana). Yeah, there’s going to be lots of confusion in the future… :stuck_out_tongue:

This GPS chip is specced for 4800 baud (http://www.sparkfun.com/datasheets/GPS/EM-406A_User_Manual.PDF - on page 3) so that’s why i’m using 4800, but yep, i’ll put in a serial.print() statement. How is the serial data printed to screen though? Do i have to open a terminal session to/from it, or will it show up in the IDE somewhere?

*edit - If i’d actually looked i would have found serial monitor under tools :stuck_out_tongue: such an idiot :stuck_out_tongue: giving that a shot now. To be honest, I had wondered how on earth anyone was supposed to debug… And now I realise that the Serial.begin() is for the IDE, not for the GPS… Figuring it out as I go…

Cheers,
Dan

It’s not even making it into the serialIO.available() while loop it seems… Going to play with that some more.

Sorry for the double post.


Update:
Ok, so the softwareserial connection seems to not become available. I tried reading out the value of c by putting these extra lines in at the start of void main:

.
.
  lcd.print("up..");
  int c = SerialIO.read();    <-- NEW LINE
  Serial.print(c);            <-- NEW LINE
  delay(2000);                <-- NEW LINE
  while (SerialIO.available())  //is serial available?
.
.

and all I see is ‘-1’ over and over. Would this be a problem with SoftwareSerial or have i messed up my code…?

thanks again. I should also clarify that i’m using a Mega 2560 board, so the use of SoftwareSerial 11 is a requirement, and also that the led on the GPS starts blinking after a short period of time to indicate that it has a successful lock, so i’m hoping it’s all just in the serial interface code now…

Tried a new project from scratch just to see what the GPS is doing and wrote this:

#include <icrmacros.h>
#include <SoftwareSerial.h>

SoftwareSerial nss(3, 2);

void setup()
{
  nss.begin(4800);
  Serial.begin(9600);
  Serial.print("Setup complete ");
  delay(5000);
}

void loop()
{
  while (nss.available());
  {
    int c = nss.read();
    Serial.print(c);
    delay(1000);
  }
}

from which I get -1 over and over, which I confirmed to be ‘empty buffer’ by modifiying the .cpp for softwareserial so the empty buffer error gave -2 instead, and yep, lots of -2’s. So it seems i’m not getting any output from the GPS, or if i am, i’m losing it somewhere… Any ideas on troubleshooting this one?

Please explain this statement:

I should also clarify that i'm using a Mega 2560 board, so the use of SoftwareSerial 11 is a requirement

SoftwareSerial 11 is NewSoftSerial in disguise. But, you have a Mega with 4 hardware serial ports. Why are you not using one of them for the GPS, and using SerialN to read it?

Didn't know you could. Will give it a shot now. Thanks Paul, slowly starting to get there. Either my GPS is faulty, board is faulty, NSS is buggy on the Mega or another serial port will work :P

that's where I am now. Thanks for sticking with me so far.

*edit - ok, new code:

void setup()
{
  Serial1.begin(4800);
  Serial.begin(9600);
  Serial.print("Setup complete ");
  delay(5000);
}

void loop()
{
  while (Serial1.available());
  {
    int c = Serial1.read();
    Serial.print(c);
  }
}

Still getting nothing, I've tried swapping the hook-up wire for TX and RX on the board too, just in case.. Suspecting my GPS is faulty at the moment.. Maybe i'll try a different rate?

Even if the rate is wrong, you should be getting something on the serial port. You do have the gps and Arduino sharing a ground, don't you?

The GPS is grounded on the arduino board (tried two of the ground connectors), so I assume that yes, they’re grounded together… Thought of that one already.

Yeah, i’m not seeing anything on the port. I get -1 repeatedly if i connect them the wrong way around (TX <–> RX). I’m thinking I received a dud GPS unit. I’m going to give sparkfun a call in a few minutes when they open for the day and hopefully they can express ship me one in time. Wish I had some other device to test the serial port with so I could know whether it’s the GPS or not.

*edit - spoke with sparkfun on the phone, i’m going to email them about the details… Meantime i’ve ordered a new GPS chip just in case - $60 is just an inconvenience. Hopefully they can refund it if the other one turns out to be faulty. Pleeeease let it turn up before the weekend!

Thanks for all your help paul, I would have been stuck for days without it - I really appreciate it. I’ll post back with how I’m going. Meantime, attached is the box I made for the project if you’re interested :slight_smile: it’s A-grade Brazilian flame rosewood and the pictures don’t even come close to doing it justice… Can’t wait to put the finish on it - i’m oil/waxing it - a mixture of tung oil, arumba wax and bees wax… Comes up incredibly :slight_smile: I’ll post more pictures and a build log when all this is done…

_MG_7101-web.jpg

_MG_7102-web.jpg

If nothing else, that is one incredibly gorgeous box.

Are you using a logic level converter? This GPS uses 2.8 volt logic (Arduino uses 5 volt logic) which won't work with a direct connection to the Arduino.

Here is a very easy way to test a GPS module to see if it’s spitting out sentences. Run this sketch and connect the Tx wire of the GPS to the Tx pin on your Arduino (yes Tx to Tx). Basically the sketch will take the data from your GPS module and send it straight to Serial Monitor. After downloading the sketch just open up Serial Monitor and choose the correct baud rate and you’ll the data stream.

void setup(){
  digitalWrite(0,LOW);
  pinMode(0,INPUT);
  digitalWrite(1,LOW);
  pinMode(1,INPUT);
}

void loop(){
  while(1);
}

Well, I emailed Mikal Hart (reverse geocache inventor) with my plea and he replied back last night with a simple fix - remove the ';' at the end of my while statement. Guess what, a nice flood of serial data.. Such a simple fix, I just wasn't familiar with the language :P

Thank you so much Paul for all your troubleshooting help, I wouldn't have managed to resolve all this without your troubleshooting..

And thanks too wayneft for chipping in. I can safely say too that yep, this chip definitely works with 5V, so all is good there..

I'll write the project up and post back within a week or two with the full build log :) might just squeeze it in with a fraction of time to spare now :)

Cheers, Dan