Serial printf implementation
The problem with your code is that you are mixing the "normal" and "variadic" forms of the printf functions.

Any printf function starting with V takes a variadic argument list pointer as its last variable. Any printf function which doesn't start with V takes a variadic list of individual variables.

When calculating your buffer size from a list of variables in your main loop you are incorrectly using vsnprintf - you should be using snprintf since you aren't passing it a va_list, but individual variables. In your _printf function you are correctly using vsnprintf to calculate the length of the buffer, but then incorrectly using sprintf with a va_list instead of individual variables.

So your two forms should actually be re-written as:

// Inline version
char buf0[snprintf(NULL, 0, "pin %i configured to output", PIN) + 1];
sprintf(buf0, "pin %i configured to output", PIN);
Serial.println(buf0);


and:

void _printf(char *fmt, ...) {
  va_list va;
  va_start(va, fmt);
  char buf[vsnprintf(NULL, 0, fmt, va) + 1];
  vsprintf(buf, fmt, va);
  Serial.println(buf);
  va_end(va);
}


Remember: if you have a va_list then it goes with a v*printf function. If you have individual variables they go with a *printf function.