I've been working on my EM-406A GPS module I have for my Decimilia. I went outside today to test its signal but I found that it was tracking my location correctly up to the millisecond.
For example, a few of my latitude readings would be something like this:
NORTH
3404.2256
3404.2260
3404.2263
3404.2265
3404.2266
3404.2268
3404.2270
...
3404.2311
3404.2311
3404.2310
3404.2311
3404.2308
3404.2305
...
3404.2244
3404.2244
3404.2245
2404.2245
Notice how the readings increase and decrease slightly at a rapid pace. The values tend to level out after I stay absolutely still for a few minutes. The same problems apply to the longitude. My question is why is this happening and how could I fix this so that I can get an accurate signal for use on a robotic rover?
I have included the code I used to test the GPS module. In the code I have a few items commented as questions about some small nuances in the code that I don't quite understand. (This code is kind of messy at the moment for testing purposes)
In the char2string() function, why must the interior while loop be organized like it is? I tried to simplify that loop but I ended up getting garbled characters. Does it have something to do with processing speed?
It didn't say in the module's data sheet, but apparently I have to transmit a constant HIGH to the module's RX in order to get a GPS reading back from it. Why is that? Do I have to do that "just cus I gotta"? Is there any interesting things I can send to the EM-406A specifically for it to do anything unique?
I also would like to better understand GPS bauds. I know they send data at 4800 baud, but I don't understand why I had to set the delays at 100 and 200 microseconds as seen in the beginning of the code.
//Created August 15 2006
//Heather Dewey-Hagborg
//http://www.arduino.cc
//reworked to GPS reader
/***********************************
Dirk, december 2006
/***********************************
Edited By: Peter Chang
UCLA Robotics
Last Modifed: April 25, 2008
Description:
Recieves data bit-by-bit from GPS unit EM-406A while sending
a constant HIGH signal to GPS unit's RX.
-Simplified and modified for EM-406A & Decimilia
*TEST FILE*
*/
//#include <ctype.h>
//#include <string.h>
#define bit4800Delay 200 //1 bit per 0.2 ms
#define halfBit4800Delay 100
byte rx = 6; //Connect to EM-406A's TX
byte tx = 7; //Connect to EM-406A's RX
//byte SWval;
//char dataformat[7] = "$GPRMC"; //RMC
char dataformat[7] = "$GPGGA"; //GGA
//char dataformat[7] = "$GPGSV"; //GSV
//char dataformat[7] = "$GPGSA"; //GSA
//char dataformat[7] = "$GPGLL"; //GLL
//char dataformat[7] = "$GPVTG"; //VTG
char messageline[80] = "";
int i= 0; //Im guessing, declaring here saves time?
char latitude[10];
char longitude[11];
void setup() {
pinMode(rx,INPUT);
pinMode(tx,OUTPUT);
digitalWrite(tx,HIGH); //NEEDS TO BE CONSTANT HIGH TO RECIEVE DATA
digitalWrite(13,HIGH); //turn on debugging LED
//SWprint('h'); //debugging hello
//SWprint('i');
//SWprint(10); //carriage return
Serial.begin(9600); // this is used to echo what is read from the GPS out the USB->SerialDebugMonitor
}
/*
void SWprint(int data)
{
byte mask;
//startbit
digitalWrite(tx,LOW);
delayMicroseconds(bit4800Delay);
for (mask = 0x01; mask>0; mask <<= 1) {
if (data & mask){ // choose bit
digitalWrite(tx,HIGH); // send 1
}
else{
digitalWrite(tx,LOW); // send 0
}
delayMicroseconds(bit4800Delay);
}
//stop bit
digitalWrite(tx, HIGH);
delayMicroseconds(bit4800Delay);
}
*/
char SWread()
{
byte val = 0;
//Wait for start bit (0)
while(digitalRead(rx) == HIGH);
if (digitalRead(rx) == LOW) //Must find seccond low bit?
{
delayMicroseconds(halfBit4800Delay);
//Read Character
for (int offset = 0; offset < 8; offset++)
{
delayMicroseconds(bit4800Delay);
val |= digitalRead(rx) << offset;
//Eg: 1, 0, 1, 1, 0, 0 = 001101 (Notice reverse ordering)
}
//wait for stop bit + extra
//Why 2 delays?
delayMicroseconds(bit4800Delay);
//delayMicroseconds(bit4800Delay);
if( val > 128 ) //Why do some values have such large ascii values?
return val-128;
else
return val;
}
}
void char2string()
{
i = 0;
messageline[0] = SWread();
if (messageline[0] == '
) //string starts with $
{
i++;
messageline[i] = SWread();
while(messageline[i] != 13 & i<80) //carriage return (13) or max size
{
i++;
messageline[i] = SWread();
}
//Why must I initialize and implement this while loop exactly like this to get readable data
messageline[i+1] = '\0'; //make end to string
}
}
void loop()
{
char2string();
if (strncmp(messageline, dataformat, 6) == 0 & i>4) //see top of code for "dataformat"
{
Serial.println(messageline);
/Lat/Lon RMA**
messageline[29] = '\0';
messageline[42] = '\0';
strcpy(latitude, messageline+20);
strcpy(longitude, messageline+32);
Serial.println("NORTH WEST");
Serial.print(latitude);
Serial.print(" ");
Serial.println(longitude);
******************************/
}
//
// way to print ALL RECEIVED MESSAGES!
//
//Serial.print(SWread(),BYTE); //use this to get all GPS output, comment out from char2string till here
}