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 support@ccsinfo.com

GPS code help, PIC 16F877A
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
talhahs



Joined: 14 Oct 2010
Posts: 14

View user's profile Send private message

GPS code help, PIC 16F877A
PostPosted: Mon Mar 07, 2011 9:09 am     Reply with quote

Hi guys,

I have a Garmin consumer GPS that works at a baud rate of 4800 bps. There is no problem in getting the sentences when running on hyperterminal, PC<>GPS; But when i try to recive them using controller i just get garbage serial characters.

Since it is a consumer GPS that connects directly to PC (works on RS-232 levels), i have used MAX 232 (fully functional) to connect HW USART to GPS.

Here is the code i am using, kindly help.

Code:


#include "D:\GPS\gps.h"
#include <stdlib.h>

#include <16F877A.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(clock=20000000)
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GPS)  //hardware USART
#use rs232(baud=4800,parity=N,xmit=PIN_D6,rcv=PIN_D7,bits=8,invert,stream=PC) //software USART

void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   

output_high(PIN_B7);  //flag LED


   char gps_str[60];  //full sentence
   char temp_str[10];
   char lat_float[10];
   char log_float[10];
   char alt_float[10];
   char rcv_chr;
   int count;
   
   
  fprintf(PC,"GPS code about to start::: \r\n");
                           
         
 if(kbhit(GPS))
   rcv_chr=fgetc(GPS);
   if (rcv_chr=='$'){
      rcv_chr=fgetc(GPS);
      if (rcv_chr=='G'){
         rcv_chr=fgetc(GPS);
         if (rcv_chr=='P'){
            rcv_chr=fgetc(GPS);
            if (rcv_chr=='G'){
               rcv_chr=fgetc(GPS);
               if (rcv_chr=='G'){
                  rcv_chr=fgetc(GPS);
                  if (rcv_chr=='A'){
                     rcv_chr=fgetc(GPS);
                        if (rcv_chr==','){
                           for (count=0;count<60;count++){
                              gps_str[count]=fgetc(GPS);
                              }
                              output_high(PIN_B7);
                             
                           for (count=0;count<7;count++){
                              temp_str[count]=gps_str[13+count];
                              }
                              lat_float=atof(temp_str);

                           for (count=0;count<7;count++){
                              temp_str[count]=gps_str[26+count];
                              }
                              log_float=atof(temp_str);

                           for (count=0;count<7;count++){
                              temp_str[count]=gps_str[45+count];
                              }
                              alt_float=atof(temp_str);
                           
                           }
                        }
                     }
                  }
               }
            }
         }
         fprintf(PC,"Latitude , = ");
         for (count=0;count<10;count++){
                              fprintf(PC,lat_float[count]);
                              }
                             
                              fprintf(PC,"\r\n");
         
         fprintf(PC,"Longitutde , = ");
         for (count=0;count<10;count++){
                              fprintf(PC,log_float[count]);
                              }
                             
                              fprintf(PC,"\r\n");
                             
         fprintf(PC,"Altitude , = ");
         
         for (count=0;count<10;count++){
                              fprintf(PC, alt_float[count]);
                              }
                             
                 
         
      }
 
       
Ttelmah



Joined: 11 Mar 2010
Posts: 19327

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 9:26 am     Reply with quote

So describe your connection to the PC from the PIC?. Just using 'invert', is not enough, though _may_ just about give a useable connection, to send data, depending on the buffering on the PC...

Some further comments:
1) Add 'ERRORS' to your GPS stream definition. Since you have long periods when the RS232 won't be receiving (when it is calculating, and sending data to the PC), without this, the UART _will_ get hung.
2) Change the setup_spi definition, to setup_spe(FALSE). SPI_SS_DISABLED, actually enables the port.....
3) Switch to defining your variables at the start of the code blocks. This is a _requirement_ in standard C, and though CCS, partially accepts the C++ layout with variables inline, it also leads to code errors, which can be a pig to track down. Keep to the standard syntax to avoid this.
4) Think about your code. There is nothing to say that the 'sentence is about to start'. Depending on how long the PIC takes to get to the first kbhit, you could be 'mid sentence'. You check for the '$', but should really keep looking till you find this. You also need to null terminate the strings before you call atof.

Best Wishes
talhahs



Joined: 14 Oct 2010
Posts: 14

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 9:30 am     Reply with quote

these are the sentences GPS sends every second or so. (all at once)

$GPRMC,,V,,,,,,,061210,0.0,E,N*3C
$GPRMB,V,,,,,,,,,,,,A,N*13
$GPGGA,121505,2485801,N,06726585,E,1,08,0,9,133.4,M,46.9,M,,*42
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGSV,3,1,12,02,08,067,00,05,37,039,00,12,28,178,00,15,28,143,00*77
$GPGLL,,,,,,V,N*64
$GPBOD,,T,,M,,*47
$GPVTG,,T,,M,,N,,K*4E
$PGRME,,M,,M,,M*00
$PGRMZ,,f,1*29
$PGRMM,Dutch*27
$GPRTE,1,1,c,*37
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 12:24 pm     Reply with quote

Hi,

A couple of additional thoughts.

You might review which NMEA messages contain the data you actually want/need, and then turn all the other messages off. Most GPS receives can be configured to send only the data you want. This will help to free machine cycles for processing the data you want.

Realistically, you may only be happy with what you are trying to do once you implement an interrupt driven serial buffering scheme using a circular buffer. Believe me that I worked mightily to avoid using this technique (believing that the implementation was difficult) before succumbing, and just doing it. With this technique, each time a new character is received from the GPS, it's stuffed into a circular buffer (a buffer that "wraps around" when reaching the end). This happens automatically, leaving your main program to process the buffer contents. You simply need to look for the start character ('$'), and the end character ('CR'), and process everything in the middle. You can further refine your interrupt handler with a state machine to only buffer characters associated with the desired NMEA strings.

The example program EX_SISR.c will get you started on this technique.

John
talhahs



Joined: 14 Oct 2010
Posts: 14

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 1:48 pm     Reply with quote

Thanks guys

Well, John you are right, I would ultimately have to move to implementing interrupts. This is because I am building code for rover that moves in all directions, rotates camera using servo and GPS is just part of it. I cant hang my control waiting for GPS sentences. Therefore, using interrrupt #int_rda is a good idea.

Secondly my Garmin etrex GPS doesn't provide option to send only GPGGA sentence, it sends all NMEA sentences mentioned above at once. What i can do is to shift to some easier protocol that this GPS is offering like simple text for latitude and longitude only.

Have you got any idea how do i extract required GPGGA from others when they are placed in circular queue as in EX_SISR.c
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 2:05 pm     Reply with quote

Hi,

You might want to consider using a GPS "engine", rather than the eTrex unit. A number of good modules can be found at Sparkfun.com for around $50 USD. These modules typically have TTL interfaces, and the NMEA data stream can be configured.......

To exclude all but the desired string from your circular buffer, you can implement a "state machine" in your serial interrupt handler. It starts with a State = 0, and stores no characters in this state. Once the '$' character is received, this character is stored, and then State is incremented. With State = 1, the next character must be a 'G', and if so, the character is stored, and the state is incremented. With State = 2, the next character must be a 'P', and if so, the character is stored, and the state is incremented. If at anytime, you don't have a match, reset State = 0. Keep doing this until you have enough of the NMEA string to ensure you've got the correct one. At that State value, just store all the incoming characters until the 'CR' character is received, and then start all over.

You'll learn a lot more if you code it yourself, but here is a small code fragment from my ISR to get you going:



Code:

   TempChar = fgetc(GPS);
   
   switch (RxState)
   {
      Case 0:
         if (TempChar == '$')
            RxState++;   //"$" received, so RxState = 1
         break;

      Case 1:
         if (TempChar == 'G')
            RxState++;   //"G" received, so RxState = 2
         else
            RxState=0;   //wrong character received, so we reset RxState
         break;





John
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 6:53 pm     Reply with quote

Oh gosh - yes. ISR is a must. I've done several GPS projects now and I can't emphasize enough...

Using an ISR to collect the serial stream is the way to go.

If all you have is the eTrex, then have at it - I don't think you NEED to go out and buy a specific GPS if the one you have puts out NMEA.

So far, I've coded against the following models:

Garmin GPS16/17
Garmin GPS296
DeLorme GPS2058

No problems.

The config strings might be different.. but the rest is the same.

Cheers,

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 7:50 pm     Reply with quote

Hi Ben,

Was the project using the GPS296 aviation related??

John
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 7:56 pm     Reply with quote

ezflyr wrote:
Hi Ben,

Was the project using the GPS296 aviation related??


Yes -- Why?
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 8:09 pm     Reply with quote

Ben,

Oh, I'm a pilot and aviation junkie and your reference to the GPS296 caught my eye.

What was the project?

John
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 8:15 pm     Reply with quote

ezflyr wrote:
Ben,

Oh, I'm a pilot and aviation junkie and your reference to the GPS296 caught my eye.

What was the project?


I wanted to make an auxilary display for some of the NMEA information that spews out of the 296.

I'm also a pilot. It's for my Grumman AA1B...

I need to finish putting it in a case and install it... When I have something to show for, I'll post pictures of what it is and what it does.

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Mar 07, 2011 8:22 pm     Reply with quote

Hi Ben,

Great stuff, I'm definitely interested!

I fly a Beech A-36 Bonanza, but my GPS project is for my other passion, R/C modeling. I'm making an airborne telemetry and autonomous control system for one of my models.

John
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Tue Mar 08, 2011 12:54 am     Reply with quote

ezflyr wrote:
Hi Ben,

Great stuff, I'm definitely interested!

I fly a Beech A-36 Bonanza, but my GPS project is for my other passion, R/C modeling. I'm making an airborne telemetry and autonomous control system for one of my models.


I'll keep you posted when it's finally complete...

A-36 -- fun! I've been in those... Especially the drop-down speed brakes. ;)

However, the AA-1's with o320's are hard to beat on the cheap vs. fun factor. If I had all the cash in the world, I'd still fly an AA-1. They're a blast.

Cheers,

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
talhahs



Joined: 14 Oct 2010
Posts: 14

View user's profile Send private message

PostPosted: Tue Mar 08, 2011 8:23 am     Reply with quote

Ben and John,

Kindly be informed this forum is not for your supersonic aircrafts discussion, I started this thread for my surveillance rover GPS Very Happy Very Happy Very Happy

http://www.lynxmotion.com/c-111-no-electronics-kit.aspx

Well, one question has sprung up in my mind.

The rover performs differential drive in real time as instructed my VB application.

so the code is of this type

Code:


#define H bridge pins



void forward(int speed)
{
   code;
}

void backward(int speed)
{
   code;
}

void left(int speed)
{
  code;

void right(int speed)
{
   code;
}

void reset()
{
   code;
}

void main()
{

 char cmd;


do{
  if(kbhit())
{    cmd=getch();
        output_high(LED);
   
      switch (cmd)
      {
         case 'q':         //backward 100% speed
            code;
                     
         break;

         case 'w':         //backward 75% speed
            code;
                     
         break;

         case 'e':         //backward 50% speed
            code;
                     
         break;

         case 'r':         //backward 25% speed
           code;
                     
         break;

         case 't':         //backward low speed
           code;
                     
         break;
           
         case 'z':         //forward 100% speed
            code;
                     
         break;
.
.
.
.
.
        code continues;
.
.
.
.

       
}
output_low(LED2);

} while(1) ;
}




So, in this sort of code when I have to integrate GPS, the MCU might be busy getting GPS sentences via interrupt, while the user might be pressing keys for the rover to move, the MCU control wont be in switch case statement, so how can GPS be integrated?.. Kindly guide me..
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Tue Mar 08, 2011 9:32 am     Reply with quote

Hi talhahs,

Yeah, sorry for the "off frequency" chatter, I guess I got carried away Very Happy!

I think you need to take a step-by-step approach to this project rather than jumping ahead. You are right, integrating other tasks into your code will be a challenge, and it's good to consider everything from the outset, but I think your 1st priority should be to establish rock solid reception from your GPS.

Is this going to be an autonomous robot, or one that is remote controlled? If it's remotely controlled, what is the purpose of the GPS?

If you plan to integrate something like an Xbee module for command/control, you'll have to use a 2nd serial port. If the data packets are small, and (relatively) infrequent, you can probably get away with using a software serial port for this purpose. I'd connect it to input B0 and use the INT_EXT interrupt. As always the devil is in the details of your project!

John
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