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

Problem with GPS parsing

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
analog_world



Joined: 16 Sep 2008
Posts: 26

View user's profile Send private message

Problem with GPS parsing
PostPosted: Fri Sep 26, 2008 1:31 pm     Reply with quote

I have written this sample code to read in gps data and parse it. However, since I do not have a GPS yet, I did not include any code to take in data from the USART. So, I just created my own array of sample gps strings that will be parsed. When I compiled the file for pic 16f877a, it gives me an error saying "not enough ram for variables". I am confused as to how can I make this program more effective. Also, how can I view my results in CCS PIC (for ex: the conventional C compiler have an output window to view results instantaneously. Does CCS C have any capability to view the results on a window immediately). I would really appreciate help with this. Here is the code I wrote.

Code:

  #include <assert.h>
  #include <float.h>
  #include <math.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdlibm.h>
  #include <string.h>

typedef struct _GPRMC
{
   char validity;
   float latitude;
   char latitudeDir;
   float longitude;
   char longitudeDir;
} GPRMC;

int hex2dec(char c);
int readGpsStr();
int parseGPRMC(char* inGpsStr, GPRMC* gprmc);

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

#define TEST_MODE 1

#ifdef TEST_MODE

char* inGpsStrArray[] =
{
"$GPZDA,033243.841,08,09,2008,00,00*55",
"$GPGGA,033243.841,0000.000000,N,00000.000000,E,1,0,0,0,M,0,M,,*4A",
"$GPGLL,0000.000000,N,00000.000000,E,033243.841,A,A*51",
"$GPVTG,0,T,0,M,0,N,0,K,A*23",
"$GPRMC,033243.841,A,0000.000000,N,00000.000000,E,0,0,080908,0,E,A*1A",
"$GPGSA,A,3,,,,,,,,,,,,,0,0,0*2C",
"$GPRTE,1,1,C,0,*0B",
""
};

int8 inGpsStrArrayIndex = 0;

#endif

int main()
{

setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   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);

   while (inGpsStrArrayIndex > 0)
      readGpsStr();

   return 0;
}

char* getStr(char* inGpsStr, int len)
{
#ifdef TEST_MODE
   inGpsStr = inGpsStrArray[inGpsStrArrayIndex];
   ++inGpsStrArrayIndex;
   if ((inGpsStrArray[inGpsStrArrayIndex])[0] == '\0')
      inGpsStrArrayIndex = -1;
#else
   gets(inGpsStr);
#endif
   return inGpsStr;
}

int hex2dec(char c)
{
   if (c >= '0' && c <= '9')
      return c - '0';

   if (c >= 'A' && c <= 'F')
      return 10 + (c - 'A');

   
   if (c >= 'a' && c <= 'f')
      return 10 + (c - 'a');

   return -1;
}

int verifyChecksum(char* str)
{
   int calcChecksum = 0;
   int readChecksum  = 0;
   int i, c1, c2;
   for (i = 1; str[i] != '\0'; ++i)
   {
      if (str[i] == '*')
         break;

       calcChecksum ^= str[i];
   }

   if (str[i+1] == '\0' || str[i+2] == '\0')
      return FALSE;

   c1 = hex2dec(str[i+1]);
   c2 = hex2dec(str[i+2]);
   if (c1 == -1 || c2 == -1)
      return FALSE;

   readChecksum = (c1 << 4) + c2;
   if (calcChecksum != readChecksum)
   {
      printf("checksum failed for %s\n", str);
   }
   else
   {
      printf("checksum is valid: %x\n", readChecksum);
   }

   return TRUE;
}

int readGpsStr()
{
   char inGpsStr[100];
   char tmpGpsStr[sizeof(inGpsStr)];
   char* tmpGpsStrPtr = NULL;
   char* nextToken;
   GPRMC gprmc;
   int result;
   char* delimitter = ",";
   
   while (1)
   {
      tmpGpsStrPtr = getStr(tmpGpsStr, sizeof(tmpGpsStr));

      if (tmpGpsStrPtr == NULL)
         continue;

      // Save the read string as strtok modifies tmpGpsStr
      strcpy(inGpsStr, tmpGpsStr);

      printf("Read: %s", inGpsStr);

      /*
         * $GPRMC,033244.885,A,0000.016667,N,00000.016667,E,0,0,080908,0,E,A*15
         */
      nextToken = strtok(tmpGpsStr, delimitter);
      if (nextToken == NULL)
         continue;

      if (strcmp(nextToken, (char*)"$GPRMC") == 0)
      {
           if (!verifyChecksum(inGpsStr))
              continue;
         
         result = parseGPRMC(inGpsStr, &gprmc);
         
         if (result == FALSE)
            continue;
         
         printf("%c,%f,%c,%f,%c\n", gprmc.validity, gprmc.latitude,
            gprmc.latitudeDir,gprmc.longitude, gprmc.longitudeDir);

         return TRUE;
      }

      if (strcmp(nextToken, (char*)"$GPGLL") == 0)
      {
         continue;
      }
   }
}

int parseGPRMC(char* inGpsStr, GPRMC* gprmc)
{
   /*
         * $GPRMC,033244.885,A,0000.016667,N,00000.016667,E,0,0,080908,0,E,A*15
   */

   char* nextToken;

   // time
   nextToken = strtok(NULL, (char*)",");
   if (nextToken == NULL)
      return FALSE;

   // A
   nextToken = strtok(NULL, (char*)",");
   if (nextToken == NULL)
      return FALSE;
   
   if (strcmp(nextToken, (char*)"A") != 0)
      return FALSE;
   gprmc->validity = nextToken[0];

    nextToken = strtok(NULL, (char*)",");
   if (nextToken == NULL)
      return FALSE;
   gprmc->latitude = (float)atof(nextToken);

    nextToken = strtok(NULL, (char*)",");
   if (nextToken == NULL)
      return FALSE;
   gprmc->latitudeDir = nextToken[0];

    nextToken = strtok(NULL, (char*)",");
   if (nextToken == NULL)
      return FALSE;
   gprmc->longitude = (float)atof(nextToken);

    nextToken = strtok(NULL, (char*)",");
   if (nextToken == NULL)
      return FALSE;
   gprmc->longitudeDir = nextToken[0];

    nextToken = strtok(NULL, (char*)"*");

   return TRUE;

}


Last edited by analog_world on Tue Oct 21, 2008 2:15 am; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 26, 2008 2:05 pm     Reply with quote

The largest RAM array size for that PIC is 96 bytes.
I suggest that you make one small GPS string for your tests.
See if you can parse that one string.

Also, I assume you've got the #device *=16 statement in your program,
which allows the use of all RAM in the 16F series PICs. Example:
Quote:
#include <16F877A.H>
#device *=16
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
analog_world



Joined: 16 Sep 2008
Posts: 26

View user's profile Send private message

PostPosted: Fri Sep 26, 2008 2:24 pm     Reply with quote

Hi,
that was helpful. I can compile, but how do I know if it is parsing it right. I was wondering how can I view if the variables are correctly storing the parsed values. Also, when I am reading in GPS data, How is that data stored in the PIC to be read by my program. Since the GPS will be refreshing constantly every second, should it be read as strings or characters. And Where is the location that I need to read these strings or characters from. (The GPS is connected to the serial USART port)
Thank you so much for your help.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 26, 2008 2:50 pm     Reply with quote

If you're parsing the sub-strings into smaller arrays, you can use
printf to display the smaller strings.

You should do a search for GPS code on this forum.
Use this search string:
Quote:
NMEA OR GPS

That will find most of the code examples.

http://www.ccsinfo.com/forum/search.php
analog_world



Joined: 16 Sep 2008
Posts: 26

View user's profile Send private message

PostPosted: Fri Sep 26, 2008 3:00 pm     Reply with quote

Thank you so much for your help. I am indeed using Printf to display the parsed string and the individual components extracted such as lat, long..etc. My only question was how can I view this output? Confused Because since the program compiles, where is the option in CCS to view the output of printf. Thank you.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 26, 2008 3:18 pm     Reply with quote

Are you running this program on a board ? If so, connect the RS-232
output to the COM port on the back of your PC. Then view it on a
terminal program, such as HyperTerminal or SIOW (the CCS terminal
program).
analog_world



Joined: 16 Sep 2008
Posts: 26

View user's profile Send private message

PostPosted: Fri Oct 03, 2008 12:25 am     Reply with quote

Hi,
When I used the above program with the 18F4550, it compiled. I did use your suggestion of reducing the array size by just using one string. However, the size of my hex file was 16KB!!!. I guess the only reason the program compiled was because of the generous memory on the 18 series. When I tried recompiling using the 16F877A, it still keeps telling me that there isn't enough RAM for variables. Do you think this is because I am using the String functions such as Strtok. I do not see why it is not working. Do you think I should just write my own string functions instead of linking the C libraries as it would link all the functions of the string library thereby consuming too much memory. Or am I just doing it wrong. I really appreciate help with this. Thank you.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Oct 03, 2008 1:13 am     Reply with quote

The 18F4550 has over 5x more RAM than the 16F877A. Also, the
16F PIC has its RAM segmented into pages. An array can't be larger
than the size of one page. This will be 96 bytes or less. For large
projects, it's recommended that you use the 18F PICs. Then you don't
have these limitations.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri Oct 03, 2008 8:30 am     Reply with quote

If you don't have a GPS receiver to play with yet you can simply have a PIC transmit a few sentences each second to similate a receiver. Your receiving PIC could try to massage the data coming in and you could sort of debug your code that way.

Ronald
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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