GPS in C
pilot0315            
            
                Posts: 952            
            
                    I have been trying to isolate a single gps sentance. strncmp not working.                 
                
            
pilot0315            
            
                Posts: 952            
            
Comments
https://github.com/parallaxinc/propsideworkspace/tree/master/Learn/Simple Libraries/Sensor/libgps
If you run "Libgps.c" as your main program it dumps a bunch of useful info. I simplified this and boiled it down to a single file that's easy to work with. I can post it later when I'm off work if you like.
I have been trying to use this code and took the first part from it. For some reason I can't get the strncmp to work so I can isolate just the gprmc.
for(int index = 0; index <= 6; index++); gpsraw = fdserial_rxChar(GPS); RMC[index] = gpsraw; // if(strncmp(RMC, "GPRMC", 5) == 0) print("%c",RMC[1]);Your for loop is doing nothing because it is terminated by a ";" character. Also, you need to use braces if you want to execute more than one statement in the for loop. So I think what you what is something like this:for(int index = 0; index <= 6; index++) { gpsraw = fdserial_rxChar(GPS); RMC[index] = gpsraw; } if(strncmp(RMC, "GPRMC", 5) == 0) print("%c",RMC[1]);The loop does not parse out the characters into the sucessive elements of RMC[index]. It stuffs the entire sentance into element RMC[0].
When I run the if statement nothing shows on the screen.
When I // the if statement it displays all of the sentances.
I also referenced the same code that was suggested during this process.
I used the following snip from Daniel's code who wrote it for the PAM-7Q GPS Module. I modified the variables to the names that I am using and it does not work as well.
//read in characters from the GPS
idx = 0;
do
{
ch = fdserial_rxChar(gps_ser);
inBuff[idx++] = ch;
}while(ch != 13);
inBuff[idx] = 0; //null terminate
//got the full sentence, do a little prep work to get ready for parsing.
//modifies inBuff!
PrepBuff();
if(strncmp(inBuff, "GPRMC", 5) == 0)
ParseRMC();
if(strncmp(inBuff, "GPGGA", 5) == 0)
ParseGGA();
}
{
for(int index = 0; index <= 6; index++);
{
gpsraw = fdserial_rxChar(GPS);
RMC[index] = gpsraw;
// pause(250);
}
// if(strncmp(RMC, "GPRMC", 5) == 0)
print("%c",RMC[0]);
}
void getdata2()
{
//read in characters from the GPS
int idx = 0;
do
{
gpsraw = fdserial_rxChar(GPS);
RMC[idx++] = gpsraw;
}while(gpsraw != 13);
RMC[idx] = 0; //null terminate
//got the full sentence, do a little prep work to get ready for parsing.
//modifies inBuff!
// PrepBuff();
if(strncmp(RMC, "GPRMC", 5) == 0)
print_data();
if(strncmp(RMC, "GPGGA", 5) == 0)
print_data();
}
print("%c",RMC[0]);will only print the single character contained in RMC[0]. If you want to print the 7 characters in RMC[0] to RMC[6] you need to change this toprint("%c",RMC[index]);/* Blank Simple Project.c http://learn.parallax.com/propeller-c-tutorials */ #undef DEBUG #ifdef DEBUG #include <stdio.h> #include <stdlib.h> #include <string.h> #define print printf #else #include "simpletools.h" // Include simple tools #include "fdserial.h" #endif char RMC[80]; //gps string char gpsraw; void getdata(); //receive data from gps void getdata2(); //receive data from gps void print_data(); void init(); int index; char rmc_test[6] = {"x"}; #ifdef DEBUG #define fdserial_rxChar(x) getchar() #else int rx_pin = 26; int tx_pin = 27; int mode_ = 0; int Baud_rate = 9600; fdserial *GPS; //MASK FOR THE FDSERIAL INPUT #endif int main() // Main function { init(); while(1) { // getdata(); getdata2(); // print_data(); } } void init() { #ifndef DEBUG GPS = fdserial_open(rx_pin,tx_pin,mode_ ,Baud_rate); #endif } void getdata() { for(int index = 0; index <= 6; index++) { gpsraw = fdserial_rxChar(GPS); RMC[index] = gpsraw; // pause(250); } // if(strncmp(RMC, "GPRMC", 5) == 0) print("%c",RMC[0]); } void getdata2() { //read in characters from the GPS int idx = 0; do { gpsraw = fdserial_rxChar(GPS); RMC[idx++] = gpsraw; } while(gpsraw != 13 && gpsraw != 10); RMC[idx] = 0; //null terminate printf("RMC = %s\n", RMC); //got the full sentence, do a little prep work to get ready for parsing. //modifies inBuff! // PrepBuff(); if(strncmp(RMC, "GPRMC", 5) == 0) print_data(); if(strncmp(RMC, "GPGGA", 5) == 0) print_data(); } void print_data() { for(int index = 0; index <= 6; index++) print("%c",RMC[index]); }I wrote this not long ago as test code for the PAM-7Q GPS module that Parallax sells. It should work for others, but it hasn't been tested on anything but that hardware.
The code skips all input until it finds a '$' character, then looks for a 'G'. If it doesn't find one, it goes back to waiting for the '$'.
After finding the $G sequence, it grabs the next four characters and compares them against 'PRMC' or 'PGGA' - (meaning it's found either a $GPRMC or $GPGGA string). If either of those are found, the appropriate parsing function is called.
I don't use the standard string library stuff because I was trying to keep the compiled size down, and the code ends up being quite readable this way. I was looking for very specific values in the strings, like lat & long, sat count, and so on.
I have been struggling to get the data to go from a buffer to an array. The array does not work. I will upload another bit of code tomorrow and explain the problem.
I did this in spin without a problem.
If I don't put the semicolon after the for loop statement nothing works.
I can't just print out just a single selected setance instead of all of the sentances. It still appears that in my code the string does not get "tokenized" into the selected array via the buffer
Thanks for the help though.
Since the array starts with the Dollar sign it will not match.
This will work though: "strncmp(RMC, "$GPRMC", 6)"
Mike
Added "$" to the string. Thanks to all of you
Are you still missing the $ at the beginning of the string? The data in RMC starts with a $ character, so you'd need to change your code that looks for the 5 characters "GPRMC" to look for the 6 characters "$GPRMC".
Thanks to all
#define is used to define a symbol, that can be used to replace code or provide a compile-time flag for conditional compilation.
#undef undefines a symbol.
#ifdef tests whether a symbol has been define, and will include the following lines.
#endif terminates an #ifdef section.
#else can be used within an #ifdef section to include text when the #ifdef test fails.
In fact, because the top of his code specifically does this:
#undef DEBUG // forcibly un-define the DEBUG symbol if it's defined elsewhere
...the other code is only going to compile the "DEBUG not defined" parts.
For example,
So, since his code specifically un-defines that symbol, it's only going to use the 2nd part (simpletools and fdserial) and not the first part (stdio, stdlib, etc).
Slightly more detail:
All the lines that start with # are pre-processor commands (directives). The pre-processor does a rough parse of the source file looking for these. Directives can do things like text-based substitutions, #include a whole other file, or remove chunks of your code. The result is just a text file, and that is what's passed to the actual compiler.
If you #define something, you can use it as a text-swapper in your code:
#define BOO print("This is what gets substituted.") void main(void) { BOO ; }That code would actually compile. The #define tells the pre-processor to look for instances of the text "BOO" and substitute the other text (the print command). They're often referred to as macros, and should be used sparingly . They're generally not type-safe and can be hard to debug.
In Dave's code, they're used more appropriately to control the code. You'll occasionally see stuff in multi-platform code that looks like:
#ifdef WINDOWS FileHandle = WinCreateFile("filename" .. . . ); #endif #ifdef OSX FileHandle = OsxOpenFile("filename" .. . . ); #endifIt's usually done slightly differently, but it gets the point across. To compile on one platform or another, you just #define the platform value, and compilers often have things like that built in.