Need some programming help, incorporating .cpp files

08 May 2013

I need some help here. I have been struggling with NMEA parsing for my GPS project. I have a Venus 6 GPS running 10Hz from Sparkfun. I can easily pull the data string over the serial connection. All is good as long as I pull the gps data and send it to the hyperterminal through the PC connection.

I have an example parsing program that comes from the cookbook that has a gps.h and data.h. The gps.h has a "getstring" function that works. The 'getstring" then calls on the different parsing subroutines and identifies a GGA, RMC, etc string to divide up.

I assign a variable to each term in the string using a comma separated tag to get Longitude, Latitude, etc.

Here is my problem.

I can locally print the variables using a device.printf() function as long as the print function is in the gps.h file. Even if I define the variables to be global I get garbage out if I move the device.printf() function to the main.cpp. I can not figure out how to deal with the variables outside this header file.

I have 4 other peripheral devices running in main. I just want to collect the variables and then dump them to an SD card. I do not want multiple open/write/close steps as it really slows down the data rate.

Any suggestions? I will see if I can clean up and post some example code.

09 May 2013

Hard to tell what the problem is if we can't see what your doing in the header file or in the main.cpp file.

13 May 2013

OK,

Here is a description of the code.

I call a function (gpsgetstring). This searches the NMEA output and looks for the call signs (RMS, GGA, etc). When it finds these it then calls the particular parsing function for that string. The code is working.

However, I can define a variable in gps.h and use it right there. Meaning, I can print the value but the value is not stored even though I think I am assigning it as a global variable.

I want to be able to print to an LCD and write all the variables to an SD card in my main.cpp. the commented out strings return gibberish if I print as a string, int, char, etc but work perfectly in the parse_rmc() section.

here is the code. I appreciate any help.

my main.

#include "mbed.h"
#include "gps.h"
#include "data.h"
#include "TextLCD.h"
//#include "cnmea0183.h"
//#include "cnmea0183.cpp"

//Serial port pin assignment and setup
//Serial gps(p9, p10);  // tx, rx//Creates a variable for serial comunication through pin 28 and 27
//LCD 2x20 parallel code pin assignment
//TextLCD lcd(p21, p22, p23, p24, p25, p26, p30, 20, 2); // (rs, rw, e, d0, d1, d2, d3, n_column, n_rows)
//Serial pc(USBTX, USBRX); //define USB connection pins



/**********************************************/
int column;
int row;
int i;
char c;


int main()
{
    //pc.printf("Ready");
    pc.baud(115200);
    gps.baud(115200);
    pc.printf("Ready\r\n");
    wait(1);
    
    while(1) {



        getGPSstring(1);
//       lcd.locate(0,3);
//       lcd.printf("Lat=%6.4i", Lat1);
//       lcd.locate(0,1);
//       lcd.printf("Long=%i%i", Long, Long_h);


//query software baud Rate


        //pc.putc(gps.getc());
        // wait(2);
    }
}

gps.h - Here I have commented out many print functions and am only calling the RMC string for basic Lat/Long and speed.

#include "mbed.h"
#include "TextLCD.h"
#include "data.h"



Serial pc(USBTX, USBRX);
Serial gps(p9, p10);
TextLCD lcd(p21, p22, p23, p24, p25, p26, p30, 20 ,2);


int parseGSV()
{
    gsv2 = strtok(gsv1, ",");
    while (gsv2 != NULL) {
        sep++;
        switch (sep) {
            case 1:
                // # of sentences
                //    pc.printf("#:%s ",gsv2);
                break;
            case 2 :
                // Sentence # of #
                //    pc.printf("S#:%s",gsv2);
                break;
            case 3 :
                // Number of Satellites in view (Should give a hint as to how many cases to expect here...
                //   pc.printf("#:%s ",gsv2);
                break;
            case 4 :
                // Satellite PRN Number
                //  pc.printf("PRN#:%s   ",gsv2);
                break;
            case 5 :
                // Elevation in Degrees
                break;
            case 6:
                // Azimuth in Degrees
                break;
            case 7:
                // SNR - up to 4 satellites per sentence
                break;
        }
        gsv2 = strtok(NULL, ",");
    }
    sep = 0;
    return *gsv2;
}

int parseGSA()
{

    return 0;
}

int parseRMC()
{
    rmc2 = strtok(rmc1, ",");
    while (rmc2 != NULL) {
        sep++;
        switch (sep) {
            case 1:
                // Time
                timeGPS = rmc2;
                //pc.printf("Time:%s ,",timeGPS);//UTC time
                lcd.locate (0,0);
                lcd.printf("Time:%s",timeGPS);//UTC time
                break;
            case 2 :
                // Status
                //    pc.printf("Status:%s ",rmc2);//Status
                break;
            case 3 :
                // Lattitude
                Lat = rmc2;
                            sscanf(Lat, "%c", Lat1);
//                            Lat1 = Lat1 /100;
                //pc.printf("%s,",Lat);//Lattitude
                //lcd.locate (0,10);
                lcd.locate (0,2);
                lcd.printf("Lat:%s",Lat);
                break;
            case 4 :
                // Hemisphere
                Lat_h = rmc2;
                //pc.printf("%s ,",Lat_h);//Lattitude Hemisphere
                //lcd.printf("%s",Lat_h);//Lattitude Hemisphere
                break;
            case 5 :
                // Longitude
                Long = rmc2;
                sscanf(Long, "%i", Long1);
                //Long1 = Long1 /100;
                //pc.printf("%s,",Long);//Longitude
                //lcd.locate (0,3);
                //lcd.printf("Long:%f,",Long1);//Longitude
                break;
            case 6:
                Long_h = rmc2;
                //pc.printf("%s ,",Long_h);    // Longitude Hemispere
                //lcd.printf("%s",Long_h);    // Longitude Hemispere
                break;
            case 7:
                speed_kph = rmc2;
                //speed_mph = (speed_kph * 1.15077945); //convert to mph
                //pc.printf("%s,",speed_kph); //Speed Knots
                break;
            case 8:
                heading = rmc2;
                //pc.printf("%s, ",heading);    // Heading degrees
                break;
            case 9:
                UTS_Date = rmc2;
                //pc.printf("%s,\r\n",UTS_Date); //Date
                lcd.locate(0,1);
                lcd.printf("%s",UTS_Date); //Date
//                pc.printf("%s,%s,%s,%s,%s,%s,%s\r\n",timeGPS,Lat,Lat_h,Long,Long_h,speed_kph,UTS_Date);
                break;

        }
        rmc2 = strtok(NULL, ",");
    }
    sep = 0;
    return *rmc2;
}

int parseVTG()
{
    ////Velocity made Good
    vtg2 = strtok(vtg1, ",");
    while (vtg2 != NULL) {
        sep++;
        switch (sep) {
            case 1:
                if (mode == 1) {
                    lcd.cls();
                    //  pc.printf("Course:%s\n",vtg2);//Course (deg)
                }
                break;
            case 2 :
                if (mode == 2) {
                    lcd.cls();
                    //    pc.printf("Magnetic Track:%s",vtg2);//course True (T)
                }
                break;
            case 3 :
                if (mode == 2) {
                    //   pc.printf("%s\n",vtg2);//Track True M
                    //   wait(0.25);
                }
                break;
            case 4 :
                if (mode == 2) {
                    lcd.cls();
                    //   pc.printf("Lon:%s",vtg2);//longitude
                }
                break;
            case 5 :
                if (mode == 2) {
                    //   pc.printf("Knots:%s\n",vtg2);//Speed Knots
                    wait(0.25);
                }
                break;
            case 6://GPS Quality
                if (mode == 1) {
                    lcd.cls();
                    //   pc.printf("%s\n",vtg2);//Speed Units Knots
                }
            case 7://Number of Satallites
                if (mode == 1) {
                    lcd.cls();
                    //    pc.printf("KPH:%s\n",vtg2);//Speed kPH
                }
                break;
            case 8 :
                if (mode == 2) {
                    lcd.cls();
                    //    pc.printf("%s",vtg2);//Speed Units K = Kph
                }
                break;
            case 9 :
                if (mode == 2) {
                    //    pc.printf("Alt=%s\n",vtg2);//Checksum
                    //    wait(0.25);
                }

                break;
        }
        vtg2 = strtok(NULL, ",");
    }
    sep = 0;
    return *vtg2;
}

int parseGGA()
{
    gga2 = strtok(gga1, ",");
    while (gga2 != NULL) {
        sep++;
        switch (sep) {
            case 1:
                if (mode == 1) {
                    lcd.cls();
                    //        pc.printf("Time:%s\n",gga2);//time
                }
                break;
            case 2 :
                if (mode == 2) {
                    lcd.cls();
                    //   pc.printf("Lat:%s",gga2);//lattitude
                }
                break;
            case 3 :
                if (mode == 2) {
                    //   pc.printf("%s\n",gga2);//hemisphere lattitude
                    //   wait(0.25);
                }
                break;
            case 4 :
                if (mode == 2) {
                    //    lcd.cls();
                    //   pc.printf("Lon:%s",gga2);//longitude
                }
                break;
            case 5 :
                if (mode == 2) {
                    //  pc.printf("%s\n",gga2);//hemisphere longitude
                    // wait(0.25);
                }
                break;
            case 6:                         //GPS FixQuality
                if (mode == 1) {
                    if (gga2 == "0") {
                        fix = "Invalid";
                    }
                    if (gga2 == "1") {
                        fix = "GPS Fix (SPS)";
                    }
                    if (gga2 == "2") {
                        fix = "DGPS Fix";
                    }
                    if (gga2 == "3") {
                        fix = "PPS Fix";
                    }
                    if (gga2 == "4") {
                        fix = "Real Time Kinematic";
                    }
                    if (gga2 == "5") {
                        fix = "Float RTK";
                    }
                    if (gga2 == "6") {
                        fix = "Estimated (Dead Reckoning)";
                    }
                    if (gga2 == "7") {
                        fix = "Manual Input Mode";
                    }
                    if (gga2 == "8") {
                        fix = "Simulation Mode";
                    }
                    // pc.printf("FIX: %s_%s",gga2,fix);
                }
            case 7://Number of Satallites
                if (mode == 1) {
                    lcd.cls();
                    //   pc.printf("NSat:%s\n",gga2);//Number of Sattelites
                }
                break;
            case 8 :
                if (mode == 2) {
                    lcd.cls();
                    //   pc.printf("Horiz:%s",gga2);//Horizontal dilution
                }
                break;
            case 9 :
                if (mode == 2) {
                    //    pc.printf("Alt=%s\n",gga2);//Altitude
                    wait(0.25);
                }

                break;
        }
        gga2 = strtok(NULL, ",");
    }
    sep = 0;
    return *gga2;
}

int getGPSstring(int str)
{
    if (gps.scanf("%s", &gpsString) ==1) {
        /*        if (str == 1)
                {
                    if (sscanf(gpsString, "$GPGGA,%s",gga1) >= 1)
                    {
                        sep = 0;
                        parseGGA();
                        pc.printf("Test1");//debug line
                        wait(2);//debug line
                    }
                return *gga2;
                }
                if (str == 1)
                    {
                    if (sscanf(gpsString, "$GPGSA,%s",gsa1) >= 1) {
                        sep = 0;
                        parseGSA();
                        pc.printf("Test2");//debug line
                        wait(2);//debug line
                    }
                return *gsa2;
                }
                if (str == 1)
                    {
                    if (sscanf(gpsString, "$GPGSV,%s",gsv1) >=1)
                        {
                        sep = 0;
                        parseGSV();
                        pc.printf("Test3");//debug line
                        wait(2);//debug line
                        }
                    return *gsv2;
                    }*/
        if (str == 1) {
            if (sscanf(gpsString, "$GPRMC,%s",rmc1) >= 1) {
                sep = 0;
                parseRMC();
                // pc.printf("Test4");//debug line
                // wait(2);//debug line
            }
            return *rmc2;
        }/*
               if (str == 1)
               {
            if (sscanf(gpsString, "$GPVTG,%s",vtg1) >= 1)
                    {
                    sep = 0;
                    parseVTG();
                    pc.printf("Test5");//debug line
                    wait(2);//debug line
                    }
            return *vtg2;
            }*/

    }
    return 0;
}

data.h

#ifndef _DATA_H_
#define _DATA_H_
    char gpsString[1024];
    char gsv1[1024];
    char * gsv2;
    char rmc1[1024];
    char * rmc2;
    char gga1[1024];
    char * gga2;
    char * fix;
    char vtg1[1024];
    char * vtg2;
    char gsa1[1024];
    char * gsa2;
    int sep;
    int mode = 1;
    char * Lat;
    char * Long;
    char * Lat_h;
    char * Long_h;
    char * timeGPS;
    char * speed_kph;
    char * speed_mph;
    char * heading;
    char * UTS_Date;
        char Lat1[10];
    char Long1[8];
    char Lat_h1;
    char Long_h1;
    float time_GPS1;
    float speed_k1;
    float speed_mph1;
    float heading1;



    
        
#endif
13 May 2013

The code is just written into different file types *.h vs .c which means different rules is all.

1. In your gps.h file delete ALL the #includes and the objects shown below:

// delete all these
#include "mbed.h"
#include "TextLCD.h"
#include "data.h" 
 
Serial pc(USBTX, USBRX);
Serial gps(p9, p10);
TextLCD lcd(p21, p22, p23, p24, p25, p26, p30, 20 ,2);

2. In your main.c arrange the order of your #include files and uncomment your global ojbects (ie variables).

//  use this order
#include "mbed.h"
#include "TextLCD.h"
#include "data.h"
#include "gps.h"

//Serial port pin assignment and setup
Serial gps(p9, p10);  // tx, rx//Creates a variable for serial comunication through pin 28 and 27
//LCD 2x20 parallel code pin assignment
TextLCD lcd(p21, p22, p23, p24, p25, p26, p30, 20, 2); // (rs, rw, e, d0, d1, d2, d3, n_column, n_rows)
Serial pc(USBTX, USBRX); //define USB connection pins

Now this is should all work, you should be able to print in main or gps.h...

However.. I wonder if this is what you really wanted. Normally the gps.h should be a called gps.c, then the data.h file should have a some #define clauses to make them extern, but I dunno if thats what you wanted, separate modular .c files.

14 May 2013

Thanks for the quick reply. I will try this tomorrow on the test bench.

All I really want is to pull data from the GPS and write it (along with about 80 other real time variables from an accelerometer and automotive fuel injection system to an SD card. A few select variables will go to the display.

I use the mbed as a datalogger for my road race track car.

That being said, I was attracted to the mbed becuase I started with zero programming skills. I managed to get everything else working by adapting example code and looking up basic functions. but I am not sure what file structure is needed.

14 May 2013

I tried the suggestions. I still get gibberish if I try to print from the mail while loop. The call functions to print from the gps.h file work perfectly.

I tried to declare a definition for gps.h following the same format as data.h. in this case, I get no output at all.

I tried to move the "getgpsstring" function to the main. Again, no output.

I guess its a good thing I never took up programming in school.

14 May 2013

Your doing just fine, just need to read up more on characters, character arrays, float, and integers.

The problem is in main.c

1. First problem is lcd.printf("Lat=%6.4i", Lat1);

Here you have Lat1 printing out as a integer, but in data.h you declare it as a character array (char Lat1[10]) and you capture it as a single character in parseRMC() via , sscanf(Lat, "%c", Lat1). This will only put 1 character in to the array at location Lat1[0] and the print statement is wrong because it will print the address of the char array Lat1 not the character. If you want to print that one character as a integer it should be:

lcd.printf("Lat=%6.4i", atoi(Lat1[0])); uses the function atoi to convert ascii char to integer

However if you wanted to print it as a character then:

lcd.printf("Lat=%c", Lat1[0]);

You should be able to put lcd.printf("Lat:%s",Lat); in your main.c and that will work.

2. Next problem is lcd.printf("Long=%i%i", Long, Long_h);

In data.h you have Long and Long_h declared as a pointer to a character but you are using %i in the printf statement, that will print the address of the variables. The correct syntax would be:

lcd.printf("Long=%s %s", Long, Long_h);

So in main.c put this in there:

       lcd.locate(0,3);
       lcd.printf("Lat:%s",Lat);
       lcd.locate(0,1);
       lcd.printf("Long=%s%s", Long, Long_h);

I think your confused with a what a number is and a character or character string. Characters are stored in memory as numbers and can be printed as characters (%c) or numbers (%d or %i) using printf. The letter or character 'A' has the ascii number 65, you can google ascii character set to see thetable. When stored in memory it is the number 65. Another example is the character '8' it is not number 8 but character 8 and is store in memory as ascii number 56.

char ch = '8' ;   //  character 8 NOT number 8
// if you printf("%c %i",ch,ch)  you will see "8 56", 8 is the character, 56 is its ascii number

char ch = 'A' ;   // a character
// if you printf("%c %i",ch,ch)  you will see "A 65", A is the character, 65 is its ascii number

int ch = 65;    // a integer
// if you printf("%c %i",ch,ch)  you will see "A 65", A is the character, 65 is its ascii number

char *ch;    // pointer to character array
ch ="A";     // this is location ch[0]

/*
if you printf("%s %i %c",ch,ch,ch) you will see "A 11622208 @"  , A is the character array "A",
the 11622208 is the memory address of ch which will be different for every computer, and the 
@ is the character number from the lower 8 bits of the memory address 11622208. If you
convert 11622208 to hexadecimal you get B15740, so 40 Hex is a @ character and that
shows up because %c is asking for 1 byte character and 40 is stored low byte first because 
mbed is litte endian.

The correct way is printf("%s %i %c",ch,ch[0],ch[0]), you will see "A 65 A"
*/

I suspect that some of your data is in floating point format. When you read from the gps it probably has Latitude like 54.345 or something like that. When you use strtok it points to the data as a character array not a number ie "54.345" and not 54.345 So print the character array using %s NOT %i. ie printf("Lat %s",Latitude);

If you want to print the Latitude as a floating point number (maybe because you want to control the formatting) then you need to convert the character array to a floating point number. Use atof() or like you did with sscanf(), Here are some crazy examples

char *Latitude;
Latitude = strtok(NULL,",");
printf("Lat %s",Latitude);

char *Latitude;
Latitude = strtok(NULL,",");
printf("Lat %6.4f",atof(Latitude));  // converts char array to float

char *Latitude;
char Flatitude[20];
Latitude = strtok(NULL,",");
sscanf(Latitude,"%f",Flatitude);  // converts char array to float
printf("Lat %6.4f",Flatitude);

.

15 May 2013

Thanks for the suggestions. It all makes sense related to the format designations of the variables. Some of the different formats may be messed up as I experimented trying to get them to work. I will spend some time going back through the code and trying to clean it up so that there is consistency between files.

I have had a question about the difference between a "char" and a "char *". This has created some format issues in conversion.

I have tried the sscanf() function to convert the arrays but I have had trouble getting it to convert due to the *. I understand that the * designates an array and this is a location pointer.