Trying to parse nmea with double and strtod

Hi,

I'm trying to build nmea parser, so I have a functionc hecking all nmea sentences and trying to get double value, but I always go bad double value. For example here what I do for VTG sentence

if ((strcmp(&field[0][3], "VTG") == 0) && (f > 8)) {

      LOG_HEXDUMP_INF(field[5], strlen(field[5]), "Field[5]");
      LOG_HEXDUMP_INF(field[7], strlen(field[7]), "Field[7]");

      LOG_INF("Check string for strtod: '%s'", field[5]);
      for (int i = 0; i < strlen(field[5]); i++) {
          LOG_INF("field[5][%d] = 0x%02x", i, field[5][i]);
      }

      LOG_INF("Pointer field[5] = %p", field[5]);

      double ground_speed_kn = strtod(field[5], NULL);
      double ground_speed_kmh = strtod(field[7], NULL);

      snprintf(str, sizeof(str), "speed knt : %5.4lf, speed kmh : %5.4lf", ground_speed_kn, ground_speed_kmh);
      LOG_INF("VTG %s", str);

    }

str is defined like this 

 static char str[128];

And here is my terminal output:

[00:01:28.277,832] <inf> nmea_parser: #0 : $GNVTG
[00:01:28.277,893] <inf> nmea_parser: #1 : 86.89
[00:01:28.277,923] <inf> nmea_parser: #2 : T
[00:01:28.277,954] <inf> nmea_parser: #3 : 
[00:01:28.278,015] <inf> nmea_parser: #4 : M
[00:01:28.278,045] <inf> nmea_parser: #5 : 0.982
[00:01:28.278,076] <inf> nmea_parser: #6 : N
[00:01:28.278,137] <inf> nmea_parser: #7 : 1.819
[00:01:28.278,167] <inf> nmea_parser: #8 : K
[00:01:28.278,198] <inf> nmea_parser: #9 : A
[00:01:28.278,259] <inf> nmea_parser: Field[5]
                                      30 2e 39 38 32                                   |0.982            
[00:01:28.278,289] <inf> nmea_parser: Field[7]
                                      31 2e 38 31 39                                   |1.819            
[00:01:28.278,320] <inf> nmea_parser: Check string for strtod: '0.982'
[00:01:28.278,350] <inf> nmea_parser: field[5][0] = 0x30
[00:01:28.278,350] <inf> nmea_parser: field[5][1] = 0x2e
[00:01:28.278,381] <inf> nmea_parser: field[5][2] = 0x39
[00:01:28.278,381] <inf> nmea_parser: field[5][3] = 0x38
[00:01:28.278,411] <inf> nmea_parser: field[5][4] = 0x32
[00:01:28.278,472] <wrn> cbprintf_package: (unsigned) char * used for %p argument. It's recommended to cast it to void * because it may cause misbehavior in certain configurations. String:"Pointer field[5] = %p" argument:0
[00:01:28.278,503] <inf> nmea_parser: Pointer field[5] = 0x2001c94c
[00:01:28.278,930] <inf> nmea_parser: VTG speed knt : 1133871366.0000, speed kmh : -1099511628.0000

As you can see I have a good value in field[5] (0.982) and pointer addr seems to be good also 0x2001c94c. But strtod always retunr big false number don't unerstand why. In my prj.conf I've added

CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

In fact I don't need double for VTG but I'll have to use double for lat and long,..

Parents
  • Hello,

    is CONFIG_FPU=y enabled in your application? Also, double values are not supported in hardware, but are emulated. Is there any specific reason why you don't just use regular float?

  • No I can use float, but for example if instead of strtod I use strtof I have the same result for example:

    if ((strcmp(&field[0][3], "VTG") == 0) && (f > 8)) {
    
          LOG_INF("Check string for strtod: '%s'", field[5]);
          for (int i = 0; i < strlen(field[5]); i++) {
              LOG_INF("field[5][%d] = 0x%02x", i, field[5][i]);
          }
    
    
          char tmp_kn[16] = {0};
          char tmp_kmh[16] = {0};
          strncpy(tmp_kn, field[5], sizeof(tmp_kn) - 1);  
          strncpy(tmp_kmh, field[7], sizeof(tmp_kmh) - 1);
    
          float ground_speed_kn = strtof(tmp_kn, NULL);
          float ground_speed_kmh = strtof(tmp_kmh, NULL);
    
          snprintf(str, sizeof(str), "speed knt : %.4f, speed kmh : %.4f", ground_speed_kn, ground_speed_kmh);
          LOG_INF("VTG %s", str);
    }

    I got in my terminal:

    <inf> nmea_parser: #0 : $GNVTG
    <inf> nmea_parser: #1 : 
    <inf> nmea_parser: #2 : T
    <inf> nmea_parser: #3 : 
    <inf> nmea_parser: #4 : M
    <inf> nmea_parser: #5 : 0.179
    <inf> nmea_parser: #6 : N
    <inf> nmea_parser: #7 : 0.331
    <inf> nmea_parser: #8 : K
    <inf> nmea_parser: #9 : A
    <inf> nmea_parser: Check string for strtod: '0.179'
    <inf> nmea_parser: field[5][0] = 0x30
    <inf> nmea_parser: field[5][1] = 0x2e
    <inf> nmea_parser: field[5][2] = 0x31
    <inf> nmea_parser: field[5][3] = 0x37
    <inf> nmea_parser: field[5][4] = 0x39
    <inf> nmea_parser: VTG speed knt : 1043811264.0000, speed kmh : 1051293888.0000

    So my nmea sentece seems to be good, my value also, but when i'm try to print I got bad value, should I add to enable FPU for float also ?

    Edit: If I use sscanf instead of strtof everything works well...

Reply
  • No I can use float, but for example if instead of strtod I use strtof I have the same result for example:

    if ((strcmp(&field[0][3], "VTG") == 0) && (f > 8)) {
    
          LOG_INF("Check string for strtod: '%s'", field[5]);
          for (int i = 0; i < strlen(field[5]); i++) {
              LOG_INF("field[5][%d] = 0x%02x", i, field[5][i]);
          }
    
    
          char tmp_kn[16] = {0};
          char tmp_kmh[16] = {0};
          strncpy(tmp_kn, field[5], sizeof(tmp_kn) - 1);  
          strncpy(tmp_kmh, field[7], sizeof(tmp_kmh) - 1);
    
          float ground_speed_kn = strtof(tmp_kn, NULL);
          float ground_speed_kmh = strtof(tmp_kmh, NULL);
    
          snprintf(str, sizeof(str), "speed knt : %.4f, speed kmh : %.4f", ground_speed_kn, ground_speed_kmh);
          LOG_INF("VTG %s", str);
    }

    I got in my terminal:

    <inf> nmea_parser: #0 : $GNVTG
    <inf> nmea_parser: #1 : 
    <inf> nmea_parser: #2 : T
    <inf> nmea_parser: #3 : 
    <inf> nmea_parser: #4 : M
    <inf> nmea_parser: #5 : 0.179
    <inf> nmea_parser: #6 : N
    <inf> nmea_parser: #7 : 0.331
    <inf> nmea_parser: #8 : K
    <inf> nmea_parser: #9 : A
    <inf> nmea_parser: Check string for strtod: '0.179'
    <inf> nmea_parser: field[5][0] = 0x30
    <inf> nmea_parser: field[5][1] = 0x2e
    <inf> nmea_parser: field[5][2] = 0x31
    <inf> nmea_parser: field[5][3] = 0x37
    <inf> nmea_parser: field[5][4] = 0x39
    <inf> nmea_parser: VTG speed knt : 1043811264.0000, speed kmh : 1051293888.0000

    So my nmea sentece seems to be good, my value also, but when i'm try to print I got bad value, should I add to enable FPU for float also ?

    Edit: If I use sscanf instead of strtof everything works well...

Children
No Data
Related