HOWTO · Arduino

Función printf de Arduino

Uno puede obtener el mismo resultado que printf() usando la función sprintf() y la función Serial.print().

En esta página

El entorno de programación estándar de Arduino no ofrece una llamada portátil a printf() que escriba en el monitor serie. Algunos núcleos de placa incorporan su propio método Serial.printf(), así que consulta la documentación de la placa que uses. Para escribir sketches portátiles, formatea el texto en un búfer de caracteres con sprintf() y envíalo mediante Serial.print() o Serial.println(). Si no necesitas una cadena de formato, puedes construir el mismo mensaje directamente con varias llamadas al puerto serie.

¿Arduino proporciona printf()?

No hay una interfaz printf() única garantizada para todas las placas Arduino. La función printf() de la biblioteca C suele escribir en un flujo de salida estándar, que en un entorno de microcontrolador puede no estar conectado a un puerto serie. Algunos núcleos ofrecen un método específico, Serial.printf(), pero su disponibilidad y los especificadores de formato admitidos dependen de la placa. Los sketches siguientes usan setup() y loop() y escriben mediante Serial; un pequeño sustituto del puerto serie en el equipo anfitrión permite mostrar los mismos ejemplos sin una placa Arduino. En una placa, el núcleo de Arduino proporciona Serial y el ciclo de vida del sketch.

Dar formato al texto con sprintf() y enviarlo por el puerto serie

Usa sprintf() cuando un mensaje necesite marcadores de posición o espacios de relleno. La función escribe el texto completo en un arreglo de caracteres; después, Serial.println() envía ese texto seguido de un salto de línea. Este sketch usa snprintf() para indicar al formateador la capacidad del arreglo y comprueba que el mensaje completo quepa antes de enviarlo:

#include <cstdio>

#ifdef ARDUINO
#include <Arduino.h>
#else
class HostSerial {
 public:
  void begin(unsigned long) {}
  void println(const char* text) { std::puts(text); }
};
HostSerial Serial;
#endif

void setup() {
  Serial.begin(9600);
  char buffer[32];
  const int value = 42;
  const int length = std::snprintf(buffer, sizeof(buffer), "The answer is: %d", value);
  if (length >= 0 && static_cast<unsigned int>(length) < sizeof(buffer)) {
    Serial.println(buffer);
  }
}

void loop() {}

#ifndef ARDUINO
int main() {
  setup();
  return 0;
}
#endif
The answer is: 42

snprintf() devuelve la cantidad de caracteres que escribiría, sin contar el carácter nulo final. Si esa cantidad es igual o superior a la capacidad del arreglo, el sketch no envía un mensaje parcial. Comprueba que la biblioteca C de la placa elegida proporcione snprintf() como se espera; la disponibilidad y el comportamiento de las funciones de formato pueden variar según la placa y el núcleo.

Construir la salida con Serial.print()

Para etiquetas y valores sencillos, las llamadas directas evitan usar un búfer temporal de formato. Serial.print() continúa en la misma línea; Serial.println() la termina. Este sketch construye la misma línea mediante llamadas al puerto serie:

#include <cstdio>

#ifdef ARDUINO
#include <Arduino.h>
#else
class HostSerial {
 public:
  void begin(unsigned long) {}
  void print(const char* text) { std::printf("%s", text); }
  void print(int value) { std::printf("%d", value); }
  void print(double value, int digits) { std::printf("%.*f", digits, value); }
  void println(const char* text) { std::printf("%s\n", text); }
};
HostSerial Serial;
#endif

void setup() {
  Serial.begin(9600);
  const int temperature = 25;
  const double humidity = 60.5;
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print(" C, Humidity: ");
  Serial.print(humidity, 1);
  Serial.println("%");
}

void loop() {}

#ifndef ARDUINO
int main() {
  setup();
  return 0;
}
#endif
Temperature: 25 C, Humidity: 60.5%

El sustituto del puerto serie en el equipo anfitrión reproduce las llamadas usadas aquí para mostrar la línea del sketch sin hardware; no es un núcleo de Arduino. En la placa, Serial.print(humidity, 1) solicita un dígito después del separador decimal, y el formato exacto admitido depende de la implementación de Serial de la placa.

Valores de punto flotante y límites del búfer

El formato de valores de punto flotante mediante sprintf() no es uniforme en todos los núcleos de Arduino: algunas bibliotecas C integradas omiten la conversión de valores flotantes en la entrada/salida con formato para ahorrar memoria de programa. Comprueba el núcleo de destino antes de depender de %f. La forma directa Serial.print(value, digits) es una alternativa cuando el núcleo admite la implementación habitual de Print de Arduino.

Toda salida con formato debe caber en su arreglo de caracteres, incluido el carácter nulo final \0. Cuando esté disponible, usa snprintf() con la capacidad real del arreglo y comprueba el valor que devuelve antes de usar el resultado. Si el texto formateado supera el tamaño del arreglo, amplía el búfer o acorta el mensaje. Un búfer más grande consume más RAM, un recurso limitado en muchas placas.

Elegir el método adecuado

Elige sprintf() o snprintf() cuando una sola cadena de formato facilite la lectura de un mensaje estructurado, y envía el resultado con Serial.println(). Elige llamadas a Serial.print() cuando solo necesites unir unas pocas etiquetas y valores. Ambos métodos envían texto por la interfaz serie; ninguno garantiza la misma compatibilidad de formato en todas las placas. Comprueba los métodos específicos del núcleo y el comportamiento de los valores flotantes para la placa en la que compilarás.