Can you sprintf in Arduino with SAMD

I have some sprintf commands that were working in the Arduino IDE, but after moving my program over to PlatformIO, they don’t seem to put anything into the char array. I am using an Adafruit ItsyBitsy M4, which is a Atmel SAMD 54.

char charBuf[20];
float sprintf(charBuf, "Ping: %.2f (s)", seconds);
Serial.println(charBuf);

It’s supposed to go to a TFT, but this shows the same issue - I get “Ping: (s)”

I did some searching on this forum, and I see a couple of posts about STM32 and setting a build flag, but they didn’t work, and I couldn’t see any flags for SAMD boards. The posts said that the sprintf was disabled on that architecture because of memory constraints. Is it disabled for SAMD boards too?

Writing float in front of the sprintf function call like that should give you a compile error. Is this the real code?

i use this function:

.h file:

#include <stdarg.h>
String s_printf(const char* format, ...)  __attribute__((format(printf, 1, 2)));

.cpp file:

String s_printf(const char* format, ...)
{
    char loc_buf[64];
    char* temp = loc_buf;
    va_list arg;
    va_list copy;
    va_start(arg, format);
    va_copy(copy, arg);
    int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
    va_end(copy);
    if (len < 0) {
        va_end(arg);
        return "";
    };
    if (len >= sizeof(loc_buf)) {
        temp = (char*)malloc(len + 1);
        if (temp == NULL) {
            va_end(arg);
            return "";
        }
        len = vsnprintf(temp, len + 1, format, arg);
    }

    va_end(arg);        

    String s = String(temp);
    

    if (temp != loc_buf) {
        free(temp);
    }
    return s;

}

@maxgerhardt oops. Should be float seconds = 10.1 on one line, the sprintf on the next…. I was reusing seconds a few times in my clode and botched my example.

@savejeff is there a reason sprintf doesn’t work on platformio and you need this method?

i found this method to be the one that works on all platforms meaning SAMD, STM, ESP, Pico. with the correct compiler flags it even works on AVR.
i like to get a String from my sprint func instead of creating a char buffer. its just easier and the code is cleaner. you can do
Serial.print(s_printf(...)); in on line even if the Serial does not offer sprintf itself.

I think you are refering to Arm mbed: Serial.printf() fails to emit floats when using platformio - #5 by valeros. These flags absolutely work. They are not STM32 specific, they are specific to arm-none-eabi-gcc’s C library, so it applies to all ARM targets.

If I do

[env:adafruit_feather_m0]
platform = atmelsam
board = adafruit_feather_m0
framework = arduino
build_flags = -Wl,-u_printf_float
monitor_speed = 115200
monitor_dtr = 1

with code

#include <Arduino.h>

void setup() { Serial.begin(115200); }
void loop() {
   char charBuf[20] = {};
   float seconds = 1.3f;
   sprintf(charBuf, "Ping: %.2f (s)", seconds);
   Serial.println(charBuf);
   delay(1000);
}

I get

--- Miniterm on COM6  115200,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
Ping: 1.30 (s)
Ping: 1.30 (s)

So, no problems & no additional function needed. Just enable it in the C library.

If that still doesn’t work for you, post your complete platformio.ini.

Thanks @maxgerhardt I must have not done the build_flags correctly. I think I had a different one or two that I tried, but that worked. That was very frustrating. Very glad to have that solved.

1 Like