• AVR Freaks

Hot!18F252 and parsing NMEA

Author
alejandrodaniel
New Member
  • Total Posts : 17
  • Reward points : 0
  • Joined: 2020/06/07 03:44:09
  • Location: 0
  • Status: offline
2021/01/15 16:18:44 (permalink)
0

18F252 and parsing NMEA

I wrote this test code for an 18F252 to parse the NMEA strings with $ GPRMC header and store them in the internal eeprom to transmit the values ​​detected with the IIC bus when the master requests it.
sorry my awful english
//--------------------------- EXTRACION DATOS ----------------------------------
void Parsing_GPS(char *L_NMEA)
     {
      unsigned short Fix,N_S,E_W,Delta;
      unsigned int Gr_Lat,Min_Lat,Sec_Lat;
      unsigned int Gr_Long,Min_Long,Sec_Long;
      float Raw_Latitud,Raw_Longitud;
      char *Buffer,*Datos[40],strDatos[40];
      //CALCULO
      Buffer=strtok(L_NMEA,",");
      for(Delta=0;Delta<13;Delta++)
         {
          Datos[Delta]=Buffer;
          Buffer=strtok(NULL,",");
         }
      if(strcmp(Datos[0],"$GPRMC")==0)
        {
         //FIX
         if(strcmp(Datos[2],"A"))Fix=0x00;else Fix=0x01;
         WR_Eeprom(0x00,Fix);
         //LATITUD
         Raw_Latitud=atof(Datos[3]);
         Gr_Lat=Raw_Latitud/100;
         Min_Lat=Raw_Latitud-(Gr_Lat*100);
         Sec_Lat=(Raw_Latitud-((Gr_Lat*100)+Min_Lat))*60;
         WR_Eeprom(0x08,Gr_Lat);
         WR_Eeprom(0x09,Min_Lat);
         WR_Eeprom(0x0A,Sec_Lat/256);
         WR_Eeprom(0x0B,Sec_Lat%256);
         //LATITUD N_S
         if(strcmp(Datos[4],"S"))N_S=0x00;else N_S=0x01;
         WR_Eeprom(0x0C,N_S);
         //LONGITUD
         Raw_Longitud=atof(Datos[5]);
         Gr_Long=Raw_Longitud/100;
         Min_Long=Raw_Longitud-(Gr_Long*100);
         Sec_Long=(Raw_Longitud-((Gr_Long*100)+Min_Long))*60;
         WR_Eeprom(0x10,Gr_Long);
         WR_Eeprom(0x11,Min_Long);
         WR_Eeprom(0x12,Sec_Long/256);
         WR_Eeprom(0x13,Sec_Long%256);
         //LONGITUD E_W
         if(strcmp(Datos[6],"E"))E_W=0x00;else E_W=0x01;
         WR_Eeprom(0x14,E_W);
         Led_status^=1;
        }
      }

//--------------------------- CICLO --------------------------------------------
void main(void)
     {
      Config_PIC();
      __delay_ms(100);
      while(1)
         {
          char NMEA[]="$GPRMC,192123.00,V,4056.72626,N,01421.39990,E,0.191,,120121,,,A*7E";
          Parsing_GPS(NMEA);
          __delay_ms(400);
         }
     }
[/code]
the result is this
EEData Memory
0000 01  FF  FF  FF  FF  FF  FF  FF  
0008 28  38  00  2B  00  FF  FF  FF  
0010 0E  15  00  17  01  FF  FF  FF  
0018 FF  FF  FF  FF  FF  FF  FF  FF
[/code]
however I find the values ​​of the FIX and of the hemispheres and cardinal points reversed
0x00 = 0x01 instead of 0x00("A")
0x0C=0x00 instead of 0x01("N")
0x0C=0x01 instead of 0x00("E")

what am I doing wrong?
#1

5 Replies Related Threads

    Aussie Susan
    Super Member
    • Total Posts : 3827
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: 18F252 and parsing NMEA 2021/01/15 19:02:32 (permalink)
    +2 (2)
    Don't forget that 'strcmp' returns 0 when the strings match.
    Therefore your line 'if(strcmp(Datos[6],"E"))E_W=0x00; else E_W=0x01;" will set 'E_W' to 1 when 'Datos[6]' is equal to "E" because that makes 'strcmp' return 0 which is interpreted as 'false'
    Susan
    #2
    alejandrodaniel
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2020/06/07 03:44:09
    • Location: 0
    • Status: offline
    Re: 18F252 and parsing NMEA 2021/01/16 05:17:47 (permalink)
    0
    I made a trivial mistake.
    now it's OK
    [quote]EEData Memory
    0000 00 FF FF FF FF FF FF FF
    0008 28 38 2B 01 FF FF FF FF
    0010 0E 15 17 00 FF FF FF FF
    0018 FF FF FF FF FF FF FF FF [/quote]
    Thanks again



    #3
    TechDpt
    Starting Member
    • Total Posts : 74
    • Reward points : 0
    • Joined: 2011/06/13 09:29:39
    • Location: 0
    • Status: offline
    Re: 18F252 and parsing NMEA 2021/01/16 08:20:29 (permalink)
    0
    alejandrodaniel
    I made a trivial mistake.
    now it's OK
    [quote]EEData Memory
    0000 00 FF FF FF FF FF FF FF
    0008 28 38 2B 01 FF FF FF FF
    0010 0E 15 17 00 FF FF FF FF
    0018 FF FF FF FF FF FF FF FF [/quote]
    Thanks again





    Just a suggest,
    have you also checked what can happen with a malformed string (less or bigger numbers of sections)?
    You have supposed a 13 section, this can be true for a properly formatted frame (not checked, I'm just doing some programming consideration here). It may be useful to perform a while loop and checking about the null terminated string to know when you reach the end of the string and then you are able to know, by counting the steps you did, if the string was properly formatted from the number of items perspective.
     
    Link to strtok description:
    https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
     
    BR
    F.
    #4
    BroadwellConsultingInc
    Super Member
    • Total Posts : 105
    • Reward points : 0
    • Joined: 2020/06/09 06:07:55
    • Location: 0
    • Status: offline
    Re: 18F252 and parsing NMEA 2021/01/17 20:01:34 (permalink)
    +4 (4)
    One quick (slightly off topic) suggestion.  Your code doesn't really require any of the PIC's resources to do what you're doing.  I find I can often solve problems like this if I compile the code on my PC and use either the debugger or printf's to the console to figure out what's wrong.   Once it works right, copy the code back to the PIC.
     
    I'd generate a couple of dummy functions:
     
    #define EEPROM_SIZE 256

    uint8_t FakeEEPROM[EEPROM_SIZE] = { ... Some initialization ...};

    void WR_Eeprom(uint8_t address, uint8_t value)
    {
       if (address < EEPROM_SIZE)
        { 
            FakeEEPROM[address] = value;
        }
        else
        {
            printf("BAD EEPROM WRITE ADDRESS AT %d",address);
        }
    }

    uint8_t RD_Eeeprom(uint8_t address)
    {
       if (address < EEPROM_SIZE)
        { 
            return(FakeEEPROM[address]);
        }
        else
        {
            printf("BAD EEPROM READ ADDRESS AT %d",address);
            return(0x77);
        }
    }

     
    On the PC you can insert debugging printfs on every line if you want, you have faster, easier memory views, breakpoints, etc.  Cycle time to compile and execute is often much, much faster.
     
    And as a side effect, once you've got it running well on the PC, your ability to unit test your code with lots of different input and generate reports gets really easy.
     
    #5
    davea
    Super Member
    • Total Posts : 627
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: Tampa Bay FL USA
    • Status: online
    Re: 18F252 and parsing NMEA 2021/01/17 23:27:15 (permalink)
    0
    you may want to rethink the use of string functions to parse
    and just look for $GPRMC then start filling a buffer until 0x0A 
    then parse it by hand it would be faster
    do you have to convert from decimal min, to min and seconds
    for map use ?
     
    #6
    Jump to:
    © 2021 APG vNext Commercial Version 4.5