2

I've got a uBlox Neo 7N GPS Module and configured it so if theres is no incoming data print no location but if there is print the latitude and longitude. However it's printing ?,?.

So I'm assuming it's wired correctly as I'm getting an output however maybe my code is preventing it from printing the two long numbers hence converting it to a ? instead.

  char buf[128];   
  if (gps.location.isValid()) {
    snprintf(buf, sizeof(buf), "%lf,%lf", gps.location.lat(), gps.location.lng());
    Serial.println(buf);
  }

EDIT I know that Im getting a read as I set two variables of type double lat and long to equal gps.location.lat() and gps.location.lng() respectively and I'm getting a number. How do I fix up this snprintf line so it prints properly?

4
  • When arduino boards used the atmega8, there was so little memory they decided to take out the floating point support for s(n)printf. Instead of letting the users decide to use sprintf or not, they just took it out. That caused a lot of troubles. In 2018 it is still not there, which is outrageous. Sorry that you bumped into this problem. You have to make a workaround. It can be cast to a unsigned long or the dstrtof function can be used and the Serial.println itself supports float variables. The uno does not support 64 bit double, only 32 bit float variables.
    – Jot
    Aug 26, 2018 at 6:30
  • Oh wow, well that makes sense. Thank you for replying, will try your recommendation!
    – Explorex
    Aug 26, 2018 at 6:36
  • Oops, it is "dtostrf".
    – Jot
    Aug 26, 2018 at 6:48
  • I would try adjusting the baud rate your arduino or MCU is reading the GPS data stream at. My guess is that the stream is being misinterpreted.
    – j0h
    Aug 26, 2018 at 15:27

1 Answer 1

3

No floating point for sprintf, it prints a '?'.

The functions sprintf, sscanf and the alike functions (snprintf and others) do not have floating point support for avr microcontrollers.

History

One of the first Arduino boards used the Atmega8 microcontroller with only 8k flash and 1k sram. It was important to be very memory efficient.
The gcc compiler did not automatically include the floating point support libraries for the sprintf functions, however it was easy to include them. Arduino decided not to include those extra libraries because they use extra memory.

Arduino has a preprocessor, compiler and linker that tries to only use code that is actually used. The sprintf does not know at compile time if floating point will be used, so it would have to include those extra floating point support libraries whether they were used or not.

Now it is 2018 and it is sadly still not included.

Workaround

  • The Serial.println functions can print floating point variables. They can however not print the output in scientific notation. It rounds the value that is printed to the nearest number.
  • The dtostrf() and dtostre() convert a float variable to text. The dtostre() is for scientific notation.
  • A variable of the float type can be cast to a integer.
  • The Arduino String object can handle a float.

Only float for avr microcontrollers, no double.

The avr microcontrollers are 8-bit microcontrollers. There is no floating point library for 64-bit double variables, only a library for 32-bit float variables.
That library is according to the IEEE standard and is extremely fast and optimized.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.