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.
Thanks.
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.
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:
When it comes to community support on customer code, you forum members rock! Thanks Jason and Dave. This is an issue Tech Support could not offer assistance with. :chip:
Thanks for the attempt to help.
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();
Here is the snibbet with the code written by Daniel. It does not run with the if statements and without all I get is a single random character then line feed. No isolated sentances. I am just trying to at first isolate the GPRMC sentance then struggle with the rest. Thanks to everybody. This C language is a pain to learn.
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();
As I said before, the semicolon at the end of the for statement causes the for loop to do nothing. A semicolon by itself if a null statement. Remove the semicolon at the end of the for statement. In other words, do this
for(int index = 0; index <= 6; index++)
and not this
for(int index = 0; index <= 6; index++) ;
Another thing is that the "%c" format string causes a single ASCII character to be printed. So the statement
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 to
I did that and it does not work . it dumps into [0], nothing in [1], or any of the others. if I index it and attempt to print a selected cell of the array nothing is there
pilot0315, try the following code and see if it works. If you define DEBUG at the beginning of the file you can type in test strings from the console to see what happens. Note, I changed the test for 13 to also test for 10 in case a linefeed is sent instead of a carriage return. I tested it with DEBUG defined, and it works as expected.
/*
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]);
}
This doesn't fix your existing code, but shows a different approach to handling the GPS data.
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.
Yes I did it works but I am still having the problem of isolating only the gprmc sentance. Your code puts out the same thing that my code puts out.
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
The strncmp(array, findarray, number) is only looking at the first 5 characters in the array.
Since the array starts with the Dollar sign it will not match.
This will work though: "strncmp(RMC, "$GPRMC", 6)"
I have tried 5, 6 and many other combinations. and it strncmp does ot work.
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".
Hey Dave, can you give me an explanation of all of these preprocessor directives. I thank you for uour help. I am gonna print this and try to follow the preprocessor stuff as I am new in C. This has been a good lesson.
Thanks to all
The preprocessor directives I used in my code were #include, #define, #undef, #ifdef, #else and #endif. You are probably familiar with #include, which is used to include the text from another file. This is normally used with header files with the .h extension.
#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 Dave's specific case, he's checking to see if the symbol "DEBUG" is defined, and altering the code that gets compiled based on that.
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,
#ifdef DEBUG // this part is compiled if the symbol "DEBUG" is defined
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define print printf
#else // this part is compiled if "DEBUG" is NOT defined
#include "simpletools.h" // Include simple tools
#include "fdserial.h"
#endif
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).
C/C++ is powerful, but it can be a pain in the butt for a beginner. Happy to help.
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:
It'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.
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.
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();
}
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:
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:
It'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.