Auteur Sujet: La fonction printf() en Arduino  (Lu 10280 fois)

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1080
  • HO avec DCC++
    • Voir le profil
La fonction printf() en Arduino
« le: décembre 31, 2021, 06:31:51 pm »
Bonjour à tous,

Pour bien terminer l’année, je vous propose la petite astuce suivante : Tous ceux qui connaissent la fonction printf() en langage C sont sans doute frustrés comme je l’étais qu’elle ne soit pas disponible dans le langage Arduino.

Je précise rapidement que la fonction printf() correspond à la fonction Serial.print() de l’Arduino mais offre l’avantage de pouvoir inclure en même temps que du texte, des variables dans les paramètres.

Voici un exemple simple : si vous souhaitez écrire un texte plus la valeur de i dans la boucle ci-dessous, vous devrez appeler deux fois la fonction Serial.print() (ou Serial.println() pour avoir un retour à la ligne).

for(byte i = 0; i < 10; i++) {
  Serial.print("La valeur de i est ");
  Serial.print(i);
}

Avec la fonction printf, le code devient :

for(byte i = 0; i < 10; i++) {
  printf("La valeur de %d est ", i);
}

C’est plus compact et avec l’habitude, plus facile à écrire d’autant que l’on peut placer plusieurs variables sur une seule ligne comme nous le verrons dans l’exemple suivant.

J’ai repris pour l'essentiel un code que j’ai trouvé sur internet mais que j’ai placé dans un fichier distinct pour qu’il ne vienne pas « polluer » le code du fichier principal (.ino)

Il suffit donc d’ajouter un nouvel onglet dans l’IDE Arduino, d’appeler ce fichier « Printf.h » et de copier le code suivant :


#ifndef printf_h
#define printf_h

// Define a file descriptor for the serial output:
static FILE uartout = { 0 };

// Declare our put-character function:
static int uart_putchar (char c, FILE *stream);

// My char output function
static int uart_putchar (char c, FILE *stream) {
  if ( c == '\n' )
    Serial.write('\r');
  Serial.write(c) ;
  return 0 ;
}

struct Printf {
  static void begin(long);
};

void Printf::begin(long baud) {
   // Fill in UART file descriptor with pointer to my char-out func.
  fdev_setup_stream(&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
  stdout = &uartout;
  Serial.begin(baud);
}

#endif

Dans le fichier principal (.ino), il faut tout d’abord ajouter le lien #include "Printf.h" et dans le setup() placer Printf::begin(xxxxxx); au lieu du traditionnel Serial.begin(xxxxxx) ;

Enfin, je vous donne un exemple complet. Pour l’utilisation optimale de cette fonction printf(), je vous renvoie au nombreux tutos d’internet comme celui-ci : https://www.gladir.com/CODER/C/printf.htm

#include "Printf.h"

void setup() {

  Printf::begin(115200);
  printf("Hello world\n");
}

void loop( void ) {
  long compt = 0;
  for (byte i = 'A'; i <= 'z'; i++) {
    compt++;
    printf("Le code ASCII de %c est %d et le nombre de caractères lus est %ld\n", i, i, compt);
    delay(1000);
  }
}



« Modifié: décembre 31, 2021, 06:33:31 pm par bobyAndCo »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3037
  • 100% Arduino et N
    • Voir le profil
Re : La fonction printf() en Arduino
« Réponse #1 le: décembre 31, 2021, 10:06:29 pm »
#include "Printf.h"
Int an = 2022;

void setup() {

  Printf::begin(115200);
  Printf("Bonne Année %d et Bonne Santé ", an);
}
void loop() {
}


Amitiés
Dominique
« Modifié: décembre 31, 2021, 10:09:12 pm par Dominique »
Cordialement,
Dominique

JPM06

  • Newbie
  • *
  • Messages: 49
    • Voir le profil
Re : La fonction printf() en Arduino
« Réponse #2 le: janvier 01, 2022, 03:53:19 pm »
Je sais que ça n'a rien à voir, mais il y a une question que je me pose depuis longtemps au sujet des Serial.print:
> que deviennent ces instructions lorsque Arduino tourne sans connexion série, de façon autonome?
Sont elles ignorées? exécutées dans le vide? A-t-on alors intérêt à les inhiber (les "out-commenter"!) avant chargement pour accélérer l'exécution?
Merci d'éclairer ma lanterne ou de m'indiquer où cette question  a été traitée, car c'est sûrement le cas?
Personnellement, dans le doute, je déclare:    #define sp Serial.print
    #define spl Serial.println
et j'utilise ces macros en lieu et place des Serial.machins
Et avant chargement du programme je les modifie en:    #define sp //Serial.print
    #define spl //Serial.println
Je suppose que la question s'applique aussi à PrintF et autres?

Bonne année à tous!




AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : La fonction printf() en Arduino
« Réponse #3 le: janvier 03, 2022, 10:10:26 am »
Tout code qui est compilé est exécuté, qu'il y ai un périphérique connecté ou pas au port série de l'Arduino.
Il émet vos "traces" même en production. Ce qui veut dire qu'il "fuite" de l'information et, surtout, qu'il consomme du temps de calcul pour faire une activité LOURDE inutile (la génération de traces sur la console est un traitement assez lourd toutes proportions gardées !)

Une bonne pratique quand on fait un usage sérieux de la chose consiste à utiliser des MACROS + compilation conditionnelle pour ne pas produire ce code quand on fait une compilation RELEASE du projet, mais à l'inclure seulement lorsqu'on fait une compilation DEBUG lors d'une phase de mise au point. Cela nécessite de passer des options au compilateur qui changent en fonction des circonstances....et là l'IDE ARDUINO c'est pas le panard...

Par contre ça se fait simplement dès qu'on utilise un outil plus sérieux comme Plateforme IO.
Sébastien.
La perfection est un chemin, non un but...

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2217
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Re : La fonction printf() en Arduino
« Réponse #4 le: janvier 03, 2022, 10:48:48 am »
Bonjour,

et donc, il m'avait semblé de bonne pratique d'utiliser :

#ifdef DEBUG
#endif

avec

// #define DEBUG 1 en tête pour les activer

et donc encadrer les Serial.print de mise au point.
Cordialement

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : La fonction printf() en Arduino
« Réponse #5 le: janvier 03, 2022, 12:12:34 pm »
C'est bien l'idée, mais cette écriture ne fonctionnera que si le programme ne comporte qu'un seul sketch et pas de librairies ou fichiers inclus...ce qui est rarement le cas pour un programme d'un certain niveau de complexité.

Dans ce cas il faut utiliser un define passé au compilateur comme argument...
Sébastien.
La perfection est un chemin, non un but...