Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

latitude and longitude

Status
Not open for further replies.

vead

Full Member level 5
Joined
Nov 27, 2011
Messages
285
Helped
3
Reputation
6
Reaction score
3
Trophy points
1,298
Location
india
Activity points
3,815
I was searching about 8051 gps programming. I don't understand latitude and longitude. I found this link https://www.electronicshub.org/interfacing-gps-8051-microcontroller/

I don't understand what's happening in these two function

Code:
void gps ()
{
   unsigned int LAT[9], LON[10];  
   unsigned char Temp, i;
   if (rx_data() == ‘$’)
   {
     if( rx_data() == ‘G’)
      {
        if (rx_data() == ‘P’)
       {
         if (rx_data() == ‘R’)
         {
         if (rx_data() == ‘M’)
           {
             if (rx_data() == ‘C’)
             {
                while (rx_data() != ‘,’);
                while (rx_data() != ‘,’);
           Temp = rx_data();       /*checking for “A” condition*/

           if (Temp == ‘A’||Temp == ‘V’)
                   {
                      while (rx_data() != ‘,’);                                                                         
                       LCDCmd (0x80);                                     /*latitude values*/
                         for (i=0; i<9; i++)
                        {
                            LAT[i] = rx_data();
                            LCDData (LAT[i]);
                        }
                     while (rx_data() != ‘,’);
                     while (rx_data() != ‘,’); 
                      LCDCmd (0xc0);  /*longitude values*/
                       for (i=0; i<10; i++)

                       {

                           LON[i] = rx_data();

                           LCDData (LON[i]);

                        }

                    }

            }
        }
     }
  }
 } 
}
}
 

For anyone seeing accented characters, A' should be a double quote symbol (").
It reads characters from the UART and compares them one at a time to find a particular 'word' which it then passes to the LCD.
A classic example of how not to parse a text string!

Brian.
 
  • Like
Reactions: vead

    vead

    Points: 2
    Helpful Answer Positive Rating
For anyone seeing accented characters, A' should be a double quote symbol (").
It reads characters from the UART and compares them one at a time to find a particular 'word' which it then passes to the LCD.
A classic example of how not to parse a text string!

Brian.
Thank you very much @Brian

I know we can send or receive 8 bit or 1 byte data using uart But I am having difficulty to understand given function. Microcontroller receiving data from GPS

if (rx_data() == ‘$’)

we are checking function rx_data is equal to ‘$’ ...and so on

I don't understand what the meaning of these character's and why we are checking
 

we are checking function rx_data is equal to ‘$’ ...and so on

I don't understand what the meaning of these character's and why we are checking

This is because you have not yet taken a look at any webpage explaining NMEA standard in detail:


The above code is a parser for the specific sentence $GPRMCxxxx

- - - Updated - - -

Anyway, in my view the program seems very confusing due to the encoding of characters in your text editor, probably not UTF-8.
 
  • Like
Reactions: vead

    vead

    Points: 2
    Helpful Answer Positive Rating
I think it is copied directly from HTML, hence the strange encoding.

It works like this:
get a character
is it $
if it is get a character
is it G
if it is get a character
is it P
and so on....

A far better way is to repeatedly read characters until the end of the line and store them in a string array. You can then look for the individual fields in the string and extract them. That way has the advantage of simpler code and it can be used for any of the NMEA messages. At the moment, it requires completely recoding to recover a different NMEA message, if you capture the string first you can easily extract any other message from it by using string comparison instructions or by tokenizing it. It also overcomes the potential problem of capturing forever if a matching character isn't found.

Brian.
 
  • Like
Reactions: vead

    vead

    Points: 2
    Helpful Answer Positive Rating
I think it is copied directly from HTML, hence the strange encoding.

Brian.
Is it complete code ?
Code:
#include<reg51.h>
#define port2 P2
sbit rs = P1^0;
sbit rw = P1^1;
sbit e = P1^2;
char info[70];
char test[6]={"$GPGGA"};
char comma_position[15];
unsigned int check=0,i;
unsigned char a;
void receive_data();
void lcd_latitude();
void lcd_longitude();
 
//DELAY FUNCTION
void delay(unsigned int msec)
{
int i,j ;
for(i=0;i<msec;i++)
for(j=0;j<1275;j++); 
}
 
// LCD COMMAND SENDING FUNCTION
void lcd_cmd(unsigned char item)
{
port2 = item;
rs= 0;
rw=0;
e=1;
delay(1);
e=0;
return;
} 
 
// LCD DATA SENDING FUNCTION
void lcd_data(unsigned char item)
{
port2 = item;
rs= 1;
rw=0;
e=1;
delay(1);
e=0;    
return;
}
 
 // LCD STRING SENDING FUNCTION 
void lcd_string(unsigned char *str)
{
int i=0;
while(str[i]!='\0')
{
        lcd_data(str[i]);
        i++;
        delay(10);
   }
        return;
}
 
// SERIAL PORT SETTING
void serial()
{
TMOD=0x20;      //MODE=2
TH1=0xfa;     // 4800 BAUD
SCON=0x50  ;    // SERIAL MODE 1 ,8- BIT DATA ,1 STOP BIT ,1 START BIT , RECEIVING ON
TR1=1;         //TIMER START
}
 
void find_comma()
{
unsigned int i,count=0;
for(i=0;i<70;i++)
{ 
if(info[i]==',')
{
comma_position[count++]=i;
}
    }
}
void compare()
{  
IE=0x00;       //Interrupt disable 
find_comma();   //Function to detect position of comma in the string
lcd_latitude();   //Function to show Latitude
lcd_longitude(); //Function to show Longitude
check=0;
IE=0x90;   //Interrupt enable
}
void receive_data()    interrupt 4  
{
info[check++]=SBUF;  //Read SBUF
if(check<7)         //Condition to check the required data
    {
if(info[check-1]!=test[check-1])
check=0;
    }
RI=0;
}
void lcd_shape()      //Function to create shape of degree
{
lcd_cmd(64);
lcd_data(10);
lcd_data(17);
lcd_data(17);
lcd_data(10);
lcd_data(0);
lcd_data(0);
lcd_data(0);
lcd_data(0);
}
 
void lcd_latitude() //Function to display Latitude
{
unsigned int c2=comma_position[1]; //Position of second comma
lcd_shape();
lcd_cmd(0x01);         // Clear LCD display
lcd_cmd(0x84);         //Move cursor to position 6 of line 1
lcd_string("LATITUDE"); //Showing Latitude
lcd_cmd(0xC0); //Beginning of second line  
lcd_data(info[c2+1]); 
lcd_data(info[c2+2]);
lcd_data(0); //Degree symbol
lcd_data(info[c2+3]); 
lcd_data(info[c2+4]);
lcd_data(info[c2+5]);
lcd_data(info[c2+6]);
lcd_data(info[c2+7]);
lcd_data(info[c2+8]);
lcd_data(info[c2+9]);
lcd_data(0x27);          //ASCII of minute sign(')
lcd_data(info[c2+10]);
lcd_data(info[c2+11]);
delay(250);
} 
 
void lcd_longitude()
{
unsigned int c4=comma_position[3];
lcd_cmd(0x01);            //Clear LCD display
lcd_cmd(0x84);            //Move cursor to position 4 of line 1
lcd_string("LONGITUDE"); //Showing Longitude
lcd_cmd(0xC0);    //Begining of second line  
lcd_data(info[c4+1]);
lcd_data(info[c4+2]);
lcd_data(info[c4+3]);
lcd_data(0);
lcd_data(info[c4+4]);
lcd_data(info[c4+5]);
lcd_data(info[c4+6]);
lcd_data(info[c4+7]);
lcd_data(info[c4+8]);
lcd_data(info[c4+9]);
lcd_data(info[c4+10]);
lcd_data(0x27);               //ASCII of minute sign(')
lcd_data(info[c4+11]);
lcd_data(info[c4+12]);
delay(250);
}
void main()
{
serial();
lcd_cmd(0x38);        //2 LINE, 5X7 MATRIX
lcd_cmd(0x0e);         //DISPLAY ON, CURSOR BLINKING
IE=0x90;
while(1)
{
if(check==69)
compare();
}
}
I will try to make my own program that's why I want to know the best method.

I don't know what is in these function
find_comma(),
void compare(),
void lcd_shape()
void lcd_latitude() ,
void lcd_longitude()
 
Last edited:

Is it complete code ?

The originally posted code was purposed to decode the sentence RMC, whereas the second code expects the raw sequence of bytes of the sentence GGA with a fixed lenght, a worse implementation in my oppinion, and I doubt this will work because the value of the latitude and longitude sometimes are shown with different resolution, with or without one additional digit after comma, as stated on the link above mentioned, quoted here:

"The data itself is just ascii text and may extend over multiple sentences in certain specialized instances but is normally fully contained in one variable length sentence. The data may vary in the amount of precision contained in the message. "
 

I am using this GPS Module with Ceramic Antenna for DIY Handheld Positioning System for $7.86
https://www.dx.com/p/open-smart-gps...ino-apm2-5-flight-control-480918#.WiDKElWnH4Y
This is the NEMA ascii sentence that it works with
$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68
225446 Time of fix 22:54:46 UTC
A Navigation receiver warning A = OK, V = warning
4916.45,N Latitude 49 deg. 16.45 min North
12311.12,W Longitude 123 deg. 11.12 min West
000.5 Speed over ground, Knots
054.7 Course Made Good, True
191194 Date of fix 19 November 1994
020.3,E Magnetic variation 20.3 deg East
*68 mandatory checksum
 

I suggest you look at the 'C' instruction "strtok", it is designed to split a string into component parts by looking for a specified character. If you use a comma as that character, it will return a pointer to each field in the string.

Vead, just copying other peoples code, especially when it is written for a different task will lead you nowhere. The first thing you have to do is analyze the incoming data and decide what you want to with it. Pay attention to common things in each block of data, such as then all starting with '$', all using commas to separate the data fields and importantly, see if there is a common character at the end of each line, for example a carriage return or line feed character. When you know what you are dealing with, a strategy to decode it is trivial task.

Brian.
 
  • Like
Reactions: vead

    vead

    Points: 2
    Helpful Answer Positive Rating
Vead, just copying other peoples code, especially when it is written for a different task will lead you nowhere.
I can write my own subroutine for lcd and uart but the problem with only GPS routines I am looking someone code because I don't have any idea about it. I am trying to understand how they did programming.

Is it batter code to follow? if yes then I don't understand only one routine that is void ISR_sc(void) interrupt 4

Code:
#include<reg51.h>
#include <stdio.h>
#include <string.h>
 
#define lcd_data P2
 
sbit rs=P0^0;
sbit rw=P0^1;
sbit en=P0^2;
 
void lcd_init();
void cmd(unsigned char a);
void dat(unsigned char b);
void show(unsigned char *s);
void lcd_delay();
 
void tx(unsigned char send);
void tx_str(unsigned char *s);
unsigned char rx();
 
char namegps[7], name1gps[7] = "GPRMC,",gpsdat[63];
char msggps , checkgps;
int h;
unsigned char f;
 
void main()
{
    TMOD = 0x20;
    TH1 = TL1=0xfd;
    SCON = 0x50;
    TR1 = 1;
    IE = 0x90;
    lcd_init();
    cmd(0x80);
    show("LON:                ");
    cmd(0xc0);
    show("LAT:                ");
    while(1);
}
 
 
void ISR_sc(void) interrupt 4
{
    if(RI==1){
        msggps= rx();
        if(msggps=='$') {
            EA = 0;
            for(f=0;f<=5;f++) {
                namegps[f]=rx();
            }
            checkgps=strcmp(namegps,name1gps);
          if(checkgps==0) {
                for(f=0;f<=62;f++) {
                    gpsdat[f]=rx();     
                }
                cmd(0x84);
                for(h=12;h<14;h++) {
                    dat(gpsdat[h]);
                }
                dat('.');
                for(h=14;h<16;h++) {
                    dat(gpsdat[h]);
                }
                for(h=17;h<19;h++) {
                    dat(gpsdat[h]);
                }
                dat(223);
                dat(' ');
                dat('N');
 
                cmd(0xc4);
                for(h=26;h<28;h++) {
                    dat(gpsdat[h]);
                }
                dat('.');
                for(h=28;h<30;h++) {
                    dat(gpsdat[h]);
                }
                for(h=31;h<33;h++) {
                    dat(gpsdat[h]);
                }
                dat(223);
                dat(' ');
                dat('E');
                EA = 1;
            }
        }   
    }
}
 
void tx(unsigned char send)
{
    SBUF=send;
    while(TI==0);
    TI=0;
}
 
void tx_str(unsigned char *s)
{
    while(*s)
        tx(*s++);
}
 
unsigned char rx()
{
    while(RI==0);
    RI=0;
    return SBUF;
}
 
void lcd_init()
{
    cmd(0x38);
    cmd(0x0e);
    cmd(0x01);
    cmd(0x06);
    cmd(0x0c);
    cmd(0x80);
}
 
void cmd(unsigned char a)
{
    lcd_data=a;
    rs=0;
    rw=0;
    en=1;
    lcd_delay();
    en=0;
}
 
void dat(unsigned char b)
{
    lcd_data=b;
    rs=1;
    rw=0;
    en=1;
    lcd_delay();
    en=0;
}
 
void show(unsigned char *s)
{
    while(*s) {
        dat(*s++);
    }
}
 
void lcd_delay()
{
    unsigned int lcd_delay;
    for(lcd_delay=0;lcd_delay<=6000;lcd_delay++);
}
 

In my opinion that code should *NOT* be followed if only for one reason - it does way too much in the ISR.
ISR code should execute as quickly as possible and get out. The main loop is where the processing should occur, typically triggered by some flag that is set in the ISR.
Remember that when the ISR is working, nothing else can happen (except perhaps higher priority interrupts on devices that have such things).
Worse still, there are calls all through the ISR to the 'dat()' routine that contains a delay - this is never a good idea.
I'm not sure what calls the ISR but it does read in the GPS string (character by character,processing as it goes along) which is very much along the lines of your original code.
If it were me, I would create a ring buffer that is filled by an ISR on the UART (?if that is who the characters come in) that sets a flag when it sees the '\n' character (all of the GPS strings I've seen end with this character). The mainline code can test for the flag and starts decoding the full sentence when the flag is set.
Also it means that you can use all of the string parsing functions (as betwixt and others have suggested) to parse and interpret the string efficiently.
Finally, the LCD output (with all of the delays it may require) can occur (effectively) in parallel with the GPS string input and not interfere.
Susan
 
  • Like
Reactions: vead

    vead

    Points: 2
    Helpful Answer Positive Rating
....Something along the lines of

Establish a string buffer (a character array) long enough for the longest GPS message.
Call ISR when the UART has a character

-- inside the ISR ---
1. if it is a "$" set a pointer to the start of a string buffer
2. if it's a CR/LF set a variable (a 'flag') to say the end of string has been found
3. if there is space in the buffer (check the pointer hasn't reached buffer length) add the character to it and advance the pointer.
4. get out of the ISR

-- in the main code --
1. check the flag to see if the whole string has been received
2. reset the flag
3. scan along the string to isolate the individual fields and extract the data you want.

So all the slow string manipulation routines are in 'main' and the ISR just does a quick check for valid characters and stores them. Susan suggests a circular buffer to store the string, I prefer a linear buffer and a pointer, reset when a $ is received but both methods will work just as well and avoid the pitfalls you have at the moment.

Brian.
 
  • Like
Reactions: vead

    vead

    Points: 2
    Helpful Answer Positive Rating
I can write my own subroutine for lcd and uart but the problem with only GPS routines I am looking someone code because I don't have any idea about it.

At the time I made my own NMEA GPS parsing code, I started the development first in a simulation environment, Proteus in this case. I used sentences available on other websites and made the data entry via Realterm and the creation of a serial port via an application called 'VSPE'. I strongly recommend that you think of a similar approach, otherwise you will end up in this endless process of trial and error with foreign codes that may merely work by accident.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top