Function dtostrf not declared

Hello, again.
So tried to convert a float value from the reading of the GPS shield to a char value, so that way I can store it in the MKR MEM shield's flash memory, but for some reason when I compile the code:

/*  file.lseek(0, START); /* Rewind file pointer to the start */
//  char buf[64] = {0};
//  int const bytes_read = file.read(buf, sizeof(buf));
// buf[bytes_read] = '\0';
//  Serial.println(buf);





#include <SPI.h>
#include <Arduino_MKRGPS.h>
#include <Arduino_MKRMEM.h>

static char const PANGRAM[] = "The quick brown fox jumps over the lazy dogukzewguikzweruiewgiruowerwegiurweuirwezui";
const char* fang = "ejewoidLIKZFUITRDTZ8DUTZRLIZG23986T9238TZUTFGTTTUZE677E66RI988UH7d.";

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  GPS.begin();
  unsigned long const start = millis();
  for(unsigned long now = millis(); !Serial && ((now - start) < 5000); now = millis()) { };
  flash.begin();
  /* ... */
  int res = filesystem.mount();
  if(res != SPIFFS_OK && res != SPIFFS_ERR_NOT_A_FS) {
    Serial.println("mount() failed with error code "); Serial.println(res); return;
  }

  /* ... */
  File file = filesystem.open("data.txt", CREATE | APPEND);
  /* ... */
  if (GPS.available()) {
    // Read GPS data
    float latitude = GPS.latitude();
    float longitude = GPS.longitude();
    float altitude = GPS.altitude();
    float speed = GPS.speed();
    int satellites = GPS.satellites();
  
char buffer[16];
  dtostrf(latitude, 8, 7, buffer);

  file.write((void *)buffer, strlen(PANGRAM));
  file.write((void *)fang, strlen(PANGRAM));
  /* ... */}
  file.lseek(0, START); /* Rewind file pointer to the start */
  char buf[2048] = {0};
  int const bytes_read = file.read(buf, sizeof(buf));
  buf[bytes_read] = '\0';
  Serial.println(buf);
  
  /* ... */
  file.close();
  unsigned int bytes_total = 0,
               bytes_used = 0;
  if(SPIFFS_OK != filesystem.info(bytes_total, bytes_used)) {
    Serial.println("check() failed with error code "); Serial.println(filesystem.err()); return;
  } else {
    char msg[64] = {0};
    snprintf(msg, sizeof(msg), "SPIFFS Info:\nBytes Total: %d\nBytes Used:  %d", bytes_total, bytes_used);
    Serial.println(msg);
  }
  filesystem.unmount();
}

void loop() {

}

returns with an error:

C:\Users\user\OneDrive\Documents\Arduino\sketch_sep14a\sketch_sep14a.ino: In function 'void setup()':
C:\Users\user\OneDrive\Documents\Arduino\sketch_sep14a\sketch_sep14a.ino:45:3: error: 'dtostrf' was not declared in this scope
   dtostrf(latitude, 8, 7, buffer);
   ^~~~~~~
C:\Users\user\OneDrive\Documents\Arduino\sketch_sep14a\sketch_sep14a.ino:45:3: note: suggested alternative: 'strstr'
   dtostrf(latitude, 8, 7, buffer);
   ^~~~~~~
   strstr

exit status 1

Compilation error: 'dtostrf' was not declared in this scope

I've looked over the internet and websites say that the dtostrf function is supposed to be implemented in the arduino....

Perhaps the MKR version of sprintf() supports floats, in which case you don't need dtostrf().

Try it and see, following this example:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial) yield();
  Serial.println("sprintf float test");

  float x=1.234;
  char buf[40];
  sprintf(buf,"x = %8.4f, cos(x) = %8.4f",x, cos(x));
  Serial.println(buf);
}

void loop() {
}

There are many families under the Arduino umbrella. What is true In the AVR family is not always true, for example, in the SAMD family.

Perhaps a read of the Compilation error dtostrf thread might be enlightening.

Can you send a link to where you got this code, I want to know what each command and variable does myself. In case this is your code I would be very grateful if you could explain the 9th line sprintf(buf,"x = %8.4f, cos(x) = %8.4f",x, cos(x));. Thanks

I wrote that code.

Details of sprintf() format statements can be found on the C/C++ reference pages for printf().

Just tried to run it and got this output:

20:33:05.785 -> sprintf float test
20:33:05.785 -> x = , cos(x) = 

Is it supposed to equal to nothing or...?

That means that sprintf() does not support floats, using the default libraries.

Have you followed the advice in post #3?

So unless I install some library that might work, writing float values to a MKR board is impossible.

Serial.print() prints floating point values on all Arduinos. To set the number of digits past the decimal point, use this (for 5):

Serial.println(x, 5);

yeah, I kinda of worded it badly. What I meant is that there is no way to write the float values to a flash on a MKR MEM

I know how to simply print it on the serial monitor, yeah

Why would you want to store formatted character strings to flash memory? Store binary values instead, and save space.

Sure, but the idea is to store it there temporarily and then send it to the cloud. I would like to use as little space as possible for the program itself. But if you think there is no other way I can also convert it to binary and then back...

Incorrect. You've already been pointed to a solution which does work, but you appear to be ignoring it.

I guess you're referring to the 3rd reply. I'll dig into it.

Does it make a difference if you

  • convert the float to ASCII and store it as binary chars (more than 4 bytes ...!)
  • load the ASCII data and send them to the cloud

or

  • store the float (directly as binary data -> 32 bit -> 4 bytes)
  • load the float, convert it to ASCII and send them to the cloud

P.S.: I think this line

file.write((void *)buffer, strlen(PANGRAM));

should read

file.write((void *)buffer, sizeof(buffer));

as the second parameter defines the number of bytes to write. buffer is only 16 bytes long ...

I cannot test it but you may try to write and read the float like this

// Write 4 bytes
file.write((void *)latitude, 4);


// Read 4 bytes
file.read((void *)latitude, 4);

No guarantee, it may be worth a try ...

Good luck!

That didn't work, unfortunately, but I got the dtostrf working, just one quick question if anyone knows the answer to, does file.read (this command is under MKRMEM library and has no connection to the main topic) only read one singular line of text or is there a way to read multi-line text

If you look up the library

https://github.com/arduino-libraries/Arduino_MKRMEM/blob/master/src/Arduino_SPIFFS_File.cpp

you will find these definitions

/**************************************************************************************
 * PUBLIC MEMBER FUNCTIONS
 **************************************************************************************/

int Arduino_SPIFFS_File::read(void * buf, int len)
{
  return filesystem.read(_fh, buf, len);
}

int Arduino_SPIFFS_File::write(void * buf, int len)
{
  return filesystem.write(_fh, buf, len);
}

read and write require a pointer to data and the number of bytes (to read or write) independent of the type of data. These functions do not take care of delimiters like '\0' as end of string.

You wrote that the suggested functions did not work. Would you mind to post how you used them and what the result was?

So for example in this code :

#include <SPI.h>
#include <Arduino_MKRGPS.h>
#include <Arduino_MKRMEM.h>
void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  GPS.begin();
  unsigned long const start = millis();
  for(unsigned long now = millis(); !Serial && ((now - start) < 5000); now = millis()) { };
  flash.begin();
  /* ... */
  int res = filesystem.mount();
  if(res != SPIFFS_OK && res != SPIFFS_ERR_NOT_A_FS) {
    Serial.println("mount() failed with error code "); Serial.println(res); return;
  }
 
  /* ... */
 Serial.println("Staring GPS...");
  /* ... */
}

void loop() {
if (GPS.available()) {
    // Read GPS data
    float latitude = GPS.latitude();
    float longitude = GPS.longitude();
    float altitude = GPS.altitude();
    float speed = GPS.speed();
    int satellites = GPS.satellites();

File file = filesystem.open("data.txt", CREATE | TRUNCATE | READ_WRITE | APPEND);

file.write((void *)longitude, 4);
}
}

I get this error:

C:\Users\user\AppData\Local\Temp\.arduinoIDE-unsaved2023816-9076-nwipjx.uja8g\sketch_sep16c\sketch_sep16c.ino:36:20: error: invalid cast from type 'float' to type 'void*'
 file.write((void *)longitude, 4);
                    ^~~~~~~~~

exit status 1

Compilation error: invalid cast from type 'float' to type 'void*'

I would assume this means that we must convert it with dtostrf.

But about the first part, where you mentioned the definitions, I would also assume that _fh means file handle?
I'm still quite new to this stuff so I may be saying some dumb things....

You got the error because that code is nonsense. Better to ignore ec2021's misguided contribution.

This should work to store the binary value of latitude, if that is what you want to do.

 file.write((char *)&longitude, 4);

Sorry for the misleading suggestion ...

If you read the sketch from post #1 you'll find the lines

file.write((void *)buffer, strlen(PANGRAM));
 file.write((void *)fang, strlen(PANGRAM));
 

Also in the library the cast of void* buf is used.

As I stated: Not tested, but worth a try. Hopefully it leads to a solution now ...