Guide complet pour le débogage étape par étape d'un code Arduino

Dans cet article

Je possède beaucoup de robots ! Et la plupart d'entre eux sont contrôlés par une carte Arduino.

Le développement sur la plateforme Arduino, bien que passionnant, n'est pas exempt de défis. L'IDE Arduino 1.x n'est pas incroyable et le second fait un peu l'effet d'un VSCode au rabais. Dans un cas comme dans l'autre, l'un de leurs nombreux soucis est l'absence de débogueur simple. Au cours de la programmation d'un projet, et plus celui-ci se complexifie, les erreurs peuvent survenir à tout moment et les identifier efficacement est une compétence essentielle pour tout développeur Arduino. La méthode classique et la plus simple ? L'envoi d'information textuelle sur le port série et l'utilisation du moniteur comme écran de débogage. Évidemment, suivre l'exécution d'une boucle ou d'un code complexe devient vite difficile, et il n'est pas possible d'arrêter le programme au moment opportun pour en étudier l'état interne.

Serial.println("jusqu'ici tout va bien !");

C'est une autre approche que je vous propose au cours de cet article : le débogage pas-à-pas.

Le débogage pas-à-pas se fait à l'aide du débogueur. Il permet d'exécuter le programme pas-à-pas (c'est-à-dire le plus souvent ligne par ligne), d'afficher la valeur des variables à tout moment et de mettre en place des points d'arrêt sur des conditions ou sur des lignes du programme.

La méthode que je vais vous montrer est compatible avec de nombreuses cartes programmables. Je l'utilise personnellement avec tout type de carte Arduino (nano, uno, mega, etc..) mais avec un peu d'adaptation, elle fonctionnerait également avec des cartes esp ou autres. Nous allons, autant que possible, utiliser des outils gratuits (ou pour quelques euros en fin d'article) afin que la méthode convienne aux hobbyistes.

Installation de l'environnement de travail

Quel que soit votre logiciel de programmation : Arduino IDE, CLion, VSCode, etc.., il possède nécessairement des outils d'aide au débogage. Ceux-ci peuvent être plus ou moins puissants, plus ou moins complexe à mettre en œuvre, ou nécessiter plus ou moins de matériel.

La méthode que je vous propose utilise l'IDE gratuit PlatformIO. L'outil est gratuit et open-source. Il est multi-platforme (windows, linux, mac, etc..), multi-architecture (x32, x64, ARM, etc..), multi-framework (Arduino, ESP, Simba, etc...) et construit sur la base de VSCode. Bref, c'est l'IDE parfait pour la programmation de système embarqué en C/C++… ou presque.

Son installation est simple : rendez-vous sur le lien https://platformio.org/platformio-ide et laissez-vous guider.

Je vous laisse quelques minutes pour installer l'IDE, et je vous retrouve dès que c'est fait ! ☕︎

Création du projet

Open PlatformIO welcome page

Une fois installé, une jolie petite icône d'alien apparait dans la barre d'outils à gauche de VSCode. C'est en cliquant sur cette icone que nous allons commencer. Sachez que la page d'accueil de platformIO se trouve dans QuicAccess > PIO Home > Open. Ce n'est pas très intuitif et il est vrai que platformIO (tout comme VSCode sur lequel il se base) souffre - à mon goût - de ce défaut de clarté d'interface : il n'est pas toujours évident de s'y retrouver ou de parcourir sa documentation, par ailleurs très fournie.

Un ensemble d'option nous est désormais présenté : l'ouverture d'un projet Arduino existant ou la création d'un nouveau projet. Pour la suite, je vais créer un nouveau projet, mais l'idée est la même avec un code Arduino existant : indiquez l'emplacement de votre code et la board (arduino nano, uno, etc...) de votre projet.

Pour cet article, je vais créer un nouveau projet ayant pour nom Blink que l'on fera tourner sur une carte Arduino nano: Arduino Nano ATmega328.

PlatformIO new project wizard

Le fichier qui s'ouvre à l'écran est nommé platformio.ini. C'est dans ce fichier que nous allons faire la plupart de nos modifications ultérieurement, mais pour l'instant, concentrons-nous sur le reste de la structure du projet crée. PlatformIO crée une structure permettant la gestion de projet complexe, avec différent dossiers (include, lib, src, test, ...). Nous retrouvons dans le dossier src un premier fichier généré par le logiciel et nommé main.cpp. Bien que ce ne soit pas l'extension .ino à laquelle vous êtes probablement habitué, le code ce comporte de la même façon. Modifions le fichier pour qu'il contienne le code suivant :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <Arduino.h>
 
uint8_t counter = 0;
 
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
 
void blink() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}
 
void loop() {
  if (counter < 300) {
    blink();
  }
  counter++;
}

Ce code n'est pas très malin : il fait clignoter 300x une led.

Notre code déclare une variable globale de type unsigned 8 bits integer, c'est à dire nombre entier positif sur 8 bits. Dans la bouche principale, cette variable appelée counter est successivement incrémentée, de sorte qu'elle prend successivement les valeurs 1, 2, 3, etc... Tant que ce compteur reste inférieur à 300, une fonction nommée blink fait clignoter la led de la carte arduino. Quand le compteur dépasse 300, ce clignotement stop. C'est en tout cas le fonctionnement théorique de ce code, car visiblement certains problèmes subsistent.

Notez la première ligne: #include <Arduino.h>.
Cette ligne est habituellement automatiquement ajoutée à la compilation par l'IDE dédié au framework arduino: Arduino IDE. Comme ici le logiciel PlatformIO permet de coder pour différent types de framework, il nous convient d'explicitement ajouter cette inclusion.

Branchez votre Arduino Nano à l'un des ports USB de votre ordinateur, comme vous le faites classiquement pour la programmer. Je vous invite désormais à cliquer dans le menu principal sur Run > Run without debugging ou à utiliser le raccourci clavier Ctrl+F5 ce qui aura pour effet, comme son nom l'indique, de lancer dans l'ordre :

  • la compilation du programme
  • son téléchargement sur la carte
  • l'exécution du programme - c'est à dire le clignotement en boucle de la led rouge pin13 inclus sur la carte
Nous nous attendions ici à ce que le compteur prenne successivement les valeurs 1, 2, 3, 4, etc... Or le clignement ne cesse jamais, ce compteur n'a donc probablement jamais dépassé les 300 et notre code contient une erreur.

Tentative de debug à l'ancienne

La méthode "classique" ou à l'ancienne que beaucoup pratiquent pour déboguer le code précédent est l'utilisation du port série et du moniteur série pour transférer et afficher des informations de debug. Ici, ce serait la valeur de la variable counter que nous souhaiterions connaître.
La méthode à l'ancienne consistera donc à initialiser le port série dans la méthode setup(), puis à envoyer la valeur du counter dans la méthode loop() selon le code ci-dessous:

cliquez pour voir le code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <Arduino.h>
 
uint8_t counter = 0;
 
void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}
 
void blink() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}
 
void loop() {
  if (counter < 300) {
    blink();
  }
  counter++;
  Serial.println(counter);
}

Je vous invite à tester en déployant le code selon la méthode précédente (Ctrl+F5), puis en ouvrant le moniteur série :

  1. Cliquer sur l'icône PlatformIO: Serial monitor en forme de prise électrique, dans la barre d'icone en bas d'écran.
  2. Cliquer sur l'onglet Serial Monitor dans la fenêtre ainsi ouverte.
  3. Cliquer enfin sur le bouton Start monitoring.
Ouverture du moniteur série
Nous constatons l'incrémentation de notre compteur, affiché sur le moniteur série.

La méthode suivante souffre de quelques défauts :

  • Le problème apparaît au bout de plusieurs minutes, mais comment être certain du moment exact ?
  • En supposant que l'on se soit laissé distraire, il faut relancer le programme et attendre.
  • En supposant un programme un peu plus complexe, le moniteur série défile et défile à une vitesse ne permettant pas une analyse fine.
  • Il peut être difficile d'afficher le contenu de variable plus complexe (un vecteur, un buffer, un gros tableau de valeur, etc...)
  • Toute variable dont la valeur n'est pas dump dans le port série n'est pas affichée et pour peu que vous ayez oublié une valeur importante, il faut recommencer.
  • Le port série est monopolisé à l'affichage du debug et ne peut pas être utilisé en parallèle dans notre programme

Mise en place du debug pas-à-pas

Je sais que je parle (ou écris) beaucoup, mais enfin nous y sommes : voyons une méthode plus adaptée.

La première chose à faire, va être de configurer notre logiciel pour le debug :

  • Ouvrir le fichier platformio.ini qui se trouve à la racine du projet.
  • Modifier le fichier pour que son contenu soit le suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[env:default]
platform = atmelavr
framework = arduino
 
; Compatible boards with the debugger:
;  https://docs.platformio.org/en/stable/plus/debug-tools/avr-stub.html#boards
board = nanoatmega328
; board = uno
; board = megaatmega2560
 
; Configure debugger tool
debug_tool = avr-stub
debug_port = COM3
 
; GDB stub implementation
lib_deps = 
  jdolinay/avr-debugger

Ce fichier configure le comportement de PlatformIO pour notre projet.

  1. La première ligne indique un début de section. Nous configurons ici l'environnement par défaut, c'est à dire que notre projet se comportement pareil dans toutes les conditions. Il est toutefois possible de configurer un comportement ou des settings différents selon que l'on veuille faire du debug ou une compilation pour release, mais aussi selon la carte avec laquelle on souhaite travailler. Il est donc possible de complexifier ces configurations pour par exemple tester notre code simultanément sur deux cartes différentes connectés sur des ports différents de l'ordinateur.
    Plus d'infos : https://docs.platformio.org/en/latest/projectconf/sections/env/index.html
  2. Les deux lignes suivantes définissent la plateforme et le framework, c'est à dire le toolchain de compilation utilisée. En deux mots, la compilation transforme notre code C++ en code spécifique au microcontrôleur cible, ici des cartes arduino dont le processeur est de la famille des AVR. C'est donc cette plateforme la cible.
  3. Nous définissons ensuite la carte qui sera utilisé. Là encore, parce que chaque carte a un processeur différent ainsi que des spécificités matérielles, il nous faut être précis. Notre compilateur supporte un très grand nombre de carte, mais le débogueur un peu moins. (cf point 4)
  4. Voici le moment de configurer le débogueur. Nous utiliserons ici avr-stub qui est spécifique aux processeurs de la famille des AVRs. Ce débogueur supporte un nombre limité d'architecture, de framework et de cartes (en fait toutes les cartes de type Arduino)
    Plus d'infos : https://docs.platformio.org/en/stable/plus/debug-tools/avr-stub.html
  5. Nous indiquons ensuite le port de debug. Notez que cette ligne est optionnelle si une seule carte Arduino est branchée à l'ordinateur : PlatformIO saura la détecter.
  6. Finalement, nous incluons une dépendance à la librarie jdolinay/avr-debugger. Vous constatez ici la magie de PlatformIO qui va se charger tout seul de trouver, télécharger, compiler et lier cette librairie au projet ! Cette librairie contient le code Arduino permettant à notre carte de dialoguer avec le débogueur via le port série.

Une fois fait, il nous reste à changer quelques détails dans notre code : nous allons repartir de notre premier jet, sans le debug Serial. Il conviendra alors d'ajouter :

  • Deux #include en début de fichier (mais après celui d'<Arduino.h> permettant d'utiliser la librairie de debug à notre code
  • L'appel à la méthode debug_init() en début du setup().

Voici le code ainsi obtenu :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <Arduino.h>
#include "avr8-stub.h"
#include "app_api.h"
 
uint8_t counter = 0;
 
void setup() {
  debug_init();
  pinMode(LED_BUILTIN, OUTPUT);
}
 
void blink() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}
 
void loop() {
  if (counter < 300) {
    blink();
  }
  counter++;
}

Créer des points d'arrêts et lancer le debug

Tout est prêt pour le grand moment, celui qui nous retourne généralement le cerveau la première fois que l'on découvre le debug pas-à-pas 🤯.

Dans PlatformIO, en passant votre souris sur le chiffre de la ligne 20, vous remarquerez un point rouge apparaître sur la gauche. Cliquez, et ce point rouge sera désormais activé.

Add a breakpoint

Ce point rouge s'appelle un "point d'arrêt". En exécutant le programme en mode debug, ce que l'on appelle aussi exécuter jusqu'au point d'arrêt, ce dernier va se lancer et s'exécuter jusqu'à rencontrer cette ligne. Le débogueur va alors mettre le programme en pause, et permettre l'exploration des valeurs internes de celui-ci. Voyons cela en pratique.

Relançons le programme, cette fois-ci en mode pas-à-pas. Pour cela, appuyez sur F5, ou utilisez le menu Run > Start Debugging.

Débug pas à pas
  1. Le lancement et l'exécution d'un programme en mode debug est plus lent que le mode classique. Il vous faudra donc patienter quelques secondes : cela est indiquer par un sablier sur l'outil correspondant
  2. Une fois lancé, le programme va s'exécuter jusqu'au point d'arrêt. Ici, nous le voyons en pause à la ligne 21 avant qu'elle ne s'exécute, c'est à dire que la condition de la ligne 20 s'est évaluée à true et le programme souhaite exécuter la ligne 21.
  3. Une barre d'outils de contrôle pas-à-pas est apparue.

De gauche à droite, les outils proposés sont :

  • Continue (F5) : Continuer l'exécution du programme.
    L'exécution reprendra jusqu'au prochain point d'arrêt rencontré. Ici, nous exécuterons donc un clignotement de la led via la méthode blind, puis l'incrémentation du compteur ligne 23 et enfin le prochain tour de boucle avec à nouveau l'évaluation de la condition ligne 20, avant de nous ré-arrêter ligne 21.
  • Step Over (F10) : Continuer à la prochaine ligne, en ne détaillant pas les appels de fonctions.
    Depuis le point d'arrêt actuel, en appuyant sur F10, nous allons exécuter la ligne 21 et passer à la prochaine ligne "sémantique", c'est à dire ligne 23. Le programme va donc exécuter l'ensemble de la fonction blink() et donc faire clignoter la led, avant de se remettre en pause ligne 23 en attendant l'incrémentation.
  • Step into (F11) : Continuer à la prochaine ligne effective
    Reprenons depuis le point d'arrêt actuel ligne 20 : le programme est en pause en attendant d'exécuter la fonction blink(). A l'inverse de l'option précédente, si nous appuyons sur F11, nous allons ici entrer dans la fonction blink() et faire pause à la prochaine ligne à exécuter. Le programme attendra donc l'utilisateur ligne 13. Cette ligne ne sera donc pas encore exécutée et la led ne sera pas allumée.
  • Step out (F12) : Continuer jusqu'à sortir de la fonction actuelle
    Par la fonction précédente, nous voilà maintenant à l'intérieur de la fonction blink() ligne 13. Si l'on choisit F10, nous allons allumer la led et attendre ligne 14. Si l'on choisit F11, nous allons entrer dans la fonction digitalWrite() et nous retrouver au cœur du code Arduino. A l'inverse, l'option Step Out ou F12 exécutera l'ensemble des lignes de la méthode en cours (blink) et nous attendra à la sortie. Dans notre cas, nous arriverons à la ligne 23, le clignotement de la led ayant été effectué.
  • Restart (Ctrl+Shift+F5) : Recommencer depuis le début
    Comme son nom l'indique, le programme va recommencer depuis le début et le débogueur fera à nouveau pose au premier point d'arrêt rencontré.
  • Stop (Shift+F5) : Stop l'exécution du programme
    Comme son nom l'indique : termine l'exécution du programme et sort du mode debug.

Lançons donc notre programme en mode debug et appuyons quelques fois sur F5, c'est à dire continuer. Nous allons ainsi faire clignoter la led plusieurs fois et nous nous retrouvons à chaque fois en pause sur la ligne 20.

En passant la souris sur les différents éléments du programme, nous en voyons apparaître les valeurs à l'instant t. En particulier, sur la variable counter, j'obtiens ici la valeur 5, indiquant que cela fait 5 fois que je parcours ma boucle. Je constate aussi que l'incrémentation se fait correctement et la valeur de mon compteur augmente.

Debug a value

Vous l'aurez deviné, avancer ainsi peut être laborieux. PlatformIO propose donc un point d'arrêt dit "conditionnel".

Effectuez un clic-droit sur le point rouge de la ligne 20 et choisissez l'option Edit Breakpoint....

Nous allons ajouter la condition counter == 100.

En relançant l'exécution via la commande Continuer (F5), le programme va reprendre et la led va ainsi clignoter de multiples fois jusqu'à ce que notre programme se mettre à nouveau en pause. A ce moment, passez votre souris au-dessus du compteur : nous avons avancé jusqu'à la 100ème exécution.

Conditionnal Breakpoint

Ce guide n'étant pas un cours de programmation Arduino, permettez-moi de passer rapidement sur la résolution de l'erreur de cet exemple. Nous allons appliquer une méthode dites "dichotomique". Le problème semble se situer lors de la comparaison de counter avec la valeur 300. Si nous n'avions pas déjà deviner le problème, voici ce que je ferais :

  • Point d'arrêt condition jusqu'à la valeur 299 pour voir ce qu'il se passe lors de la 300ème boucle. Il se trouve que notre programme ne s'arrête alors jamais, ce qui prouve que l'on n'atteint pas cette valeur. En mettant manuellement en pause (F6) et en inspectant le counter, j'obtiens une valeur improbable.
  • Nous savons que le point d'arrêt à fonctionner jusqu'à la valeur 100. Essayons donc quelque chose entre les deux. J'essaie donc un point d'arrêt conditionnel sur la valeur 200.
  • Cela fonctionne, mon programme s'arrête ici. Le problème se situe donc entre 200 et 299. Je modifie donc ma condition sur le point d'arrêt à 250.
  • C'est toujours bon ! Continuons ainsi en réduisant l'intervalle. 275 ne fonctionne plus. 260 ? Pas non plus... 254 c'est bon. En continuant ainsi, j'arrive à un point d'arrêt à 255.
  • Passons désormais en ligne par ligne via F10. En inspectant la valeur de counter à chaque ligne, je découvre que 255 + 1 = 0. Quoiiii ?

Notre compteur vaut à présent 255, soit en binaire : b1111_1111. En ajoutant 1, nous passons à 255+1=256 soit en binaire : b1_0000_0000. Or notre compteur est déclaré sur comme uint8_t, soit un nombre entier positif sur 8 bits. Seuls les 8 derniers bits sont gardés ici, c'est à dire les 8 derniers zéros : b0000_0000 soit 0. On dit que le compteur overflow, c'est à dire qu'il déborde de sa taille allouée et pour éviter de planter complètement le frameword arduino a décidé de wrap la valeur (wrapper en anglais francisé), c'est à dire de ne garder que les 8 derniers bits. Notre compteur n'atteint donc jamais 300 et c'est là l'origine de l'erreur constatée.

Debug avancé : libérons le port série !

Revenons un peu en arrière : au paragraphe Tentative de debug à l'ancienne, j'ai énuméré plusieurs inconvénients liés à l'utilisation du port série pour le débogage. J'espère à présent avoir réussi à vous persuader de l'intérêt d'un "vrai" débogueur pas à pas. Cependant, nous n'avons pas encore abordé le dernier point de la liste d'inconvénient, à savoir, comment utiliser la liaison série tout en déboguant notre programme simultanément. Car oui, cela est bel et bien possible ! 🤯

J'en suis désolé d'avance, mais pour bien comprendre, nous allons devoir évoquer des sujets un peu techniques.

Concrètement, pour communiquer avec l'extérieur, les cartes Arduino disposent de divers protocoles de communications - peut-être ces noms vous diront quelques choses : SPI, I2C, UART, etc...

Intéressons-nous plus spécifiquement au protocole UART. C'est un protocole de communication de type série nécessitant 2 câbles, appelés RX et TX. RX réceptionne les informations, tandis que le câble TX les transmet. En branchant le câble RX d'un appareil compatible UART au câble TX d'un autre et vice-versa, ces deux appareils se retrouvent capable d'échanger ensemble dans les deux sens, via ce protocole.

Pour uploader votre programme dans votre carte arduino, vous branchez certainement celle-ci au port USB de votre ordinateur. Concrètement, votre carte arduino possède un convertisseur UART-USB intégré sur ses broches 0 et 1. C'est également ces broches 0 et 1 qui sont utilisées par la bibliothèque Serial lorsque l'on écrit Serial.begin(). C'est également ces broches qui sont aussi utilisées par défaut par avr-debugger. Il n'est pas possible d'utiliser simultanément cette connectique UART0 (broche 0 et 1) pour deux usages différents et simultanés, par exemple la bibliothèque Serial et avr-debugger. Toute l'astuce réside donc dans le fait de trouver un autre couple de broche permettant une liaison UART. Plusieurs possibilités s'offre à nous :

  1. Utiliser d'autres broches pour l'upload du code Arduino. C'est théoriquement possible quoi que compliqué. En effet, l'usage des broches 0 et 1 comme support UART pour l'upload du code est ancré au plus profond de la carte Arduino dans le bootloader. Il faudrait donc hacker celui-ci (c'est à dire le modifier) puis flasher la carte selon une procédure spécifique, la rendant inutilisable par la voie classique (branchée en USB). C'est une piste que je déconseille.
  2. Utiliser un autre couple de broche pour le transfert de donnée via Serial. Là, c'est tout à fait possible.
    1. Certaines cartes - comme la Arduino Méga - possède plusieurs connexions UART, ainsi les broches 14 à 18 peuvent être utilisées par couple UART1, UART2 et UART3. Ces couples sont standards sur la carte et la bibliothèque Serial comme la bibliothèque avr-debugger sont capables de les utiliser.
    2. Il est aussi possible de simuler logiciellement une connexion série via la bibliothèque SoftwareSerial.
  3. Dans tous les cas, un convertisseur UART-USB supplémentaire sera nécessaire pour se connecter également à l'ordinateur via cette seconde liaison série. Cela peut être fait de deux façons :
    1. Via l'achat d'un convertisseur UART-USB externe. N'importe lequel de n'importe quelle marque est utilisable, même les moins chers à 1€10 sur AliExpress !
    2. Via l'usage d'une seconde carte Arduino (peu importe laquelle) pour laquelle on utilisera son convertisseur intégré aux broches 0 et 1.
  4. Dans tous les cas, le débogage peut être confiée à une carte spécialisée de type JTAG compatible avec votre carte Arduino. Ces outils sont en revanche chers et spécifiques à chaque type de carte, c'est une solution à laisser aux professionnels et dont les hobbyistes peuvent se passer.

Je vous recommande d'oublier la solution 1 qui ne présente que peu de bénéfice et beaucoup de risques dans notre affaire

Dans le cas où vous utilisez une carte Méga ou une carte ayant un port UART supplémentaire inclus, je vous recommande la solution 2.a en conjonction avec la solution 3.a, à savoir de configurer avr-debugger sur UART1 par exemple et d'y adjoindre un convertisseur UART-USB.

Dans le cas où vous utilisez une carte autre, je vous recommande la solution 2.b en conjonction avec la solution 3.a, à savoir de configurer un port différent pour votre liaison série, et de garder le port UART "officiel" pour le debug de votre code. En effet, avr-debugger ne sera pas en mesure d'utiliser une liaison série logicielle.

Enfin, la solution 3.b est un remplacement de la solution 3.a. Mais au prix négligeable d'une carte de conversion UART-USB, je vous recommande l'investissement.

Vous êtes un professionnel ? Cessez les bricolages et faites investir votre société dans du matériel, certes plus couteux, mais plus adapté : optez pour la solution 4.

Simuler un port série

Afin de libérer le port USB (UART0) pour l'usage exclusif du débogueur, il est possible de simuler la liaison série logiciellement via l'usage de la librairie SoftwareSerial. Je n'entrerais pas ici dans les détails car en effet cet article commence à être très long et il traite plus du debug que de la programmation arduino.

Utiliser le port UART1 pour la liaison série

Alternativement à la solution précédente et en supposant que vous utilisiez une carte Arduino Méga, il est possible de remplacer simplement le code classique de votre communication série (c'est à dire le mot clef Serial) par Serial1 pour le port UART1 (broches 18 et 19), par Serial2 (broches 16 et 17) ou encore Serial3 (broches 14 et 15). Là encore, c'est hors du scope de cet article et je vous invite à consulter la documentation.

Utiliser avr-debugger sur UART1

Passons à présent sur une carte Arduino Méga, présentant l'avantage d'avoir nativement plusieurs broches compatibles UART. Nous allons devoir modifier notre fichier platformio.ini comme suit :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[env:default]
platform = atmelavr
board = megaatmega2560
framework = arduino
 
; Configure upload tool
upload_port = COM3
 
; Configure debugger tool
; TX(uart)<->RX(arduino) and RX(uart)<->TX(arduino)
; PIN depends on the UART number used
debug_tool = avr-stub
debug_port = COM4
build_flags = -DAVR8_UART_NUMBER=1
 
; GDB stub implementation
lib_deps =
  jdolinay/avr-debugger

Les différences avec le fichier précédent sont :

  • Le changement de la carte board qui passe à un Arduino Méga
  • L'introduction de la configuration upload_port : il permet de définir le port série utilisé pour l'upload du code, c'est à dire le port USB sur lequel est branché notre arduino.
  • Une nouvelle configuration build_flags qui permet d'ajouter des flags à la compilation. Ici, nous utilisons -DAVR8_UART_NUMBER à la valeur 1, qui permet à avr-debugger d'utiliser le port UART1 (broches 18 et 19) de notre carte.
  • Notez que le port debug_port est différent de upload_port et nous devrons utiliser un convertisseur UART-USB depuis les broches 18 et 19 de notre carte, vers ce port USB COM4 de notre ordinateur.

Utiliser un convertisseur UART-USB

Maintenant que notre configuration est prête, nous pouvons à présent réutiliser le code du paragraphe Tentative de debug à l'ancienne pour utiliser à la fois le débogueur pas à pas et notre port série avec le moniteur. Il nous reste simplement à trouver comme relier les broches 18 et 19 de l'UART1 de notre Arduino Méga à l'ordinateur. Pour cela, il nous faut un convertisseur UART-USB. Ceux-ci se présentent généralement sous la forme d'un câble (TTL-USB) ou d'une carte (UART-USB) avec d'un côté un port USB mâle à brancher à l'ordinateur et de l'autre côté des broches ou des câbles Dupont. Il conviendra alors de relier :

  • RX de la carte, avec TX (pin 18) de l'arduino
  • TX de la carte avec RX (pin 19) de l'arduino
  • le GND de la carte au GND de l'arduino
  • laissez le +5V de la carte non connecté, en effet dans notre exemple, l'alimentation de votre arduino se fait déjà par le port série classique
Attention, certains fabricants de convertisseurs UART-USB indiquent RX/TX sur la carte comme étant les broches de l'UART. Il faut donc brancher RX<->TX et TX<->RX, tandis que d'autres indiquent RX et TX comme les broches auxquelles brancher ces pattes, le branchement dans ce cas est RX<->RX et TX<->RX. C'est un peu confus, mais dans le doute, vous pouvez essayer les deux configurations sans risquer d'endommager votre matériel.

Utiliser un arduino comme convertisseur UART-USB

Supposons que l'on souhaite utiliser un arduino nano comme convertisseur UART-USB. Il convient alors de brancher les broches UART de notre arduino méga à déboguer sur les broches UART0 (broches 0 et 1) de l'arduino nano, puis de brancher celui-ci à l'ordinateur. Afin d'éviter d'utiliser réellement cet arduino et pour n'utiliser que le convertisseur UART-USB intégré, nous devons shunter - ou court-circuiter en quelque sorte - le microcontrôleur de la carte en branche le RESET au GND. Récapitulons :

  • RX de la carte arduino à déboguer sur la broche 1 de l'arduino de conversion
  • TX de la carte arduino à déboguer sur la broche 0 de l'arduino de conversion
  • RESET de la carte arduino de conversion sur le GND de cette même carte
  • (optionnel) j'aurais tendance à vous conseiller de connecter également les GND des deux cartes ensemble

Une fois ces ajustements fait, le reste du debug se déroule comme précédemment : utilisez le raccourci F5, et c'est parti !

Ajouter un commentaire

Votre nom sera affiché publiquement avec votre commentaire.
Votre email restera privé et n'est utilisé que pour vous notifier de l'approbation de ce commentaire.
Sur internet, vous pouvez être qui vous voulez. Soyez quelqu'un de bien :)