HOWTO · Arduino

Fonction d'impression Arduino

On peut obtenir le même résultat que printf() en utilisant la fonction sprintf() et la fonction Serial.print().

Sur cette page

L’environnement de programmation Arduino standard ne fournit pas d’appel printf() portable qui écrive dans le moniteur série. Certains cœurs de carte ajoutent leur propre méthode Serial.printf() ; consultez donc la documentation de la carte choisie. Pour écrire des sketches portables, formatez le texte dans un tableau de caractères avec sprintf(), puis envoyez-le avec Serial.print() ou Serial.println(). Si vous n’avez pas besoin d’une chaîne de format, plusieurs appels série permettent de construire directement le même message.

Arduino fournit-il printf() ?

Aucune interface printf() unique n’est garantie sur toutes les cartes Arduino. La fonction printf() de la bibliothèque C écrit normalement dans un flux de sortie standard, que l’environnement d’un microcontrôleur ne relie pas forcément à un port série. Une méthode Serial.printf() propre à un cœur peut exister, mais sa disponibilité et les spécificateurs de format pris en charge dépendent de la cible. Les sketches ci-dessous utilisent setup() et loop() et écrivent via Serial ; une petite simulation du port série côté hôte permet d’exécuter les mêmes exemples sans carte Arduino. Sur une carte, le cœur Arduino fournit Serial et le cycle de vie du sketch.

Formater du texte avec sprintf() et l’envoyer sur le port série

Utilisez sprintf() lorsqu’un message nécessite des espaces réservés ou un remplissage. Cette fonction écrit le texte complet dans un tableau de caractères ; Serial.println() envoie ensuite ce texte suivi d’un saut de ligne. Ce sketch utilise snprintf() pour transmettre au formateur la capacité du tableau, puis vérifie que le message complet tient avant de l’envoyer :

#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() renvoie le nombre de caractères qu’elle aurait écrits, sans compter le caractère nul final. Si ce nombre est supérieur ou égal à la capacité du tableau, le sketch n’envoie pas de message partiel. Vérifiez que la bibliothèque C de la carte choisie fournit snprintf() comme prévu ; la disponibilité et le comportement des fonctions de formatage peuvent varier selon la carte et son cœur.

Construire la sortie avec Serial.print()

Pour de simples libellés et valeurs, les appels directs évitent d’utiliser un tampon de formatage temporaire. Serial.print() continue sur la même ligne ; Serial.println() la termine. Ce sketch assemble la même ligne avec des appels série :

#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%

La simulation côté hôte reproduit les appels utilisés ici afin de montrer la ligne du sketch sans matériel ; elle ne constitue pas un cœur Arduino. Sur la carte, Serial.print(humidity, 1) demande un chiffre après la virgule, et le formatage exact pris en charge dépend de l’implémentation de Serial de la carte.

Gérer les nombres à virgule flottante et les limites du tampon

Le formatage des nombres à virgule flottante avec sprintf() n’est pas uniforme d’un cœur Arduino à l’autre : certaines bibliothèques C embarquées omettent la conversion des nombres flottants dans les fonctions de formatage afin d’économiser de la mémoire programme. Vérifiez le cœur cible avant de compter sur %f. La forme directe Serial.print(value, digits) constitue une autre option lorsque le cœur prend en charge l’implémentation Arduino habituelle de Print.

Toute sortie formatée doit tenir dans son tableau de caractères, caractère \0 final compris. Lorsque c’est possible, utilisez snprintf() avec la capacité réelle du tableau et vérifiez sa valeur de retour avant d’utiliser le résultat. Si le texte formaté dépasse la taille du tableau, agrandissez le tampon ou raccourcissez le message. Un tampon plus grand consomme davantage de RAM, une ressource limitée sur de nombreuses cartes.

Choisir la bonne méthode

Choisissez sprintf() ou snprintf() lorsqu’une seule chaîne de format rend un message structuré plus lisible, puis envoyez le résultat avec Serial.println(). Choisissez plusieurs appels à Serial.print() si vous avez seulement besoin d’assembler quelques libellés et valeurs. Les deux méthodes envoient du texte par l’interface série ; aucune ne garantit une prise en charge identique du formatage sur toutes les cartes. Vérifiez les méthodes propres au cœur et le comportement des nombres flottants pour la carte sur laquelle vous compilez.