CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem reading RS232
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Kristofer



Joined: 22 Feb 2006
Posts: 1
Location: Coventry, GB

View user's profile Send private message

Problem reading RS232
PostPosted: Wed Feb 22, 2006 8:21 am     Reply with quote

Hi!

I have got a problem to read a string over the RS232 connection.
There is a GPS receiver connected which sends a string looking like this:

$GPGGA,125803.60,5224.43451,N,00130.09173,W,1,05,1.5,84.5,M,48.7,M,,*4E<CR><LF>

When I send the same message from a PC without the carriage return and line feed in the end, it works fine. The PIC18F452 reads it and returns the latitude and longitude via printf.
When the GPS is connected (so there is a CR and LF), it works only one time. There is no way to read another string but resetting the PIC.

Any idea?

Sourcecode:

Code:
#include<18F452.h>
#include<stdio.h>
#use delay (CLOCK=20000000)
#use rs232 (BAUD=9600,XMIT=PIN_C6,RCV=PIN_C7)


void init();
void main();
void read_RS232();
int i = 0;
int j = 0;
char string[72];
char latitude[13];
char longitude[14];


void main(){

init();
while(1){
   output_high(pin_d1);
   read_RS232();
   output_low(pin_d1);

   for (i=0; i<12; i++){
      latitude[i] = string[j+17];
      j++;
   }
   latitude[12] = '\0';
   j=0;
   for (i=0; i<13; i++){
      longitude[i] = string[j+30];
      j++;
   }
   longitude[13] = '\0';
   j=0;
   printf("Latitude: %S\n\r", latitude);
   printf("Longitude: %S\n\r", longitude);
}
}


void read_RS232(){

   for(i=0; i<71; i++){
       string[i] = getc();
   }               
   string[71] = '\0';
}


void init(){
   output_bit(pin_d1,0);
}

Thanks in advance!
angel



Joined: 19 Oct 2004
Posts: 40

View user's profile Send private message

hi
PostPosted: Wed Feb 22, 2006 8:54 am     Reply with quote

I think it would be better to use kbhit and gets :
if(kbhit){
gets(message)
}
and message could be a global char message[71] variable
Donlaser



Joined: 17 Sep 2005
Posts: 12
Location: Trenque Lauquen, Argentina

View user's profile Send private message MSN Messenger

PostPosted: Wed Feb 22, 2006 12:33 pm     Reply with quote

In the read function you need to wait for $ symbol, or better $GPGGA, then read the rest of the line.

Search the forum for NMEA parsing.

I do someting like that, and then do the parsing of the string received, in my case i use the sentence $GPRMC,...

Code:


   char k;                                                     
   char i;
   char buffer[80];                                       
   char busca[]="GPRMC";                                   

   do 
   {
       while ( fgetc(GPS) != 36 );                              // wait  $
       for (k=0;k<6;k++) buffer[k]=fgetc(GPS);       // store first 6 chars toel buffer[]  (GPRMC,)
   }   while (strncmp(buffer,busca,5)!=0);                   // compare if the first five chars are gprmc, if not, keep searching


   // now read the rest of the sentence, stop if get a * or reach the max buffer lenght
   k=0; i=0;
   while ( i !='*' && k<79)                                     
   {
      i = fgetc(GPS);
      Buffer[k++]= i;
   }



then i parse the GPRMC string in buffer...
Eliberg
Guest







PostPosted: Fri Feb 24, 2006 7:04 am     Reply with quote

I don't know if this is the error, but in your string
$GPGGA,125803.60,5224.43451,N,00130.09173,W,1,05,1.5,84.5,M,48.7,M,,*4E<CR><LF> you have 73 chars, if you consider <CR><LF>, and you read only 71 chars, with your void read_RS232 function.

Bye
eli
darkswarm



Joined: 27 Feb 2006
Posts: 7

View user's profile Send private message

PostPosted: Mon Feb 27, 2006 2:41 am     Reply with quote

Hi,

i'm having almost the same problem as Kristofer. I'm using 16F876 to extract the latitude and longitude from my GPS receiver to be shown on Hyperterminal.

Eliberg, I use a function similar to void read_RS232, and my program also works only once before i have to reset everything. If it really is a problem, how do i solve it?

I'm not familiar with NMEA parse, so i try not to use it for now as i'm afraid it might mess up my program even further.

Really appreciate the help. Thanks in advance.
sjbaxter



Joined: 26 Jan 2006
Posts: 141
Location: Cheshire, UK

View user's profile Send private message Visit poster's website

PostPosted: Mon Feb 27, 2006 6:20 am     Reply with quote

Guys, the easiest way of parsing NMEA is using a state machine. Handle each byte as it comes in and change the state of the machine (a simple switch statement with cases for handling '$' '*' ',' '<CR>' '<LF>' and the default case hanlding the data in between based on the current machine state.

If the wrong thing arrives when you aren't expecting it, throw the sentence away and reset the state machine. If you get a $ at any point and your state machine is waiting for something else, throw the sentence away as you have missed the end marker * so set the state machine accordingly. If the checksum doesn't match your calculated checksum, throw the sentence away and reset the state machine. Don't assume all fields to be populated with data so dont parse on byte position of the fields, use the comma delimiters, count them in the state machine.

You could try and use the UART interrupt handler for capturing each character so you don't miss any.

you can eliminate the for loops this way as you already have the data, so why go though it again, the more processing you do after the event, the more likly you are of missing new data comming in and at 1 second intervals (NMEA0183), the data doesn't come around too often !

Using a state machine, you only need buffers big enough to build up the LAT/LONG info from the bytes coming in as you aren't interested in storing the whole sentence. i.e.

char latitude[13];
char longitude[14];

hope this gives you a few ideas and a different view on how to solve this one.
_________________
Regards,
Simon.
darkswarm



Joined: 27 Feb 2006
Posts: 7

View user's profile Send private message

PostPosted: Fri Mar 10, 2006 1:42 am     Reply with quote

Hi,

Below is a code that I modified from another CCS forum author, Kimi. It works for me but i'm hoping to improve on it.

Code:
#include <16F876A.h>
#use delay(clock=20000000)
#fuses NOWDT,HS, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GPS,errors)//data from GPS to PIC
#use rs232(baud=4800,parity=N,xmit=PIN_C5,rcv=PIN_C4,bits=8,stream=PC,errors)// data from PIC to PC
#byte portc=7

char c;
char gps_packet[41]; // take the first 41 bits of the data string
unsigned int8 i;

void main() {
set_tris_c(0x90);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);

setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
do{
i = 0;
for (i = 0; i <= 40; i++){ // get the first 41 bits of the data
c = fgetc(GPS);
gps_packet[i] = c;

}
for (i = 17; i <= 40; i++){ // print out bits 17 to 40, which correspond to the latitude and longitude
fprintf(PC,"%C",gps_packet[i]);

}
}while(1);
}


Below is the original NMEA0183 data that i get when i'm just connecting the GPS to the PC.
Code:
$GPVTG,,,,,,,,,N*30                   
$GPGGA,,,,,,0,00,,,,,,,*66                         
$GPVTG,,,,,,,,,N*30                   
$GPGGA,,,,,,0,00,,,,,,,*66                         
$GPVTG,,,,,,,,,N*30                   
$GPGGA,,,,,,0,00,,,,,,,*66                         
$GPVTG,,,,,,,,,N*30                   
$GPGGA,013412.00,0257.8113,N,10143.5980,E,1,04,5.07,00091,M,-008,M,,*4A                                                                       
$GPVTG,002.5,T,003.2,M,000.2,N,000.4,K,A*23                                       
$GPGGA,013413.00,0257.8106,N,10143.5974,E,1,04,5.07,00091,M,-008,M,,*44                                                                       
$GPVTG,359.6,T,000.3,M,000.0,N,000.0,K,A*29                                       
$GPGGA,013414.00,0257.8105,N,10143.5973,E,1,04,5.07,00091,M,-008,M,,*47                                                                       
$GPVTG,000.0,T,000.7,M,000.0,N,000.0,K,A*24 


After including the PIC and running the C code that i've modified, this is what i get:

Code:
$GPVTG,,,,,2,,,,,,,*64                     
$GPVTG,,,,,2,,,,,,,*64                     
$GPVTG,,,,,2,,,,,,,*64                     
$GPVTG,,,,,2,,,,,,,*64                     
$GPVTG,,,,,2,,,,,,,*64
965,000.0,T,000.7,M,000.0,N0,0257.8134,N,10143.5964,000.0,T,000.7,M,000.0,N0,025                                                                               
7.8135,N,10143.5963,000.0,T,000.7,M,000.0,N0,0257.8135,N,10143.5962,000.0,T,000.                                                                               
7,M,000.0,N0,0257.8136,N,10143.5962,E,000.0,T,000.7,M,000.0,N0,0257.8136,N,10143.

(I'm extracting bits 17 to 41 from the data string)

However, what i want is just 0257.8136,N,10143.5962,E( the latitude and longitude) and that data is in the $GPGGA lines. How do i exclude the $GPVTG lines? From the the remaining $GPGGA lines, how do i extract just the data that i want?

I hope that finally, i'll be able to present the data on Hyperterminal in this format:

Latitude: 00257.8134,N
Longitude: 10143.5964,E


Although i have a concept of what i want, I'm not sure how to implement it in C. If i really need a circular buffer or NMEA parsing, how do i include that code in the program that i've shown above. Really appreciate the help.Thank you very much in advance.

Best regards
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Fri Mar 10, 2006 2:51 am     Reply with quote

It might be possible to get this to work reliably without an RDA interrupt routine filling a circular buffer but I wouldn't bet on it.
Advice:
Keep the RDA as short as humanly possible.
Get the received character if it is the $ then set a global flag in the RDA to indicate on the next interrupt to begin stuffing chars into the buffer until you see the end of a sentence. Then set a global flag that a sentence is in the buffer and parse the sentence in your main routine.
Any attempt to do extensive parsing in the interrupt will mess up the timing.
Remember at no time whatsoever is the GPS ever synchronized to your PIC code. Whatever the PIC is doing it must be prepared to capture an inbound character at anytime ..that's where the RDA interrupt comes in and the severe lack of extensive code in the interrupt makes sure that the interrupt work is done before the next char would cause the next interrupt.
Have fun you'll learn alot.
PS some GPS modules can be polled but most just start talking so you can't synchronize them to your code.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Fri Mar 10, 2006 3:15 am     Reply with quote

I believe you would learn more by doing this yourself but reluctantly here is some code I wrote a few years ago
It takes an rs232 talking GPS and sets it up as a slave in an I2C bus
you won't need the I2C stuff but the GPS parsing might help
Disclaimer :
the code below is not for commercial use and there is no assertion that it is save for any risky purpose like navigation. Any user of this code assumes all risks.
Code:
//////////////////////////////////////////////////////////////////////
///////////////////                             /////////////////////
///////////////////   Intefaces GPS to I2C      /////////////////////
//////////////////                              /////////////////////
////// The GPS sends sentences GPBWC GPGLL GPRMB GPXTE PGRMZ  ///////
//////     every 2 seconds  using NMEA-0183                   ///////
//////     GPR00 every (# waypts +1)*2 seconds                ///////
//////     GPWL  every (# route pts +1)*2 secs                ///////
//////     PGRMZ is specific to garmin                        ///////
/////                                                         ///////
/////////////////////////////////////////////////////////////////////

/**************************************************************
notes  a NMEA183 checksum is an xor of all chars between $ and *
       including commas
***************************************************************/
/********************************************************************
 $GPBWC,225444,2917.24,N,12309.57,W,051.9,T,031.6,M,001.3,N.004*29
 225444      UTC time of fix 22:54:44
 2917.24,N   Lattitiude of waypt
 12309.57,W     Longitude of waypt
 051.9,T        Bearing to waypt degrees true
 036.6,M        bearing to waypt degrees magnetic
 001.3,N        distance to waypt nautical miles
 004            Waypt ID
 *              end of sentence
 29             Checksum
*********************************************************************/

/********************************************************************
 $GPGLL,4916.45,N,12311.12,W*71
 4916.45,N     present latitude
 12311.12,W    present longitude
 *             end of sentence
 71            checksum
*********************************************************************/

/*********************************************************************
 $GPXTE,A,A,0.67,L,N*6F
 A   warning A is Ok V=warning ( loss of signal )
 A      not used by GPS so is a constant
 0.67   cross track error distance
 L      Steer left to Correct   ( R for right )
 N      distance in nautical miles
 *      end of sentence
 6F     checksum
**********************************************************************/


/*********************************************************************
*****   transmission from GPS is 4800 baud,1 stop,N parity  RS232 ****
*****                                                             ****
*****   program captures sentences and transmits via I2C          ****
*****   upon request by master I2C controller                     ****
*********************************************************************/

#include <16C73A.h>
#FUSES hs,NOPROTECT,NOWDT,NOBROWNOUT,NOPUT

#if __device__ ==77
 #device *=16
 #define BUFFER_SIZE 96
#else
 #define BUFFER_SIZE 40
#endif

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#use delay(clock=20000000)
#use I2C(SLAVE,ADDRESS=0xa0,scl=PIN_C3,sda=PIN_C4,NOFORCE_SW)

#USE RS232(BAUD=4800,XMIT=PIN_C6,RCV=PIN_C7) /* xmit pin c6 rcv c7 */

#BYTE RCREG=0x1A

#BYTE SSPADD=0x93
#BYTE SSPBUF=0x13
#BIT SSPIF=0x0C.3
#BIT SSPOV=0x14.6
#BIT I2C_BF=0x94.0
#BIT I2C_D_A=0x94.5
#BIT I2C_R_W=0x94.2
#BIT I2C_CKP=0x14.4
#BIT CREN=0x18.4
#BIT OERR=0x18.1
#define INTS_PER_SEC 76 // (20000000/(4*256*256))
#define LED1 PIN_B7
#define LED2 PIN_B6



struct {
/// status 'A' ok 'V' gps has problem (Ex.loss of signal ) 'X' invalid period
char  gll_status;
float gll_lat;
char  gll_N_S;
float gll_long;
char  gll_E_W;
char  xte_status;
float xte_error;
char  xte_steer;
char  bwc_status;
char  bwc_utc[6];
float bwc_lat;
char  bwc_N_S;
float bwc_long;
char  bwc_E_W;
float bwc_bearing_true;
float bwc_bearing_mag;
float bwc_dist;
} gps; // note a one byte CRC is appended upon transmission
       // gps is sent plus a CRC by the isr

short int led2_flag,sentence,PARSING;
byte seconds=0,int_count=0,I2C_CRC=0,GPS_CRC=0;
byte gps_buff[BUFFER_SIZE]; // implemented as a circular buffer

int next_gps_ptr=0,last_read_ptr=0,offset=0,temp;









///////////////////////////////////////////////////////////////////////
////////////////////////////// isr ////////////////////////////////////
//////////////////////////////////////////////////////////////////////

#int_rtcc
clock_isr()
{
if(--int_count==0){
                   if (seconds<60)  ++seconds;
                   else {// gps not responding
                        led2_flag=!led2_flag;
                        if (led2_flag) {output_low(LED2);output_high(LED1);}
                        else {output_high(LED2);output_low(LED1);}
                        gps.xte_status='X';
                        }
                  int_count=INTS_PER_SEC;
                  }
}


#int_ssp
void ssp_isr()
{
// offset is the pointer into the struct gps_out
// test if address or data now in buffer
output_low(LED2);
if(!I2C_D_A){
              // address hardware says the master matched b(7..1) of our address
              if(!I2C_R_W) { // master not permitted to write to us
                             // bit zero was 0 a write
                            goto quit;
                           }
             // an address so we set up for transfer of first byte
             temp=SSPBUF; // dummy read to clear BF  of SSPSTAT

             offset=&gps;
             SSPBUF=SSPADD; // echo our ADDRESS to the master
             I2C_CRC=0;
             goto quit;
             }
else {
     // data hardware says master is looking to read data

     if (offset<((&gps)+sizeof(gps))) {
                                       I2C_CRC=I2C_CRC ^ *offset; // xor to get CRC
                                       SSPBUF=*(offset++);
                                       goto quit;
                                        }


     if (offset==(&gps+sizeof(gps)))  {
                                       SSPBUF=I2C_CRC;
                                       offset++;
                                       output_high(LED2);// turn off led after transfer
                                       goto quit;
                                      }
     if (offset>(&gps+sizeof(gps)))   SSPBUF=0xFF;  // master is over reading so send FF

     }

quit:
I2C_CKP=1;// let master clock it out while we work

SSPOV=0;  // clear the overflow flag
SSPIF=0; // ready for next interrupt

}


#int_rda
void gps_isr()
{
char c;

/// note this routine needs to as short as possible since it is called
/// for each char received from GPS

c=RCREG ; // get data from RCREG hardware clears RCIF

if (c=='$') { sentence=true;output_low(LED1);return;} // new sentence

if(sentence){

      gps_buff[next_gps_ptr]=c;
      if (++next_gps_ptr>sizeof(gps_buff)) next_gps_ptr=0; // circular  buffer
      if((c==10)||(c==13)) {sentence=false;output_high(LED1);}

            }

}

///////////////////////////////////////////////////////////////////
///////////////////////////// subs //////////////////////////////
//////////////////////////////////////////////////////////////////

int gps_getc()
{
char c;
int next_char_ptr;
next_char_ptr=last_read_ptr+1;
if (next_char_ptr>sizeof(gps_buff))next_char_ptr=0;


// there is data available if next_gps_ptr != next_char_ptr

wait:  // data from gps will allow isr to update gps_ptr

if (next_gps_ptr == next_char_ptr) goto wait; // let gps advance
else        {
             c=gps_buff[next_char_ptr];
             if(c=='*')PARSING=false; // PARSING is reset in main loop
             last_read_ptr=next_char_ptr;
             if (PARSING) GPS_CRC=GPS_CRC ^ c; // calc between $ and *
            }
return(c);
}

int get_gps_CRC()
{
// get hex CRC immediately after the *
char hh,hl;

hh=gps_getc();
if (hh-'0'<10) hh=hh-'0';else hh=hh-'A'+10;
hl=gps_getc();
if (hl-'0'<10) hl=hl-'0';else hl=hl-'A'+10;


return hh*16+hl;
}

int get_gps_str( char * s)
{
// extract the item up to the next ',' or '*'
char c;
int len;
len=0;
c=gps_getc();

while ((c!=',') && (c!='*') && (len<10))
       {
        if ( (c>' ') && (c<'~') ) s[len++]=c;
        c=gps_getc();

       }
s[len]=0; // null terminate
return(len);
}

void parse_gll()
{
int len;
char s[10];
gps.gll_status='X'; // set preemptively as invalid until update done
                    // isr can interrupt at any point

if(get_gps_str(s)>0) gps.gll_lat=atof(s);else gps.gll_lat=0.0;
if(get_gps_str(s)>0)  gps.gll_N_S=s[0] ;else gps.gll_N_S='!';


if(get_gps_str(s)>0) gps.gll_long=atof(s);else gps.gll_long=0.0;
if(get_gps_str(s)>0)  gps.gll_E_W=s[0] ;else gps.gll_E_W='!';
if(get_gps_str(s)>0) {if (s[0]=='E') gps.gll_long=-gps.gll_long;}

// we now have parsed up to the *

if (get_gps_CRC()==GPS_CRC) gps.gll_status='A'; // we have gll data

seconds=0;
}

void parse_xte()
{
int len;
char s[10],temp;
gps.xte_status='X';
if(get_gps_str(s)>0) temp=s[0];else temp='X';
get_gps_str(s); //skip this item Loran c flag
if(get_gps_str(s)>0) gps.xte_error=atof(s);else gps.xte_error=0.0;
if(get_gps_str(s)>0) gps.xte_steer=s[0];else gps.xte_steer='X';
get_gps_str(s); //skip this item 'N' nautical miles

// we now have parsed up to the *

if(get_gps_crc()==GPS_CRC) gps.xte_status=temp;
seconds=0;
}

void parse_bwc()
{
int len;
char s[10];
gps.bwc_status='X';
if(get_gps_str(s)>5){ // we have utc hhmmss
                      memcpy(gps.bwc_utc,s,6);}

if(get_gps_str(s)>0) gps.bwc_lat=atof(s);else gps.bwc_lat=0.0;
if(get_gps_str(s)>0) gps.bwc_N_S=s[0];else gps.bwc_N_S='!';

if(get_gps_str(s)>0) gps.bwc_long=atof(s);else gps.bwc_long=0.0;

if(get_gps_str(s)>0) gps.bwc_E_W=s[0];else gps.bwc_E_W='!';
if(get_gps_str(s)>0) gps.bwc_bearing_true=atof(s);else gps.bwc_bearing_true=0.0;

get_gps_str(s); //skip this item 'T'

if(get_gps_str(s)>0) gps.bwc_bearing_mag=atof(s);else gps.bwc_bearing_mag=0.0;

get_gps_str(s); //skip this item 'M'

if(get_gps_str(s)>0) gps.bwc_dist=atof(s);else gps.bwc_dist=0.0;

get_gps_str(s); //skip this item 'N' nautical miles
get_gps_str(s); // skip this item waypt ID

// we now have parsed up to the *


if(get_gps_crc()==GPS_CRC) gps.bwc_status='A';
seconds=0;
}
////////////////////////////////////////////////////////////////////////////
//////////////////////////// leds //////////////////////////////////////////
///////////                                                    /////////////
/////////// LED1 is solid if we are receiving data we want     /////////////
/////////// LED2 is on if I2C is reading                       /////////////
/////////// both blink together 5 times at power up            /////////////
/////////// LED1 and LED2 blink alternatively                  /////////////
///////////    if GPS offline for 60 or more seconds           /////////////
///////////                                                    /////////////
////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// main ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

main()
{
int i;

///////////////////////////////////////////////////////////////////////
/////                 initialize       ////////////////////////////////
///////////////////////////////////////////////////////////////////////
offset=&gps;
for(i=offset;i<offset+sizeof(gps);i++)*i=0x00;// clear output
gps.xte_status='X';            // no valid data yet
gps.bwc_status='X';
gps.gll_status='X';

last_read_ptr=sizeof(gps_buff); // force rollover on first read
next_gps_ptr=0;


for(i=0;i<5;i++){
                output_low(LED1); // turn on
                output_low(LED2); // turn on
                delay_ms(200);
                output_high(LED1); // turn off
                output_high(LED2); // turn off
                delay_ms(200);
                }
Guest








PostPosted: Sat Mar 11, 2006 4:16 am     Reply with quote

Thanks for all the help. I've been trying out new codes before logging on and the results look quite promising. I'll probably just stick to those and try to improve on them step by step. Anyway, thanks again.
darkswarm



Joined: 27 Feb 2006
Posts: 7

View user's profile Send private message

PostPosted: Sat Mar 11, 2006 4:18 am     Reply with quote

Thanks for all the help. I've been trying out new codes before logging into the forum and the results look quite promising. I'll probably just stick to those and try to improve on them step by step. Anyway, thanks again.
darkswarm



Joined: 27 Feb 2006
Posts: 7

View user's profile Send private message

PostPosted: Mon Mar 13, 2006 2:08 am     Reply with quote

Hi,

I've added a few lines of codes to the program i posted last time n results have been encouraging. This is what i get to see on Hyperterminal.

Code:
Latitude:30
$GPGGA,
Longitude:,,,,0,00,,,,

Latitude:0257.8069,N
Longitude:10143.5982,E

Latitude:0257.8065,N
Longitude:10143.5980,E

Latitude:0257.8070,N
Longitude:10143.5979,E

Latitude:0257.8082,N
Longitude:10143.5979,E


It is only the first latitude and longitude that seem out of place. Other than that, this result is basically what i want. How do i modify the code further so that i can eliminate all that that is not needed?

Code:
#include <16F876A.h>
#use delay(clock=20000000)
#fuses NOWDT,HS, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GPS,errors)//data from GPS to PIC
#use rs232(baud=4800,parity=N,xmit=PIN_C5,rcv=PIN_C4,bits=8,stream=PC,errors)// data from PIC to PC
#byte portc=7

char c;
char buffer[71];
unsigned int8 i;

void main() {
set_tris_c(0x90);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);

setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
do{
   while ( fgetc(GPS) != 36 )   //wait for $
   for (i=0;i<7;i++)
       {buffer[i]=fgetc(GPS);
  }while (buffer[6]==',');     //GPGGA,,

for (i=0; i<=70; i++)
{
   c = fgetc(GPS);
   buffer[i] = c;
}

fprintf(PC,"\n\n\rLatitude:");   
for (i = 16; i <=26; i++)
{
   fprintf(PC,"%C",buffer[i]);  // bits 16 to 26 correspond to the latitude
}

fprintf(PC,"\n\rLongitude:");
for (i = 28; i <=39; i++)
{
fprintf(PC,"%C",buffer[i]);   // bits 28 to 39 correspond to the longitude
}
}while(1);
}


Sigh, i feel so close to achieving my objective. Please do lend a hand if you can. Really appreciate the help. Thanks so much.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Mon Mar 13, 2006 5:36 am     Reply with quote

Your code synchronises to the receipt of sentences by capturing one into your buffer and then processing it . Your code contains very time intensive printf statements and there is no absolute guarantee that they will finish before the receipt of the next sentence. Your code so far is having good luck in partially working but any addition code especially printf type statements will eventually doom it.
RS232 is asynchronous and the luck you are having so far with your code is due to the GPS taking sufficient specific pause between any two sentences you are interested in. Printf statements even in an interrupt fed circular buffer will eventually doom things but only if on average they exceed the availbable time between sentences.
As to the first sentence being messed up it may be due to the fact that your code requires synchronization with an essentially asynchronous start up. Alternatively a GPS on start up ( and other times) can speak a sentence with 0 position info info since it has placed a don't use code in its status byte (" loss of signal")
Advice:
up the baud rate on th PIC to PC side to reduce the time the printf takes
Check the sentence status byte for "A" ok
look at an interrupt fed circular buffer.
darkswarm



Joined: 27 Feb 2006
Posts: 7

View user's profile Send private message

PostPosted: Tue Mar 14, 2006 10:39 pm     Reply with quote

Thanks for your suggestion. I'll certainly try it when i have the time. But now, my supervisor wants me to add a new feature in the program, which is to display the location in addition to the latitude and longitude. For example,

Latitude:0257.8069,N
Longitude:10143.5982,E
Location:College of Engineering

He doesn't really require a very accurate location, just an approximation so that he'll know which place the latitude and longitude refer to.

I tried adding a few lines of codes to the previous program, but it did not work. i guess i was naive enough to think a few lines of codes like this would work.

Code:
if ( (( buffer [i] >= 10143.5002,E) && ( buffer [i] <= 10143.6347,E)) && ((buffer [i] >= 0257.7642,N) && (buffer [i] <= 0257.8547,N)) )
           {
             fprintf ( PC, "\n\rLocation: College of Information Technology" );
           }

// If latitude and longitude is between this range, then print College of Information Technology


There were all kinds of errors when i compiled it.

How should i proceed if i hope to add this feature in the program? Please do give me some hints. Thanks again.

Best regards
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Wed Mar 15, 2006 12:58 pm     Reply with quote

I thought this was someone trying to work with a GPS as a hobby.
Sadly this looks like another homework assignment and I bought into it by suppyling sample code..I'll have to try harder to spot this going forward.

Advice
Never expect to be spoonfed
A smart person learns from his/her own errors
A wise person learns from others.
Be honest with your supervisor tell him or her you don't fully understand and are asking this board to do some of the heavy lifting for you that way it is you and not this board that gets graded.

PS.
I will always be grateful to PCMprogrammer Mark and others. A search of this board will answer 90% of questions and 100% of common pitfalls.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group