Header Ads

#define DEBUG - une méthode de debugging parfaite

Introduction
Pour faire du débugging avec Arduino, le plus simple est encore d'utiliser la communication série, la commande Serial.println() et le Serial Monitor d'Arduino IDE.
Voir notre précédent article "Débugger à l'aide du port série (via USB)" pour plus d'information.

Cet article complète la technique pour offrir une approche de débogage simple et très aboutie.

Désavantage de Serial.println
La simple technique Serial.println() apporte cependant un sérieux revert.
En effet, elle stocke beaucoup de chaine de caractère dans votre programme.
Ensuite, cette méthode ralenti le programme de façon non négligeable.

L'idéal serait de désactiver l'utilisation du débogage via le port série lorsque le programme passe en production.
Cette méthodologie est particulièrement pertinente lors du développement d'une librairie :-)


Utiliser #define DEBUG
En naviguant sur le WEB, j'ai rencontré une excellente méthode que je mets en œuvre dans le développement d'une librairie pour le GPRS Shield.

1) Etape 1: Activer la connexion série
Lors du debugging, c'est le programme appelant qui initialise la communication série.
Il est ainsi possible de respecter plus facilement les contraintes du projet utilisant la classe (comme la vitesse par exemple).

/* ------------------------------
   Main Routines (PROTOTYPE CODE)
   ------------------------------ */
GoGprs gsm = GoGprs();

void setup() {
  Serial.begin(19200);
  
  gsm.begin();
}   

void loop() {
  gsm.execute();
  delay(500);
}

2) Etape 2: define d'activation
Le debugging est activité avec le define suivant:

#define GG_DEBUG

Le préfix "GG_" est utilisé pour Gof Gprs.

Si ce define n'est pas présent (je mets un zzGG_DEBUG pour le désactiver) alors aucun message de debugging ne sera envoyé sur le port série.
Pour le moment, ce define se trouve encore dans le corps de la librairie (qui n'est encore qu'un code prototype) 

3) Etape 3: defines complémentaires
L'astuce réside dans les définitions complémentaires suivantes (située dans la librairie).
C'est à partir de cette étape que la méthode devient vraiment puissante!

#ifdef GG_DEBUG
  #define GG_DEBUG_PRINTLN(x) Serial.println(x)
  #define GG_DEBUG_PRINTLN2(x,y) Serial.println(x,y)
  #define GG_DEBUG_PRINT(x) Serial.print(x)
  #define GG_DEBUG_PRINT2(x,y) Serial.print(x,y)
#else
  #define GG_DEBUG_PRINTLN(x)
  #define GG_DEBUG_PRINTLN2(x,y)
  #define GG_DEBUG_PRINT(x)
  #define GG_DEBUG_PRINT2(x,y)
#endif 


Si GG_DEBUG est défini, alors les fonctions GG_DEBUG_PRINTLN et consort deviennent disponibles (et redirigent les appels vers les fonctions Serial correspondantes).

Si GG_DEBUG n'est pas défini, les fonctions GG_DEBUG_PRINTLN sont définies comme équivalent à "rien"

4) Etape 4: Coder les messages de debug
En guise d'exemple, voici le code qui établit la communication série avec le Shield GPRS.

//Description:
//  Begin start the operation of the GoGprs class
//
void GoGprs::begin(){
  GG_DEBUG_PRINTLN("GoGprs begin");
  
  gprsSerial.begin(19200);
}

Si GG_DEBUG est définit, l'appel de GG_DEBUG_PRINTLN("GoGprs begin") envoi la chaine de caractère vers le port série via un appel a Serial.println

Si GG_DEBUG n'est pas définit, l'appel de GG_DEBUG_PRINTLN("GoGprs begin") est remplacé au moment de la compilation par une ligne vide.
En conséquence: pas d'appel a Serial.println... ni d'allocation d'une chaine de caractère :-)

Avantage de la méthode
L'avantage le plus direct c'est que les chaines de caractères de débogage ne sont plus compilées dans le programme lorsque le débogage est désactivé.

Le programme est donc plus petit si le débogage est désactivé (c'est testé et confirmé! Mon programme passe de 7318 bytes à 6398 bytes)