Parlons Arduino > Trucs & astuces

La fonction printf() en Arduino

(1/2) > >>

bobyAndCo:
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).


--- Code: ---for(byte i = 0; i < 10; i++) {
  Serial.print("La valeur de i est ");
  Serial.print(i);
}
--- Fin du code ---

Avec la fonction printf, le code devient :


--- Code: ---for(byte i = 0; i < 10; i++) {
  printf("La valeur de %d est ", i);
}
--- Fin du code ---

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 :



--- Code: ---#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
--- Fin du code ---

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


--- Code: ---#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);
  }
}

--- Fin du code ---



Dominique:

--- Code: ---#include "Printf.h"
Int an = 2022;

void setup() {

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


--- Fin du code ---

Amitiés
Dominique

JPM06:
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:
--- Code: ---    #define sp Serial.print
    #define spl Serial.println
--- Fin du code ---
et j'utilise ces macros en lieu et place des Serial.machins
Et avant chargement du programme je les modifie en:
--- Code: ---    #define sp //Serial.print
    #define spl //Serial.println
--- Fin du code ---
Je suppose que la question s'applique aussi à PrintF et autres?

Bonne année à tous!



AmadeusHF:
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.

msport:
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.

Navigation

[0] Index des messages

[#] Page suivante

Utiliser la version classique