Disable Static Navigation:Solved

Hi, I am taking data from GPS using Arduino Uno. GPS's model is PMB-688 and i am using an external antenna. When i started to walk, i cannot take different data between each 30-40 meters. After 40 meters i can take data well. What do you think about whether it is an unexpected situation? In the datasheet of this product it is written that accuracy is about 5 meters. (http://www.parallax.com/sites/default/files/downloads/28501-PMB-688-v0.1.pdf)

I asked this to firm of GPS and they said that you are using "Static Navigation" and you have to change it to "Constant Navigation", it can be a reason for accuracy problem.

These are explained in here: Spin Tutorials and Projects | LEARN.PARALLAX.COM What do you think about whether it can be a solution to overcome my problem. In that website it is not explained for Arduino. I don't use Propeller Board of Education. Do you have any idea about how i can change it to Constant Navigation? Is there any disadvantage when i change it? I am trying calculating distance between points which i walked and this is my code. Thank you so much.

#include <SoftwareSerial.h>
#include <math.h>
#define NMEA_SIZE 256
#define SIZE 120
#define SIZEA 120

SoftwareSerial GPS = SoftwareSerial(6, 1);

byte NMEA[NMEA_SIZE];
double lat_values[SIZE];
double lon_values[SIZEA];


double dis,lo_dif,la_dif,lat_1_radian1,lat_1_radian2,lon_1_radian1,lon_1_radian2,lat2_dif,lon2_dif,displacement,sum,distance,b,lon1_dif,lon_1_radian,lon1_m,lon1_d,lat1_dif,lat1_memory,lat1_mdeneme,lat_1_radiandeneme,lat_1_radian,lat1_m,lat1_d,lat1_degree,lat1_degree_1, lat1_degree_2,d,d2;
int lon1_m1,lon1_m2,lon1_m3,lon1_m4,lon1_m5,lon1_m6,lon1_d1,lon1_d2,s,m,n,e,z,f,g,h,lat1_d1,lat1_d2,lat1_m1,lat1_m2,lat1_m3,lat1_m4,lat1_m5,lat1_m6;


void getData() {

  byte character;
  int index = 0;

  do {
    if (GPS.available()) {
      character = GPS.read();
      NMEA[index] = character;
      index++;
    }
  }
  while(index < NMEA_SIZE && character != '

);

NMEA[index - 2] = '\0';
}

void setup() {

GPS.begin(4800);
 Serial.begin(9600);
 n=0;
 m=0;
 sum=0;

for(s =0 ; s<100000 ; s++){

getData();

if(NMEA[17] == 'V')
   {
     Serial.print("NO DATA\n");
   }

i = 0; NMEA[i] != '\0'; i++) { Serial.write(NMEA[i]);  }

else if(NMEA[2] == 'R' && NMEA[3] == 'M' && NMEA[4] == 'C') {
     int i = 0;
 
     Serial.print("\n");

Serial.print("Latitude: ");
     for(i = 19; i<21; i++) {
       Serial.write(NMEA[i]);
     }
     Serial.print(".");
     for(i = 21; i<23; i++) {
       Serial.write(NMEA[i]);
     }
     for(i = 24; i<28; i++) {
       Serial.write(NMEA[i]);
     }
     Serial.print(" N");
     Serial.print("\n");

Serial.print("Longitude: ");
     for(i = 32; i<34; i++) {
       Serial.write(NMEA[i]);
     }
     Serial.print(".");
     for(i = 34; i<36; i++) {
       Serial.write(NMEA[i]);
     }
     for(i = 37; i<41; i++) {
       Serial.write(NMEA[i]);
     }
     Serial.print(" E");

lat1_d1=NMEA[19]- '0';
     lat1_d2=NMEA[20]- '0';

lat1_m1=NMEA[21]- '0';
     lat1_m2=NMEA[22]- '0';
     lat1_m3=NMEA[24]- '0';
     lat1_m4=NMEA[25]- '0';
     lat1_m5=NMEA[26]- '0';
     lat1_m6=NMEA[27]- '0';

lon1_d1=NMEA[32]- '0';
     lon1_d2=NMEA[33]- '0';

lon1_m1=NMEA[34]- '0';
     lon1_m2=NMEA[35]- '0';
     lon1_m3=NMEA[37]- '0';
     lon1_m4=NMEA[38]- '0';
     lon1_m5=NMEA[39]- '0';
     lon1_m6=NMEA[40]- '0';

lat1_d= (double)lat1_d110+lat1_d2;
     lat1_m= (double)lat1_m1
10+lat1_m2+lat1_m30.1+lat1_m40.01+lat1_m50.001+lat1_m60.0001;

lat_1_radian=(double)(((22lat1_d)/(180))/7)+((((((22lat1_m)/180)/60)/7)));

lon1_d= (double)lon1_d110+lon1_d2;
     lon1_m= (double)lon1_m1
10+lon1_m2+lon1_m30.1+lon1_m40.01+lon1_m50.001+lon1_m60.0001;

lon_1_radian=(double)(((22lon1_d)/(180))/7)+((((((22lon1_m)/180)/60)/7)));

if(m<120){
       lat_values[m]=lat_1_radian;
       if(m>0){
         lat1_dif=lat_values[m]-lat_values[m-1];
         lat2_dif=lat_values[m]-lat_values[1];
       }

}

if(n<120){
       lon_values[n]=lon_1_radian;
       if(n>0){
         lon1_dif=lon_values[n]-lon_values[n-1];
         lon2_dif=lon_values[n]-lon_values[1];
       }

}

distance=(double)(2*(6364.49)(1000))(asin((sqrt(((sin((lat1_dif)/2)))(sin((lat1_dif)/2))+(cos(lat_values[m-1])cos(lat_values[m])(((sin((lon1_dif)/2)))(sin((lon1_dif)/2))))))));

sum=sum+distance;
     displacement=(double)(2*(6364.49)(1000))(asin((sqrt(((sin((lat2_dif)/2)))(sin((lat2_dif)/2))+(cos(lat_values[1])cos(lat_values[m])(((sin((lon2_dif)/2)))(sin((lon2_dif)/2))))))));

n++;
     m++;

Serial.print("\n");

Serial.print("Toplam Yol: ");
     Serial.println(sum,4);
     Serial.print("Yerdegistirme: ");
     Serial.println(displacement,4);

delay(3000);

}

}

}

void loop() {
}

The code you are using to extract coordinates from the GPS unit is so inaccurate that you have no hope of using it for navigation while walking, or any other activity.

One, your conversion from GPS text to latitude and longitude is very inaccurate and won't work properly at some locations. Two, your conversion from degrees to radians is simply wrong. Three, Arduino does not support double precision (64 bit) floating point numbers and 32 bit floats are not accurate enough to use for local navigation.

I recommend that you use the library functions to convert GPS text messages to coordinates and work with those.

I think you understand nothing about this topic. There is not any relationship between your comments and fact.Please don't write if you don't know. Im taking data very accurately for static navigation. My distance calculation is also very close to Google Maps. So, how can you writing that kind of things without any information! Try code and see whether it is accurate or not. You don't even know that radian calculation. The problem is just beginning of the data from GPS, there is not any relationship between calculations and GPS data accuracy.

Also you don't know anything about GPS. The mode is on "Static Navigation". Read and learn something before writing something which has no mean.

http://learn.parallax.com/project/constant-navigation-gps

Thanks for the link. I took a look at the Parallax web site and had a laugh at their comment:

Fortunately for us, the GPS Modules also have a mode called “Constant Navigation”. This mode has the GPS-output updated Lat/Lon data every second, which is the refresh rate of the modules themselves. This means that you can power on the module at your desk, and watch the data change ever so slightly, without ever taking a step. Now, even the smallest robot moving at 0.5 mph can have on-board GPS navigation!

(bold typeface added).

You are correct, I did not know that recently some GPS modules have been altered so that they do not continuously update your location coordinates unless you are moving at a predetermined speed. While this seems expedient for navigation in automobiles, it is a poor choice for any other purpose. The Parallax module is obviously one to be avoided. I have had excellent results with the UBlox modules, for example GPS Receiver - GS407 Helical (50 Channel) - GPS-11466 - SparkFun Electronics But as everyone who has tried knows, none of the inexpensive GPS modules are accurate enough to use for navigation on a small robot, as the Parallax people seem to suggest.

FYI the Propeller Spin code to turn on and off the default "Static Navigation" mode for the Parallax module is very clear, and simply involves sending some characters to the GPS unit, to wit send the following character strings:

'SiRF Disable Static Navigation, Message ID 143

DisStatNav    byte      $A0,$A2,$00,$02,$8F,$00,$00,$8F,$B0,$B3

'Switch back To NMEA Protocol Message ID 129 at 4800 bauds, leave on GGA and RMC strings updating oce per second.

BackToNMEA    byte      $A0,$A2,$00,$18,$81,$02,$01,$01,$00,$01
              byte      $00,$01,$00,$01,$01,$01,$00,$01,$00,$01
              byte      $00,$01,$00,$01,$00,$01,$12,$C0,$01,$61
              byte      $B0, $B3

Do fix the degrees to radians code, and good luck with your project!

Thank you but i can not change module. I do not use Propeller Board, i am trying to change the mode but there is not any clear document for Arduino Uno.

Do you have any idea about changing the mode on Arduino Uno?

To change the mode, use serial.write to send the GPS unit the character strings in the code segment I quoted above. This process should be adequately documented in the manufacturer's data sheet for the GPS module. But if not, you can follow the Propeller code.

For completeness, here is the Propeller SPIN code to do so. It can be translated nearly line for line into C or C++ for the Arduino. The first Serial.str function call puts the GPS unit into SiRF binary protocol. The next statements each send a certain number of characters, given in the data statements at the bottom, with an appropriate wait (delay) statement.

   waitcnt(cnt + clkfreq)
  Serial.str(string("$PSRF100,0,4800,8,1,0*0F", CR, LF))   'Switch to SiRF binary protocol at 4800,8,N,1

  'Disable Static Navigation
  
  waitcnt(clkfreq + cnt)
  repeat i from 0 to 9
    Serial.tx(DisStatNav[i])

  'Switch back To NMEA Protocol Message ID 129, leave only GGA and RMC strings and keep speed at 4800
  
  waitcnt(clkfreq / 2 + cnt)
  repeat i from 0 to 31
    Serial.tx(BackToNMEA[i]) 


DAT

'SiRF Disable Static Navigation, Message ID 143

DisStatNav    byte      $A0,$A2,$00,$02,$8F,$00,$00,$8F,$B0,$B3

'Switch back To NMEA Protocol Message ID 129 at 4800 bauds, leave on GGA and RMC strings updating oce per second.

BackToNMEA    byte      $A0,$A2,$00,$18,$81,$02,$01,$01,$00,$01
              byte      $00,$01,$00,$01,$01,$01,$00,$01,$00,$01
              byte      $00,$01,$00,$01,$00,$01,$12,$C0,$01,$61
              byte      $B0, $B3

By the way, the problem with your code to convert degrees to radians is that 22/7 = 3.142857 while PI = 3.141593 (to seven digits). The use of 22/7 instead of PI introduces a substantial error (0.04%) into every single calculation based on that conversion, so it is cumulative. But then, GPS coordinates cannot be very accurately represented in 32 bit float variables, either.

Thank you, the problem was solved. It is also essential saying thank you to other topics in forum about this topic. This is the updated code.

#include <SoftwareSerial.h>
#include <math.h>
#define NMEA_SIZE 256
#define SIZE 120
#define SIZEA 120

SoftwareSerial GPS = SoftwareSerial(6, 5);

byte NMEA[NMEA_SIZE];
double lat_values[SIZE];
double lon_values[SIZEA];


double time,checkdistance,dis,lo_dif,la_dif,lat_1_radian1,lat_1_radian2,lon_1_radian1,lon_1_radian2,lat2_dif,lon2_dif,displacement,sum,distance,b,lon1_dif,lon_1_radian,lon1_m,lon1_d,lat1_dif,lat1_memory,lat1_mdeneme,lat_1_radiandeneme,lat_1_radian,lat1_m,lat1_d,lat1_degree,lat1_degree_1, lat1_degree_2,d,d2;
int lon1_m1,lon1_m2,lon1_m3,lon1_m4,lon1_m5,lon1_m6,lon1_d1,lon1_d2,s,m,n,e,z,f,g,h,lat1_d1,lat1_d2,lat1_m1,lat1_m2,lat1_m3,lat1_m4,lat1_m5,lat1_m6;
//int time;

void getData() {

  byte character;
  int index = 0;

  do {
    if (GPS.available()) {
      character = GPS.read();
      NMEA[index] = character;
      index++;
    }
  } 
  while(index < NMEA_SIZE && character != '

);

NMEA[index - 2] = '\0';
}

void setup() {

GPS.begin(4800);
  Serial.begin(9600);
GPS.println("$PSRF100,0,4800,8,1,0*0F"); //this sets it to binary mode
  delay(3000);
  GPS.write((byte)0xA0);
  GPS.write((byte)0xA2);
  GPS.write((byte)0x00);
  GPS.write((byte)0x02);
  GPS.write((byte)0x8F);
  GPS.write((byte)0x00);
  GPS.write((byte)0x00);
  GPS.write((byte)0x8F);
  GPS.write((byte)0xB0);
  GPS.write((byte)0xB3);
  delay(100);
  GPS.write((byte)0xA0);
  GPS.write((byte)0xA2);
  GPS.write((byte)0x00);
  GPS.write((byte)0x18);
  GPS.write((byte)0x81);
  GPS.write((byte)0x02);
  GPS.write((byte)0x01);
  GPS.write((byte)0x01);
  GPS.write((byte)0x00);
  GPS.write((byte)0x01);
  delay(100);
  GPS.write((byte)0x00);
  GPS.write((byte)0x01);
  GPS.write((byte)0x00);
  GPS.write((byte)0x01);
  GPS.write((byte)0x01);
  GPS.write((byte)0x01);
  GPS.write((byte)0x00);
  GPS.write((byte)0x01);
  GPS.write((byte)0x00);
  GPS.write((byte)0x01);             
  delay(100);
  GPS.write((byte)0x00);
  GPS.write((byte)0x01);
  GPS.write((byte)0x00);
  GPS.write((byte)0x01);
  GPS.write((byte)0x00);
  GPS.write((byte)0x01);
  GPS.write((byte)0x12);
  GPS.write((byte)0xC0);
  GPS.write((byte)0x01);
  GPS.write((byte)0x61);
  delay(100);
  GPS.write((byte)0xB0); //back to TTL ??
  GPS.write((byte)0xB3);

n=0;
  m=0;
  sum=0;
  lon1_dif=0;
        lat1_dif=0;
        lat2_dif=0;
        lat2_dif=0;
     
       
  /*
  lon_1_radian1=(float)(((2229)/(180))/7)+((((((229.104)/180)/60)/7)));
  lon_1_radian2=(float)(((2229)/(180))/7)+((((((229.136)/180)/60)/7)));
 
  lo_dif=lon_1_radian2-lon_1_radian1;
 
  lat_1_radian1=(float)(((2240)/(180))/7)+((((((2258.454)/180)/60)/7)));
  lat_1_radian2=(float)(((2240)/(180))/7)+((((((2258.529)/180)/60)/7)));
 
  la_dif=lat_1_radian2-lat_1_radian1;
 
  dis=(float)(2*(6378.49)(1000))(asin((sqrt(((sin((la_dif)/2)))(sin((la_dif)/2))+(cos(lat_1_radian1)cos(lat_1_radian2)(((sin((lo_dif)/2)))(sin((lo_dif)/2))))))));
 
  Serial.println(lat_1_radian1,8);
  Serial.println(lon_1_radian2,8);
  Serial.println(lo_dif,8);
  Serial.println(dis,8);
  */

for(s =0 ; s<100000 ; s++){

getData();
  //  delay(1000);
//  time=millis();
  //  Serial.println(time);
   
    if(NMEA[17] == 'V')
    {
      Serial.print("NO DATA\n");
    }

//else if(NMEA[2] == 'G' && NMEA[3] == 'S' && NMEA[4] == 'V') {
    // int i = 0; 
    //for(i = 0; NMEA[i] != '\0'; i++) { Serial.write(NMEA[i]);  }
    //  }
    else if(NMEA[2] == 'R' && NMEA[3] == 'M' && NMEA[4] == 'C') {
      int i = 0;
    //  for(i = 0; NMEA[i] != '\0'; i++) { Serial.write(NMEA[i]);  }
      Serial.print("\n");

Serial.print("Latitude: ");
      for(i = 19; i<21; i++) {
        Serial.write(NMEA[i]); 
      }
      Serial.print(".");
      for(i = 21; i<23; i++) {
        Serial.write(NMEA[i]); 
      }
      for(i = 24; i<28; i++) {
        Serial.write(NMEA[i]); 
      }
      Serial.print(" N");
      Serial.print("\n");

Serial.print("Longitude: ");
      for(i = 32; i<34; i++) {
        Serial.write(NMEA[i]); 
      }
      Serial.print(".");
      for(i = 34; i<36; i++) {
        Serial.write(NMEA[i]); 
      }
      for(i = 37; i<41; i++) {
        Serial.write(NMEA[i]); 
      }
      Serial.print(" E");

e= NMEA[44]- '0';   
      f= NMEA[45]- '0';
      g= NMEA[47]- '0';
      h= NMEA[48]- '0';

lat1_d1=NMEA[19]- '0';
      lat1_d2=NMEA[20]- '0';

lat1_m1=NMEA[21]- '0';
      lat1_m2=NMEA[22]- '0';
      lat1_m3=NMEA[24]- '0';
      lat1_m4=NMEA[25]- '0';
      lat1_m5=NMEA[26]- '0';
      lat1_m6=NMEA[27]- '0';

lon1_d1=NMEA[32]- '0';
      lon1_d2=NMEA[33]- '0';

lon1_m1=NMEA[34]- '0';
      lon1_m2=NMEA[35]- '0';
      lon1_m3=NMEA[37]- '0';
      lon1_m4=NMEA[38]- '0';
      lon1_m5=NMEA[39]- '0';
      lon1_m6=NMEA[40]- '0';

lat1_d= (double)lat1_d110+lat1_d2;
      lat1_m= (double)lat1_m1
10+lat1_m2+lat1_m30.1+lat1_m40.01+lat1_m50.001+lat1_m60.0001;

lat_1_radian=(double)(((22lat1_d)/(180))/7)+((((((22lat1_m)/180)/60)/7)));

lon1_d= (double)lon1_d110+lon1_d2;
      lon1_m= (double)lon1_m1
10+lon1_m2+lon1_m30.1+lon1_m40.01+lon1_m50.001+lon1_m60.0001;

lon_1_radian=(double)((((3.1415)*lon1_d)/(180)))+(((((((3.1415)*lon1_m)/180)/60))));

if(m<120){
        lat_values[m]=lat_1_radian;
        if(m>0){
          lat1_dif=lat_values[m]-lat_values[m-1];
          lat2_dif=lat_values[m]-lat_values[0];
        }

}

if(n<120){
        lon_values[n]=lon_1_radian;
        if(n>0){
          lon1_dif=lon_values[n]-lon_values[n-1];
          lon2_dif=lon_values[n]-lon_values[0];
        }

}
      if(m==0){checkdistance=0;}
    if(m>0){
    checkdistance=(double)(2*(6364.49)(1000))(asin((sqrt(((sin((lat1_dif)/2)))(sin((lat1_dif)/2))+(cos(lat_values[m-1])cos(lat_values[m])(((sin((lon1_dif)/2)))(sin((lon1_dif)/2))))))));
  } if (checkdistance<20){
     
        if(n>0){
        lon_values[n]=lon_values[n-1];
        lat_values[m]=lat_values[m-1];
        lon1_dif=lon_values[n]-lon_values[n-1];
        lon2_dif=lon_values[n]-lon_values[0];
      lat1_dif=lat_values[m]-lat_values[m-1];
          lat2_dif=lat_values[m]-lat_values[0];}}
     
    if(m==0){distance=0;}
    if(m>0){
      distance=(double)(2*(6364.49)(1000))(asin((sqrt(((sin((lat1_dif)/2)))(sin((lat1_dif)/2))+(cos(lat_values[m-1])cos(lat_values[m])(((sin((lon1_dif)/2)))(sin((lon1_dif)/2))))))));
    }

sum=sum+distance;
     
      if(m==0){displacement=0;}
    if(m>0){
     
      displacement=(double)(2*(6364.49)(1000))(asin((sqrt(((sin((lat2_dif)/2)))(sin((lat2_dif)/2))+(cos(lat_values[0])cos(lat_values[m])(((sin((lon2_dif)/2)))(sin((lon2_dif)/2))))))));
     
    }

n++;
      m++;

d= 10e+f+g(0.1)+h*(0.01);
      d2=(0.5144)d(3.6);

Serial.print("\n");
     
Serial.println(checkdistance,4);
Serial.println(m);

Serial.print("Toplam Yol: ");
      Serial.println(sum,4);
      Serial.print("Yerdegistirme: ");
      Serial.println(displacement,4);

delay(5000);

}
    /*
    Serial.print("");
    Serial.print("\n");
    Serial.println(lat1_m,6);
    Serial.println(lat_1_radian,6);
    */

}
  }

void loop() { 
}