This is a very common issue on embedded systems like the STM32. The standard printf function is often not fully implemented in the Arduino core to save space, especially the parts that format floating-point numbers (like %f).
Here are the best ways to solve this, from easiest to most robust.
Method 1: Check for a "printf float" Build Flag (The Best Fix)
Many STM32 Arduino cores (like the popular STM32duino) let you enable full printf support. This is the cleanest solution, as it will make your original Serial1.printf(...) code work perfectly.
- In the Arduino IDE, go to the Tools menu.
- Look for options related to your STM32 board.
- Find a setting like "C runtime library" or "printf/scanf float support".
- If you see it, change the value to one that includes float support (e.g., "Newlib-nano with float printf" or "Enabled").
If you find and enable this option, recompile and upload. Your Serial1.printf line should now work.
Method 2: Use sprintf (The Standard C Way)
If you can't find the build flag, the most standard C/C++ approach is to use sprintf (string print format) to build your string in a character buffer first, and then print that buffer to the serial port.
- Include
stdio.h(which you already have). - Define a buffer: Create a character array large enough to hold your final string.
- Use
sprintf: Call the function to format your variables into the buffer. - Print the buffer: Use
Serial1.print()to send the result.
Here is how you would adapt your code:
// ... inside your loop()
if (millis() - timer > 1000) {
timer = millis(); // reset the timer
// ... (all your variable assignments for LatD, LatM, etc. go here) ...
int H=(GPS.hour);
int Mn=(GPS.minute);
int S = (GPS.seconds);
int nb =((int)GPS.satellites);
String T= (String(H)+":"+String(Mn)+":"+String(S));
int Sp=(GPS.speed);
int Cog=(GPS.angle);
float Long =(GPS.longitude);
// Be careful: Long60 is not defined in your sketch.
// I'll assume you meant (LongD * 100) based on your other code.
// float LongS =( Long-(LongD*100))/-1000; // Example fix
int LongD =(GPS.longitude)/100;
int LongM= ((GPS.longitude)-(LongD*100));
float LongS = (Long - (LongD * 100 + LongM)) * 60; // Just guessing at your GPS math
char Long1=(GPS.lon);
int Lat2=(GPS.latitude);
float Lat =(GPS.latitude);
// float LatS =( (Lat2- Lat)-60); // This logic seems circular
int LatD =(GPS.latitude)/100;
int LatM =((GPS.latitude)-(LatD*100));
float LatS = (Lat - (LatD * 100 + LatM)) * 60; // Just guessing at your GPS math
char Lat1=(GPS.lat);
// 1. Define a buffer
// Make it large enough for your whole string. 150-200 chars should be safe.
char buffer[200];
// 2. Use sprintf to format the string into the buffer
// This is the C-standard printf function.
sprintf(buffer, "%.2i-%i'%2.3f%c-%.2i-%i'%2.3f%c-%.2i-%.2i-%i-%.2i-%.2i-%.2i\n",
LatD, LatM, LatS, Lat1,
LongD, LongM, LongS, Long1,
Sp, nb, Cog, H, Mn, S);
// 3. Print the buffer to Serial1
Serial1.print(buffer);
// You can now delete your String concatenation method
// String message = ...
// Serial1.println(message);
}
What If Method 2 Still Fails? (The Float Problem)
If you use sprintf and your output looks strange (e.g., the floats just show up as ? or f), it means sprintf also doesn't have float support enabled.
In this case, you must convert the floats to strings manually using the classic Arduino dtostrf() function (double to string float).
Here's the combined sprintf + dtostrf solution:
// ... inside your loop()
if (millis() - timer > 1000) {
timer = millis(); // reset the timer
// ... (all your variable assignments go here) ...
// ... LatD, LatM, LatS, Lat1, etc...
float LatS = ...; // Your calculation
float LongS = ...; // Your calculation
// 1. Create buffers for your floats
char lat_buffer[10]; // Buffer for LatS
char lon_buffer[10]; // Buffer for LongS
// 2. Convert floats to strings
// dtostrf(float_variable, min_width, num_decimal_places, destination_buffer);
dtostrf(LatS, 4, 3, lat_buffer); // (e.g., "12.345" -> min width 4, 3 decimals)
dtostrf(LongS, 4, 3, lon_buffer);
// 3. Define your main buffer
char buffer[200];
// 4. Use sprintf, but use %s (string) for the floats
sprintf(buffer, "%.2i-%i'%s%c-%.2i-%i'%s%c-%.2i-%.2i-%i-%.2i-%.2i-%.2i\n",
LatD, LatM, lat_buffer, Lat1, // <-- Use lat_buffer
LongD, LongM, lon_buffer, Long1, // <-- Use lon_buffer
Sp, nb, Cog, H, Mn, S);
// 5. Print the final buffer
Serial1.print(buffer);
}
A Note on Your String Method
Your current solution using String concatenation works, but it's generally discouraged on microcontrollers like the STM32:
String message = String(LatD)+"-"+String(LatM)+...
- Memory Usage: It uses dynamic memory allocation, which can fragment the small amount of RAM you have.
- Speed: It's much slower than
sprintf.
For small, simple strings, it's fine. But for complex, repetitive formatting like this, sprintf (Method 2) or dtostrf (Method 3) are much more stable and efficient.