Helpful ReplyHot!UART Code

Author
StarKnight
New Member
  • Total Posts : 10
  • Reward points : 0
  • Joined: 2017/06/16 15:37:13
  • Location: 0
  • Status: offline
2018/02/09 09:35:26 (permalink)
0

UART Code

Hi, 
 
I've had to take a break over the past few months, but I'm keen on completing my project that I had set out to do.  Read the GPS module and output the Latitude and Longitude and other parameters.
 
I had some problems earlier with the UART code and after seeking help in these forums managed to get something working.
I have attached the code below, to ask if there are any improvements that I can make to the code or is this the optimal code possible.
 
There are 4 parts to the code
1. Show a display while waiting for the GPS to connect - indicated by the PPS signal or when reliable data starts pouring in. I have yet to think of a way to do this. ideas?
2. Read the UART - Code included below
3. Parse the data - Code is ready - will be posted as I can see the Longitude change, but Latitude seems constant, not sure if the update is not happening, for example it reads the first value and the refresh is not working [Code to be posted] 
4. Compute the NGR from Latitude and Longitude - Code is ready, need some help later to optimise float/double for example which should be used for what etc. and some ideas around power(s) and trig computation required. Maybe some integer math examples so that I can check the answers against 32 bit numbers. 
Thanks for all your help.
 
void interrupt ISR() {
    if (PIR1bits.RC1IF == 1 && PIE1bits.RC1IE == 1) {
        cUART_char = RCREG1;
        //if (cUART_char !='\n' && cUART_char != '\r')
        //{
            fuseDataGPS(cUART_char);
       // }
    }
    //result = SUCCESS;
    //STS_LED = ~STS_LED;

    if (RCSTA1bits.OERR || RCSTA1bits.FERR) {
       // if (RCSTA1bits.OERR)
            //printf("\r\nOverrun Serial port 1 error\r\n");
       // else
            //printf("\r\nFraming port 1 error\r\n");
        //cUART_char = RCREG1;
        RCSTA1bits.CREN = 0; /* clear any errors */
        Nop();
        //Nop();
        RCSTA1bits.CREN = 1; /* re-enable reception? */
        //result = WARNING;
    }
}

void serial_init() {
    //cUART_data_flg = 0; // init data receive flag to zero (no data)
    INTCONbits.GIE = 0; //no interruptions please
    TRISCbits.TRISC6 = 1; // input
    TRISCbits.TRISC7 = 1; // input
    TXSTA1bits.BRGH1=1; // select low speed Baud Rate
    TXSTA1bits.TX9=0; // select 8 data bits
    TXSTA1bits.TXEN = 1; // enable transmit
    TXSTA1bits.SYNC = 0;

    RCSTA1bits.SPEN=1; // serial port is enabled
    RCSTA1bits.RX9=0; // select 8 data bits
    RCSTA1bits.CREN=1; // receive enabled
    PIR1bits.RC1IF=0; // make sure receive interrupt flag is clear
    BAUDCONbits.BRG16 = 1;
    SPBRGH1 = 6;
    SPBRG1 = 130;
    INTCONbits.PEIE = 1; // Enable peripheral interrupt
    INTCONbits.GIE = 1; // enable global interrupt
    RCONbits.IPEN = 1; //enable Interrupt priority levels
    IPR1bits.RC1IP = 0; // EUSART Receive Interrupt Priority 0 = Low priority
    PIE1bits.RC1IE = 1; // 1 = Enables the EUSART receive interrupt
    //INTCONbits.GIEL = 1; //enable interrupts
    //INTCONbits.GIEH = 1;
    __delay_ms(50); // give time for voltage levels on board to settle
}

 
StarKnight
#1
rodims
Super Member
  • Total Posts : 1353
  • Reward points : 0
  • Joined: 2009/02/10 11:08:59
  • Location: 51.9627, 7.6262
  • Status: online
Re: UART Code 2018/02/09 10:37:40 (permalink) ☄ Helpfulby StarKnight 2018/02/09 12:06:05
+3 (3)
I have attached the code below, to ask if there are any improvements that I can make to the code or is this the optimal code possible.

Without even looking at any code, it is possible to say, there is always room for improvement :-)
Also the word "optimal" does not make any sense without knowing all requirements and restrictions.
 
Your shown code is just  initialization and interrupt (I did not check the details)
From your post and enumeration of your 4 topics I would conclude that you are still stuck with 2)
Since you do not show fuseDataGPS it is not even possible to judge what you are doing there.
 
Do not parse and compute within your ISR function.
 
Write your code to place one single GPS sentence (ASCII text) into a buffer.
This includes determining the end of the sentence (e.g. LF or CRLF). And also error handling, if you do not get a reasonable end of the message.
Usually also includes evaluation of a time-out, if you do not get enough data for a complete sentence.
 
[edit]: depending on your GPS configuration and messages (e.g. NMEA), you may receive more than one sentence, e.g.
$GPVTG,,T,,M,0.00,N,0.0,K,A*13
$GPGGA,160655.000,5160.1158,N,00739.1993,E,1,09,1.0,105.7,M,47.3,M,,0000*53
$GPGLL,5160.1158,N,00739.1993,E,160655.000,A,A*5D
$GPGSA,A,3,16,06,25,23,21,13,31,05,29,,,,2.1,1.0,1.9*32
$GPGSV,3,1,12,29,61,069,31,31,46,226,23,21,44,174,29,25,32,125,35*72
$GPGSV,3,2,12,16,20,298,43,05,18,058,28,06,11,256,39,23,09,313,46*77
$GPGSV,3,3,12,13,08,339,36,02,03,038,41,10,02,012,43,12,,121,*75
$GPRMC,160655.000,A,5157.1158,N,00738.1993,E,0.00,,290711,,,A*78

 
which then is repeated e.g. every second or every 1/10 second. Since these messages usually are received as a bunch of messages, i.e. without a time gap (in serial transmission) between them, this makes your detection of the end of such a package a bit more complicated.
Or it makes the buffering more complicated, e.g. ring buffer of suitable size or array of message buffers.
[/edit]
 
On detection of a valid message (i.e. end of line), set a flag which signals to your main code that it can parse the text (whatever you want to do, including display, which usually is SLOW).
Depending on the frequency of your GPS (1 Hz, 10 Hz ? ), the amount of messages activated, and the time required for calculation and further computation, you might decide to use double buffering. Primary target is to avoid reading the buffer, while it is already overwritten by the next GPS message.
 
Then return to thinking about 3 and 4 (and 1) .
Maybe you already have done all this, it is not evident from your post.
 
post edited by rodims - 2018/02/12 06:45:32
#2
StarKnight
New Member
  • Total Posts : 10
  • Reward points : 0
  • Joined: 2017/06/16 15:37:13
  • Location: 0
  • Status: offline
Re: UART Code 2018/02/09 12:24:54 (permalink)
0
Hi Rodims,
 
Thank you for taking time to read through the post 
Without even looking at any code, it is possible to say, there is always room for improvement :-)
Also the word "optimal" does not make any sense without knowing all requirements and restrictions.
 
 
Sorry I wasn't quite clear. What I meant was if I had checked all the boxes, such as error checking, clearing flags correctly, etc. 
 
Since you do not show fuseDataGPS it is not even possible to judge what you are doing there.

The code is attached below.
void parseDataGPS(void){
    // int received_cks = 16*digit2dec(gps.tmp_szChecksum[0]) + charToInt(gps.tmp_szChecksum[1]);
    int received_cks = 16*charToInt(gps.szChecksum[0]) + charToInt(gps.szChecksum[1]);
    //uart1.Send("seq: [cc:%X][words:%d][rc:%s:%d]\r\n", m_nChecksum,m_nWordIdx, tmp_szChecksum, received_cks);
    // check checksum, and return if invalid!
    if (gps.checksum != received_cks) {
        //m_bFlagDataReady = false;
        return;
    }
    /* $GPGGA
    * $GPGGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh
    * WORDS:
    * 0 = $GPGGA - Gloabl Positioning System Fixed Data
    * 1 = UTC of Position
    * 2 = Latitude
    * 3 = N or S
    * 4 = Longitude
    * 5 = E or W
    * 6 = GPS quality indicator (0=invalid; 1=GPS fix; 2=Diff. GPS fix)
    * 7 = Number of satellites in use [not those in view]
    * 8 = Horizontal dilution of position
    * 9 = Antenna altitude above/below mean sea level (geoid)
    * 10 = Meters (Antenna height unit)
    * 11 = Geoidal separation (Diff. between WGS-84 earth ellipsoid and mean sea level.
    * -geoid is below WGS-84 ellipsoid)
    * 12 = Meters (Units of geoidal separation)
    * 13 = Age in seconds since last update from diff. reference station
    * 14 = Diff. reference station ID#
    * 15 = Checksum
    */
    if (strcmp(gps.words[0], "$GPGGA") == 0) {
        // Check GPS Fix: 0=no fix, 1=GPS fix, 2=Dif. GPS fix
        if (gps.words[6][0] == '0') {
            gps.positionFixIndicator = false;
            // clear data
            // gps.res_fLatitude = 0;
            // gps.r es_fLongitude = 0;
            gps.flagDataReady = false;
            return;
        }

        gps.positionFixIndicator = true;
        // parse time
        gps.UTCHour = charToInt(gps.words[1][0]) * 10 + charToInt(gps.words[1][1]);
        gps.UTCMin = charToInt(gps.words[1][2]) * 10 + charToInt(gps.words[1][3]);
        gps.UTCSec = charToInt(gps.words[1][4]) * 10 + charToInt(gps.words[1][5]);

        // parse latitude and longitude in NMEA format
        gps.latitude = atof(gps.words[2]);
        gps.longitude = atof(gps.words[4]);
        // get decimal format
        if (gps.words[3][0] == 'S') gps.latitude *= -1.0;
        if (gps.words[5][0] == 'W') gps.longitude *= -1.0;
        float degrees = trunc(gps.latitude / 100.0f);
        float minutes = gps.latitude - (degrees * 100.0f);
        gps.latitude = degrees + minutes / 60.0f;
        degrees = trunc(gps.longitude / 100.0f);
        minutes = gps.longitude - (degrees * 100.0f);
        gps.longitude = degrees + minutes / 60.0f;

        // parse number of satellites
        gps.satellitesUsed = (int)atof(gps.words[7]);

        // parse horizontal dilution of precision
        gps.dilution = atof(gps.words[8]);
        // parse altitude
        gps.altitude = atof(gps.words[9]);
        // data ready
        gps.flagDataReady = true;
    }//$GPGGA
    /* $GPRMC
    * note: a siRF chipset will not support magnetic headers.
    * $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh
    * ex: $GPRMC,230558.501,A,4543.8901,N,02112.7219,E,1.50,181.47,230213,,,A*66,
    *
    * WORDS:
    * 0 = $GPRMC - Recommended Minimum Specific GNSS Data
    * 1 = UTC of position fix
    * 2 = Data status (V=navigation receiver warning)
    * 3 = Latitude of fix
    * 4 = N or S
    * 5 = Longitude of fix
    * 6 = E or W
    * 7 = Speed over ground in knots
    * 8 = Track made good in degrees True, Bearing This indicates the direction that the device is currently moving in,
    * from 0 to 360, measured in ?azimuth?.
    * 9 = UT date
    * 10 = Magnetic variation degrees (Easterly var. subtracts from true course)
    * 11 = E or W
    * 12 = Checksum
    */
    if (strcmp(gps.words[0], "$GPRMC") == 0) {
        // Check data status: A-ok, V-invalid
        if (gps.words[2][0] == 'V') {
            gps.dataValid = false;
            // clear data
            // gps.res_fLatitude = 0;
            // gps.res_fLongitude = 0;
            gps.flagDataReady = false;
            return;
        }
        gps.dataValid = true;
        gps.UTCHour = charToInt(gps.words[1][0]) * 10 + charToInt(gps.words[1][1]);
        gps.UTCMin = charToInt(gps.words[1][2]) * 10 + charToInt(gps.words[1][3]);
        gps.UTCSec = charToInt(gps.words[1][4]) * 10 + charToInt(gps.words[1][5]);

        // parse latitude and longitude in NMEA format
        gps.latitude = atof(gps.words[3]);
        gps.longitude = atof(gps.words[5]);
        // get decimal format
        if (gps.words[4][0] == 'S') gps.latitude *= -1.0;
        if (gps.words[6][0] == 'W') gps.longitude *= -1.0;
        float degrees = trunc(gps.latitude / 100.0f);
        float minutes = gps.latitude - (degrees * 100.0f);
        gps.latitude = degrees + minutes / 60.0f;
        degrees = trunc(gps.longitude / 100.0f);
        minutes = gps.longitude - (degrees * 100.0f);
        gps.longitude = degrees + minutes / 60.0f;
        
        gps.speed = atof(gps.words[7]);
        gps.speed *= 1.15078; // convert to mph
        // parse bearing
        gps.bearing = atof(gps.words[8]);
        // parse UTC date
        gps.UTCDay = charToInt(gps.words[9][0]) * 10 + charToInt(gps.words[9][1]);
        gps.UTCMonth = charToInt(gps.words[9][2]) * 10 + charToInt(gps.words[9][3]);
        gps.UTCYear = charToInt(gps.words[9][4]) * 10 + charToInt(gps.words[9][5]);
        // data ready
        gps.flagDataReady = true;
    }//$GPRMC
    return;
}//parseDataGPS

void fuseDataGPS(char c){
    if (c == '$') {
        gps.flagRead = true;
        STS_LED = ~STS_LED;
        // init parser vars
        gps.flagComputedCks = false;
        gps.checksum = 0;
        // after getting * we start cuttings the received m_nChecksum
        gps.flagReceivedCks = false;
        gps.index_received_checksum = 0;
        // word cutting variables
        gps.wordIdx = 0; gps.prevIdx = 0; gps.nowIdx = 0;
    }
    if (gps.flagRead) {
        // check ending
        if (c == '\r' || c== '\n') {
            // catch last ending item too
            //STS_LED = ~STS_LED;
            gps.words[gps.wordIdx][gps.nowIdx - gps.prevIdx] = 0;
            gps.wordIdx++;
            // cut received m_nChecksum
            gps.szChecksum[gps.index_received_checksum] = 0;
            // sentence complete, read done
            gps.flagRead = false;
            // parse
            parseDataGPS();
        }
        else {
            // computed m_nChecksum logic: count all chars between $ and * exclusively
            if (gps.flagComputedCks && c == '*') gps.flagComputedCks = false;
            if (gps.flagComputedCks) gps.checksum ^= c;
            if (c == '$') gps.flagComputedCks = true;
            // received m_nChecksum
            if (gps.flagReceivedCks) {
                gps.szChecksum[gps.index_received_checksum] = c;
                gps.index_received_checksum++;
            }
            if (c == '*') gps.flagReceivedCks = true;
                // build a word
                gps.words[gps.wordIdx][gps.nowIdx - gps.prevIdx] = c;
                if (c == ',') {
                    gps.words[gps.wordIdx][gps.nowIdx - gps.prevIdx] = 0;
                    gps.wordIdx++;
                    gps.prevIdx = gps.nowIdx;
                }
                else gps.nowIdx++;
         }
    }
    return;
}//fuseDataGPS

 
Do not parse and compute within your ISR function.

I had moved the function
 fuseDataGPS(cUART_char); 
outside and had a flag here earlier but it wasn't working, will try again.
Write your code to place one single GPS sentence (ASCII text) into a buffer.

This includes determining the end of the sentence (e.g. LF or CRLF). And also error handling, if you do not get a reasonable end of the message.

Usually also includes evaluation of a time-out, if you do not get enough data for a complete sentence.

 
The code captures the line and parses it. I can display the Longitude (which changes), but Latitude remains static. In the test, the module is stationary. I have not configured the 1 Hz/10Hz setting yet, will try to get the manual for the module.
 
I've included the code for data collection and parsing above, hope this helps?
 
 
#3
rodims
Super Member
  • Total Posts : 1353
  • Reward points : 0
  • Joined: 2009/02/10 11:08:59
  • Location: 51.9627, 7.6262
  • Status: online
Re: UART Code 2018/02/09 14:06:50 (permalink)
+1 (1)
Only very short answer, no time left today ...
FuseDataGPS like you show it should be ok within ISR.
But the call to ParseDataGPS should not be done from within FuseDataGPS.
 
This changes logic a bit,- I would start with that.
It also depends on what you want to do / learn. Learn GPS, or learn PIC.
If it works now (basically), even with doing all this calculations etc. in the ISR, you could continue to debug that and consider improving the code later.  You have to decide upon where you want to go next  ...
 
Depending on your baud rate, you currently always risc, that you miss characters. Needs some timing calculations ...
 
edit: you should specify your PIC and clock frequency ...
post edited by rodims - 2018/02/09 14:08:35
#4
RISC
Super Member
  • Total Posts : 5272
  • Reward points : 0
  • Status: offline
Re: UART Code 2018/02/09 15:28:46 (permalink)
+1 (1)
Hi StarKnight,
 
Which PIC do you use..there are more than 1200 different models...
Do you use the internal clock or an external XTAL ?
 
Regards
 
#5
StarKnight
New Member
  • Total Posts : 10
  • Reward points : 0
  • Joined: 2017/06/16 15:37:13
  • Location: 0
  • Status: offline
Re: UART Code 2018/02/09 15:36:28 (permalink) ☄ Helpfulby davekw7x 2018/02/09 18:02:51
0
Hi RISC,
 
I'm using the PIC18LF26K22. 
 
#ifndef __BIT_SETTINGS_H
#define __BIT_SETTINGS_H

#include <xc.h>
#define _XTAL_FREQ 64000000

// PIC18F46K22 Configuration Bit Settings
// CONFIG1H
//#pragma config FOSC = HSMP // Oscillator Selection bits (HS oscillator (medium power 4-16 MHz))
#pragma config FOSC = INTIO67 // Oscillator Selection bits (Internal oscillator block)
#pragma config PLLCFG = ON // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = ON // Primary clock enable bit (Primary clock is always enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 190 // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC1 // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<5:0> pins are configured as analog input channels on Reset)
#pragma config CCP3MX = PORTB5 // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0 // Timer3 Clock input mux bit (T3CKI is on RC0)
//#pragma config P2BMX = PORTD2 // ECCP2 B output mux bit (P2B is on RD2)
#pragma config MCLRE = EXTMCLR // RE3 input pin enabled; MCLR disabled

// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-003FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (004000-007FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (008000-00BFFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (00C000-00FFFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-003FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (004000-007FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (008000-00BFFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (00C000-00FFFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0 (000800-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (004000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)

#endif

 
Thanks
 
/StarKnight
#6
StarKnight
New Member
  • Total Posts : 10
  • Reward points : 0
  • Joined: 2017/06/16 15:37:13
  • Location: 0
  • Status: offline
Re: UART Code 2018/02/09 16:02:09 (permalink)
0
Hi Rodims/RISC
 
Thanks to the initial feedback, I've moved the parseDataGPS() from inside FuseDataGPS to here:
while(1) {
    if (gps.flagRead == false) {
            
    parseDataGPS();
    //if (strcmp(gps.words[0], "$GPGGA") == 0) {
       if (gps.positionFixIndicator ==true) {
///Print statements go here
}
}
}

 
I also realised that I've not provided a crucial snippet of code. Here it is:
STS_LED = 1;
OSCCON = 0b01110000;
OSCTUNEbits.PLLEN = 1; // turn on the PLL 64 MHz
ANSELA = 0; ANSELB = 0; ANSELC = 0; //ANSELD = 0; ANSELE = 0;
PORTA = 0; PORTB = 0; PORTC = 0; PORTE = 0; //PORTD = 0;
TRISA = 0; TRISB = 0; TRISC = 0; TRISE = 0; //TRISD = 0;

//SPI Init()
//TFT Init() etc
serial_init();

 
Many thanks for your patience.
 
/StarKnight
#7
Aussie Susan
Super Member
  • Total Posts : 3338
  • Reward points : 0
  • Joined: 2008/08/18 22:20:40
  • Location: Melbourne, Australia
  • Status: offline
Re: UART Code 2018/02/11 18:59:33 (permalink)
+3 (3)
Looking at your 'parse' code in post #3, I'm not sure what 'gps.words[0]' equates to but the 'strcmp' function call is probably NOT doing what you expect. It looks like you are checking the the first few characters of the received sentence for a match with "$GPGGA".
However the spec of 'strcmp' says that it will return a value based on the first non-matching character. If *both* strings are of the same length and all characters are the same then you will get '0' - which is what you are testing for.
But if one of the strings continues on then you will get a comparison of the *next* character with the trailing null of the literal and that is (almost certainly) not a match and so you will get a non-zero return.
All in all that means you will not ever get a valid match using 'strcmp'.
Try using strncmp instead or, better still, invest in some proper string parsing code (and *NOT* the scanf family).
Susan
#8
rodims
Super Member
  • Total Posts : 1353
  • Reward points : 0
  • Joined: 2009/02/10 11:08:59
  • Location: 51.9627, 7.6262
  • Status: online
Re: UART Code 2018/02/12 02:13:08 (permalink)
+3 (3)
code will be posted as I can see the Longitude change, but Latitude seems constant, not sure if the update is not happening, for example it reads the first value and the refresh is not working
I think it should not be so difficult to debug your Parse function yourself. If you need help, then you should again describe in detail what is your problem, the above is a bit vague (...seems ...  not sure ... refresh not working ... ).
Also then you should post a complete package of NMEA messages as you receive it (before parsing). You seem to assume 6 messages.  It's kind of reverse engineering from your code to what the input "might" be. And finally you could describe the idea (algorithm) of your fuseDataGPS and the parsing function. 
 
As you see this is a bit of work, so it might be easier to just debug the code yourself before explaining it in detail :-)
 
#9
StarKnight
New Member
  • Total Posts : 10
  • Reward points : 0
  • Joined: 2017/06/16 15:37:13
  • Location: 0
  • Status: offline
Re: UART Code 2018/02/12 06:17:36 (permalink)
0
Hi Susan,
 
Thanks for the heads-up on the strcmp. gps.words[0] contains the first characters in the GPS string such as GPGGA, GPGSV. I've included a sample here 
$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76
$GPGSA,A,3,10,07,05,02,29,04,08,13,,,,,1.72,1.03,1.38*0A
$GPGSV,3,1,11,10,63,137,17,07,61,098,15,05,59,290,20,08,54,157,30*70
$GPGSV,3,2,11,02,39,223,19,13,28,070,17,26,23,252,,04,14,186,14*79
$GPGSV,3,3,11,29,09,301,24,16,09,020,,36,,,*76
$GPRMC,092750.000,A,5321.6802,N,00630.3372,W,0.02,31.66,280511,,,A*43
$GPGGA,092751.000,5321.6802,N,00630.3371,W,1,8,1.03,61.7,M,55.3,M,,*75
$GPGSA,A,3,10,07,05,02,29,04,08,13,,,,,1.72,1.03,1.38*0A
$GPGSV,3,1,11,10,63,137,17,07,61,098,15,05,59,290,20,08,54,157,30*70
$GPGSV,3,2,11,02,39,223,16,13,28,070,17,26,23,252,,04,14,186,15*77
$GPGSV,3,3,11,29,09,301,24,16,09,020,,36,,,*76
$GPRMC,092751.000,A,5321.6802,N,00630.3371,W,0.06,31.66,280511,,,A*45

 
The Latitude and Longitude are now getting refreshed each cycle (1 second), there are some glitches at times which must mean that some strings are being dropped. 
 
The first reason for the post was to check if the ISR routine to read chars was handled correctly, with error checking. Based on the feedback that I received I have moved the parseGPSdata () out from FuseGPSdata, so I now have 
ISR() -- FuseGPSdata 
and the while { if flag parseGPSData() Print()} running
instead of 
ISR() -- FuseGPSdata -- parseGPSdata and the while loop running 
 
So the parsedata is splitting the data into each array bucket at the comma delimiter that appears in the string. 
 
Where would be the best place to display the characters that come in from the GPS. In a computer monitor the lines would fold onto the next and so on.
 
Initially I just need to check that the characters are arriving correctly and if the array bucket is being updated. 
 
Sorry if this is a big ask. :(
 
So to summarise, data is arriving, but how to I check if the data is arriving correctly. I currently use the seconds display to check if the seconds update and the Lat/Long update happens at the same time. Is it the best way?
 
I will try strncmp (will read this, thanks!)  and update this post tonight.
 
Thanks!
 
/StarKnight
 
#10
rodims
Super Member
  • Total Posts : 1353
  • Reward points : 0
  • Joined: 2009/02/10 11:08:59
  • Location: 51.9627, 7.6262
  • Status: online
Re: UART Code 2018/02/12 10:35:31 (permalink)
+1 (1)
Where would be the best place to display the characters that come in from the GPS. In a computer monitor the lines would fold onto the next and so on.

How do you display other results ? Do you have a serial output connected to a PC terminal application ?
Compared to the calculations the display likely is the slowest part. You must take into account, that it will slow down your code outside the interrupt routine.
 
Your message with 6 lines consists of 385 bytes, lets say 400 bytes.
Your GPS rate is 1 second. If you have a UART with e.g. 115200 baud as display output, then it should be possible to output roughly 11520 bytes per second. So you could dump your array bucket as raw data to see how your "glitches" might look like.  A terminal application like HTERM will log all the outputs, so can review the data later on or save it to files. Since you removed the LFs in your array, you need to add a Newline in your output for each element.
 
What is the baud rate for your GPS ? Take care that receiving and printing must not run in parallel, and everything (receiving, printing, optionally parsing) must fit into 1 second. 
 
#11
Jump to:
© 2018 APG vNext Commercial Version 4.5