Débuter Arduino. Fonctions pour combiner, formater des variables vers le port série (compatible ESP32, ESP8266)

Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

On utilise le moniteur série pour mettre au point le code Arduino, mais il est possible de faire bien d’autres choses. Nous allons découvrir dans cet article les principales méthodes pour imprimer (envoyer) des chaînes de caractères sur le port série. print et println pour envoyer du texte simple. La fonction printf pour convertir, formater et combiner plusieurs variables dans une même chaîne de caractère. sprintf et snprintf pour stocker le résultats dans une variable.

 

Accès rapide aux fonctions

 print ou println   printf   options printf   sprintf write

Comment ouvrir le port série dans le code Arduino ?

Avant de pouvoir envoyer des messages sur le port série, il est nécessaire d’initialiser la communication avec la commande Serial.begin(vitesse). Cette méthode prend comme paramètre la vitesse du port série en bauds.

Par défaut, elle est fixée à 9600 bauds.

Vous pouvez opter pour l’une de ces vitesses 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, ou 115200.

La plupart des cartes de développement actuelles supportent sans aucun problème la vitesse de 115200 bauds.

Serial.begin(115200);

Imprimer du texte sur le port série avec print ou println

La fonction print() est la fonction de base. Elle permet d’envoyer (imprimer) un caractère ou une chaine de caractères sans aucun formatage particulier.

Les caractères sont envoyés sur le port série les uns à la suite des autres.

Exemple Résultat sur le moniteur série
Serial.print("A");
Serial.print("B");
Serial.print("C");
ABC

Pour renvoyer le curseur à la ligne (comme sur un traitement de texte), il existe plusieurs solutions :

  • Utiliser la méthode println()
  • Ajouter \n à la fin de la chaîne publiée
  • Combiner les deux

Exemple Résultat obtenu sur le moniteur série
Serial.print("Une demo ");
Serial.print("avec ");
Serial.println("un retour à la ligne ");
Une demo avec
un retour à la ligne
Equivalent
Serial.print("Une demi avec \n");
Serial.print("un retour à la ligne");
Une demo avec
un retour à la ligne

Comment combiner plusieurs variables avec print ou println

Comme dans la plupart des autres langages (Javascript, PHP..), le C++ autorise de combiner des chaînes à l’aide de l’opérateur +. Il faudra au préalable convertir la donnée en chaîne à l’aide de la fonction String().

Voici un exemple qui combine dans une même chaîne de caractère une variable de type entier, une variable de type float (nombre décimal) et un booléen.

int INT_VAR = 32;
float FLOAT_VAR = 32.23;
bool BOOL_VAR = true;
Serial.println("Un chaine qui combine un entier " + String(INT_VAR) + ", un décimal " + String(FLOAT_VAR) + " est un bool " + String(BOOL_VAR));

Combiner et formater plusieurs variables dans une chaîne avec printf

La méthode printf() permet à la fois de formater une ou plusieurs données et ensuite les combiner dans une même chaîne avant de l’envoyer sur le port série.

Pour cela, il suffit de spécifier la position dans la chaîne à l’aide du caractère %.

Serial.printf("la pression atmosphérique est de %u hPa", pressure);

L’argument %specifier sera ensuite remplacé par la valeur mise en forme correspondante.

Pour formater comme on le souhaite la chaine de sortie, il est possible d’ajouter des options supplémentaires. Les options sont détaillés dans les paragraphes suivants.

%[flags][width][.precision][length]specifier

Voici un exemple qui permet de formater un nombre décimal avec un seul chiffre significatif. L’arrondi est automatique.

%.1f

On peut combiner autant de variables qu’on le souhaite. Il faudra simplement passer les variables dans le même ordre que dans la chaîne de sortie.

arduino printf esp32 esp8266 format convert var

Specifier disponibles

Pour pouvoir combiner des variables de natures différentes dans la chaîne de sortie, il faut indiquer à la commande printf le type de chaque données

Attention, choisissez le specifier qui correspond au type de variable déclaré dans le code Arduino.

Specifier Type de données Arduino Description Exemple
d ou i Int

Byte

World

Long (préférable d’utiliser unsigned Int)

Entier décimal signé 392
u Entier décimal non signé 7235
o Octal non signé 610
x unsigned long

unsigned int

Entier hexadécimal non signé (minuscule) 7fa
X Entier hexadécimal non signé (majuscule) 7FA
f ou F float

double

Virgule flottante décimale, minuscule 392.65
e Notation scientifique exposant en minuscule 3.9265e+2
E Notation scientifique exposant en majuscule 3.9265E+2
g Utilisez la représentation la plus courte : %e ou %f 392.65
G Utilisez la représentation la plus courte : %E ou %F 392.65
c char Caractère a
s char [] Chaîne de caractères exemple
n Rien n’est imprimé
% Un % suivi d’un autre caractère % écrira un seul % %

Option Flag (drapeau)

Le flag permet d’ajouter des caractères avant la valeur :

  • Forcer l’ajout d’un signe (+ ou -)
  • Insérer un espace
  • Remplir avec des zéros
  • Remplir avec 0x pour les nombres hexadécimaux

flag Description
- Justifiez à gauche dans la largeur de champ donnée. Par défaut, la justification est à droite de la valeur (voir l’option largeur)
+ Force à faire précéder le résultat d’un signe plus ou moins ( + ou - ) même pour les nombres positifs. Par défaut, seuls les nombres négatifs sont précédés du signe -
(space) Si aucun signe ne doit être écrit, un espace est inséré avant la valeur
# Utilisée avec les specifiers ox ou X, la valeur est précédée de 0 , 0x ou 0X respectivement pour les valeurs différentes de zéro.
Utilisé avec aAeEfF, g ou G, la chaîne de sortie doit contenir un point décimal même si aucun chiffre ne suit. Par défaut, si aucun chiffre ne suit, aucun point décimal n’est écrit
0 Remplit à gauche le nombre avec des zéros (0) au lieu d’espaces lorsque le remplissage est spécifié (voir l’option largeur)

Option width (largeur)

Spécifie (ou pas) le nombre de caractères à imprimer

with Description
(nombre) Nombre minimum de caractères à imprimer. Si la valeur à imprimer est inférieure à ce nombre, le résultat est complété par des espaces vides. La valeur n’est pas tronquée même si le résultat est plus grand
* La largeur n’est pas spécifiée dans la chaîne de formatage, mais sous la forme d’un argument de valeur entière supplémentaire précédant l’argument à mettre en forme

Option Precision (précision)

Permet de définir la précision des nombres décimaux (le nombre de chiffres significatifs à imprimer) ou le nombre maximal de caractères si c’est une chaine.

.precision Description
.nombre
  • Pour d, i, o , u , x , X, la précision spécifie le nombre minimum de chiffres à écrire. Si la valeur à écrire est plus courte que ce nombre, le résultat est complété par des zéros non significatifs. La valeur n’est pas tronquée même si le résultat est plus long. Une précision de 0 signifie qu’aucun caractère n’est écrit pour la valeur 0
  • Pour a, A, E, E, f et F, c’est le nombre de chiffres à imprimer après la virgule décimale (par défaut, il s’agit de 6)
  • Pour g et G, il s’agit du nombre maximal de chiffres significatifs à imprimer
  • Pour s, c’est le nombre maximum de caractères à imprimer. Par défaut, tous les caractères sont imprimés jusqu’à ce que le caractère nul de fin soit rencontré
.* La précision n’est pas spécifiée dans la chaîne de format , mais sous la forme d’un argument de valeur entière supplémentaire précédant l’argument à mettre en forme.

Options de conversion tirées de cet article.

Stocker le résultat d’une chaîne formatée avec sprintf ou snprintf dans une variable

La méthode sprintf() permet de stocker le résultat de la conversion dans une variable de type char[].

Seule restriction, il n’est pas possible de convertir plusieurs variables avec une seule commande.

La commande sprintf() nécessite d’initialiser la variable de sortie avec une taille au moins égale à la longueur de la chaîne. C’est tout simplement le nombre de caractères de la chaîne de sortie.

char output_sprintf[6];
sprintf(output_sprintf, "%.1f°C", temp);
Serial.printf("Valeur formatée enregistrée dans la variable output %s \n", output_sprintf);

Pour combiner plusieurs variables dans une même chaîne, il faudra utiliser la fonction snprintf() qui s’écrit de manière similaire

char output_snprintf[60];
snprintf(output_snprintf, sizeof(output_snprintf), "La température est de %.1f°C, l'humidité est de %.1f%% \n", temp, hum);
Serial.printf("output_snprintf = %s \n", output_snprintf);

Imprimer le contenu d’un buffer de bytes avec write()

On peut être amené à utiliser un tableau de bytes. Ce tableau pourra par exemple contenir le code numérique de chaque caractère d’une String (chaîne de caractères).

Pour imprimer sur le port série un tableau de byte, les fonctions print(), println() ne fonctionnent pas car elles attendent une variable de type char, char[] ou String.

Pour imprimer le contenu d’un buffer avec la fonction write(), il suffit de parcourir ce dernier à l’aide d’une boucle for().

String stringtocopy = "Arduino"; 

// mesure la longueur de la chaine
int buffer_size = stringtocopy.length();
Serial.printf("Buffer size: %u\n", buffer_size);

// Cree un buffer ayant la meme taille que la chaine
byte buffer[buffer_size]; 

// Copie le contenu de la chaine a l'aide de la fonction getBytes
// Attention, il faut ajouter 1 a la taille de la chaine pour ne pas avoir de caractere NULL
stringtocopy.getBytes(buffer, buffer_size + 1); 
Serial.println("Print buffer with write function"); 

// On imprime un a un chaque cellule du buffer a l aide d une boucle for
for (int i = 0; i < buffer_size; i++) { 
  Serial.write(buffer[i]); 
} 
Attention, il faut ajouter 1 à la longueur de la chaîne au niveau du paramètre len de la fonction getBytes, sinon le dernier caractère sera null, par exemple : Arduin␀

Téléverser le code Arduino des exemples

Créer un nouveau croquis sur l’IDE Arduino ou PlatformIO et téléverser le code pour tester tous les exemples présentés précédemment.

#include <Arduino.h>

#define SERIAL_SPEED 115200

void setup() {
  Serial.begin(SERIAL_SPEED);
  
  Serial.println("\n=== print et println ====");
  Serial.print("A");
  Serial.print("B");
  Serial.print("C");

  Serial.println("\n=======");

  Serial.println("Une demo avec ");
  Serial.print("un retour à la ligne ");
  
  Serial.println("\n---- Ou -----");

  Serial.print("Une demo avec \n");
  Serial.print("un retour à la ligne");

  Serial.println("\n=== Concatenation avec println ====");
  int INT_VAR = 32;
  float FLOAT_VAR = 32.23;
  bool BOOL_VAR = true;
  Serial.println("Un chaine qui combine un entier " + String(INT_VAR) + ", un décimal " + String(FLOAT_VAR) + " est un bool " + String(BOOL_VAR));

  Serial.println("\n=== printf ====");
  unsigned int x = 0x999b989;
  byte b = 120;
  word w = 63450;
  unsigned int l = 2147483647; // long
  char c = 65; // A
  char s[] = "une chaîne de caractères";
  float f = 99.57;
  double fdbl = 99.5769;
  Serial.printf("Hexa %x %X \n", x, x);
  Serial.printf("Byte %u \n", b);
  Serial.printf("World %u \n", w);
  Serial.printf("Long %u \n", l);
  Serial.printf("Caractère %c \n", c);
  Serial.printf("%s \n", s);
  Serial.printf("Variable float %f | %.2f \n", f, f);
  Serial.printf("Variable double %f | %.2f \n", fdbl, fdbl);

  Serial.println("\n=== FAKE BME280 ====");
  float temp = 18.68;
  float hum = 67.98;
  Serial.printf("La température est de %.1f°C, l'humidité est de %.1f%% \n", temp, hum);

  char output_sprintf[6];
  sprintf(output_sprintf, "%.1f°C", temp);
  Serial.printf("output_sprintf = %s \n", output_sprintf);
  
  char output_snprintf[60];
  snprintf(output_snprintf, sizeof(output_snprintf), "La température est de %.1f°C, l'humidité est de %.1f%% \n", temp, hum);
  Serial.printf("output_snprintf = %s \n", output_snprintf);

  Serial.println("\n=== write() buffer to Serial ====");
  String stringtocopy = "Arduino"; 
  int buffer_size = stringtocopy.length();
  Serial.printf("Buffer size: %u\n", buffer_size);
  byte buffer[buffer_size]; 
  stringtocopy.getBytes(buffer, buffer_size + 1); 
  Serial.println("Print buffer with write() function"); 
  for (int i = 0; i < buffer_size; i++) { 
    Serial.write(buffer[i]); 
  }
}

void loop() {
}

Ouvrez le moniteur série pour visualiser le fonctionnement des fonctions

=== print et println ====
ABC
=======
Une demo avec 
un retour à la ligne 
---- Ou -----
Une demo avec 
un retour à la ligne
=== Concatenation avec println ====
Un chaine qui combine un entier 32, un décimal 32.23 est un bool 1

=== printf ====
Hexa 999b989 999B989 
Byte 120 
World 63450 
Long 2147483647 
Caractère A 
une chaîne de caractères 
Variable float 99.570000 | 99.57 
Variable double 99.576900 | 99.58 

=== FAKE BME280 ====
La température est de 18.7°C, l'humidité est de 68.0% 

=== Write buffer to Serial ====
Buffer size: 7
Print buffer with write function
Arduino

Mises à jour

2/10/2020 Publication de l’article

English Version

Avez-vous aimé cet article ?
[Total: 1 Moyenne: 5]
Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

Vous avez aimé ce projet ? Ne manquez plus aucun projet en vous abonnant à notre lettre d’information hebdomadaire!

quel modèle esp8266 choisir
Quel modèle d'ESP8266EX choisir en 2020 ?
guide choix esp32 development board
Quel ESP32 choisir en 2020 ?

Vous rencontrez un problème avec ce sujet ?

Peut-être que quelqu’un a déjà trouvé la solution, visitez le forum avant de poser votre question

Nous serions ravis de connaître votre avis

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.