Arduino CLI sous Linux : compiler et téléverser en ligne de commande
Si vous programmez des cartes dans l’environnement Arduino (Arduino Uno, Nano, Mega, Uno R4 Minima/WiFi, mais aussi ESP8266/ESP32, RP2040, RP2350, etc.), vous êtes sans doute passés par l’IDE Arduino officiel (1.8.x ou 2.x). C’est l’outil le plus répandu pour débuter : il permet de compiler et téléverser en un seul clic, sans avoir à se soucier de la chaîne de compilation ou des outils sous‑jacents.
L’IDE a aussi un avantage important : il unifie les pratiques. Le même bouton Build ou Upload fonctionne pour toutes les cartes, alors que les outils utilisés en arrière‑plan sont totalement différents selon la famille. Une Arduino Uno ne se compile pas avec les mêmes toolchains qu’un ESP32, et un RP2040 utilise encore une autre chaîne. L’IDE masque cette complexité et offre une expérience homogène, ce qui est idéal pour débuter.
Arduino‑CLI, développé indépendamment des IDE 1.8.x et 2.x, est l’outil officiel pour compiler et téléverser des sketches dans l’environnement Arduino, mais sans interface graphique : tout se fait en ligne de commande. Comme l’IDE, il propose des commandes unifiées (compile, upload) qui fonctionnent pour toutes les familles de cartes, même si les toolchains utilisées en arrière‑plan diffèrent selon le modèle. La différence, c’est que la CLI (Command Line Interface) rend ces opérations plus explicites, scriptables et intégrables dans des workflows automatisés.
Je propose dans ce billet d’installer et de découvrir cette interface en ligne de commande et ses avantages. L’objectif est de comprendre comment compiler et téléverser des sketches sans passer par l’IDE Arduino, en utilisant uniquement le terminal. J’ai testé l’installation d’Arduino‑CLI sur une Raspberry Pi avec le Raspberry Pi OS Lite officiel, mais les commandes présentées ici fonctionnent de la même manière sur n’importe quelle distribution Linux (Ubuntu, Debian, Mint, etc.).
Installation d’Arduino CLI
La méthode d’installation standard, et mise en avant par la documentation, fonctionne sur toutes les distributions Linux.
On commence par télécharger et exécuter le script d’installation :
1
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
Le script détecte l’architecture (ARM, x86_64…), télécharge la bonne version d’Arduino CLI et extrait le binaire dans un dossier bin/ local.
Pour pouvoir utiliser arduino-cli depuis n’importe quel emplacement, il est conseillé de déplacer ce binaire dans /usr/local/bin :
1
sudo mv bin/arduino-cli /usr/local/bin/
Vous pouvez vérifier votre installation avec la commande :
1
arduino-cli version
Si tout s’est bien passé, la commande affiche la version installée, par exemple :
1
arduino-cli Version: 1.5.1 Commit: 01f3d4f2b Date: 2026-06-05T10:22:11Z
Pour plus de détails sur l’installation, voir https://docs.arduino.cc/arduino-cli/installation/
Configuration initiale
En plus du binaire arduino-cli, un dossier caché ~/.arduino15/ est créé automatiquement. Il sert à stocker les fichiers temporaires, les cores installés, les bibliothèques, les index, ainsi que divers éléments internes nécessaires au fonctionnement de l’outil.
La documentation recommande de générer un fichier de configuration minimal avec la commande :
1
arduino-cli config init
Cette commande crée un fichier ~/.arduino15/arduino-cli.yaml. Arduino‑CLI peut fonctionner sans fichier de configuration, mais dès que l’on souhaite installer des cores supplémentaires (ESP32, RP2040, etc.) ou personnaliser les chemins, ce fichier devient indispensable.
Cette commande crée un fichier ~/.arduino15/arduino-cli.yaml minimal.
1
2
board_manager:
additional_urls: []
Ce fichier peut rester tel quel, et l’outil fonctionnera avec la configuration par défaut, mais il permet aussi de personnaliser certains aspects de l’outil, comme l’ajout d’URLs supplémentaires pour installer des cores non officiels, ou la modification des chemins utilisés par Arduino‑CLI.
Pour plus de détails sur les options de configuration disponibles, la documentation officielle propose une description complète : https://docs.arduino.cc/arduino-cli/configuration/
Installation des cores
Un core Arduino est l’ensemble des fichiers nécessaires pour que l’IDE ou Arduino‑CLI puisse compiler et téléverser un sketch pour une famille de cartes donnée. Il contient la chaîne de compilation adaptée au microcontrôleur, les définitions de cartes, les scripts de build, ainsi que les bibliothèques système de bas niveau. Chaque famille de cartes possède son propre core : les cartes AVR (Uno, Nano), les ESP32/ESP8266, les RP2040, les cartes ARM, etc.
L’Arduino CLI fraîchement installé ne contient encore aucun core. Sans core, il est impossible de compiler ou téléverser un sketch, car l’outil ne sait pas quelles définitions de cartes, quelles bibliothèques système ou quelle chaîne de compilation utiliser.
Nous allons commencer par installer le core officiel destiné aux cartes Arduino basées sur des microcontrôleurs AVR : Arduino Uno, Nano et Mega. Ce core porte le nom arduino:avr :
1
arduino-cli core install arduino:avr
Après quelques instants, le temps de télécharger et d’installer tous les outils nécessaires, vous devriez voir un message de confirmation indiquant que le core a bien été installé :
1
2
...
Platform arduino:avr@1.8.8 installed
On peut vérifier que le core est bien installé en affichant la liste des plateformes disponibles avec la commande :
1
arduino-cli core list
Vous devriez y voir apparaître la ligne :
1
2
ID Installed Latest Name
arduino:avr 1.8.8 1.8.8 Arduino AVR Boards
Ce qui confirme que le core AVR est actif et prêt à être utilisé pour compiler des sketches destinés aux cartes Arduino Uno, Nano ou Mega.
Certaines familles de cartes, comme les ESP32 d’Espressif, ne sont pas incluses dans les sources officielles d’Arduino. Pour installer ces cores, il faut d’abord ajouter l’URL fournie par le fabricant, afin qu’Arduino CLI puisse télécharger l’index correspondant. Par exemple, pour les cartes ESP32, on peut ajouter l’URL Espressif directement en ligne de commande :
1
arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
Une fois l’index mis à jour, l’installation du core se fait comme pour les autres plateformes :
1
arduino-cli core install esp32:esp32
Ce core permet de compiler pour la plupart des cartes ESP32 (DevKitC, WROOM, WROVER, NodeMCU‑32S, etc.). Attention, le core Espressif ESP32 est un core monolithique qui inclut les toolchains pour plusieurs familles de microcontrôleurs (ESP32, ESP32‑S2, ESP32‑S3, ESP32‑C3, etc.). Son installation peut occuper plusieurs gigaoctets. Ce comportement est normal, car Espressif regroupe toutes les variantes dans un seul core.
Sur Linux (et Raspberry Pi OS), Arduino CLI installe tous les cores dans : ~/.arduino15/packages/
Compiler un sketch
Pour tester la compilation, on part d’un sketch minimal blink.ino placé dans un sous‑dossier blink/ :
1
2
3
4
5
6
7
8
9
10
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
La commande de compilation s’exécute depuis le dossier parent :
1
arduino-cli compile --fqbn arduino:avr:uno blink
Le paramètre --fqbn (Fully Qualified Board Name) indique la carte cible. Ici, arduino:avr:uno correspond au core arduino:avr et à la carte Arduino Uno.
Si tout se passe bien, la compilation affiche un résumé du binaire généré :
1
2
Sketch uses 924 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
La commande arduino-cli compile accepte plusieurs options pratiques :
--verboseAffiche les détails de la compilation : commandesavr-gcc, chemins, options, etc. Utile pour comprendre ce qui se passe ou diagnostiquer un problème.--warnings <level>Niveau d’avertissements du compilateur :none,default,more,all. Exemple :--warnings allpour activer tous les warnings GCC.--cleanSupprime le dossier de build avant de compiler. Utile si vous changez de carte ou de core.--build-path <dossier>Permet de choisir où générer les fichiers de compilation. Par défaut :blink/build/arduino.avr.uno/.--libraries <dossier>Ajoute un dossier de bibliothèques personnalisé à la compilation.--export-binariesCopie les fichiers.hexou.bindans le dossier du sketch après compilation.
Exemple de comande de compilation complète, à lancer depuis un dossier parent :
1
2
3
4
5
6
arduino-cli compile \
--fqbn arduino:avr:uno \
--verbose \
--warnings all \
--build-path blink/build \
blink
Le dossier du build est alors généré dans blink/build/arduino.avr.uno/
Téléverser un sketch
Une fois votre carte Arduino Uno reliée au port USB de la Raspberry Pi, vous pouvez lister les ports COM/tty détectés avec la commande :
1
arduino-cli board list
On obtient par exemple :
1
2
Port Protocol Type Board Name FQBN Core
/dev/ttyACM0 serial Serial Port (USB) Arduino UNO arduino:avr:uno arduino:avr
L’Arduino Uno est ici détectée sur le port série /dev/ttyACM0/.
On peut maintenant téléverser dans la carte Arduino avec la commande suivante (en mode verbeux) :
1
arduino-cli upload -p /dev/ttyACM0 --fqbn arduino:avr:uno --verbose blink
Si tout se passe bien, le message se termine par :
1
2
3
4
5
6
7
8
...
Reading 924 bytes for flash from input file blink.ino.hex
in 1 section [0, 0x39b]: 8 pages and 100 pad bytes
Writing 924 bytes to flash
Writing | ################################################## | 100% 0.21s
924 bytes of flash written
Avrdude done. Thank you.
New upload port: /dev/ttyACM0 (serial)
La Led intégrée à la carte devrait se mettre à clignoter.
Installer une bibliothèque
L’environnement Arduino, c’est aussi une galaxie de bibliothèques, officielles ou tierces, qui ajoutent des fonctionnalités prêtes à l’emploi : gestion de capteurs, modules de communication, afficheurs, actionneurs, protocoles, traitements numériques, etc.
Ces bibliothèques permettent d’étendre facilement les capacités d’un sketch sans réinventer la roue.
Arduino CLI permet de rechercher une bibliothèque dans l’index officiel :
1
arduino-cli lib search servo
Et il existe une pléthore de bibliothèques disponibles pour piloter un servomoteur. Je ne mets ici que la première détectée (bibliothèque Servo officielle) :
1
2
3
4
5
6
7
8
9
10
11
12
Downloading index: library_index.tar.bz2 downloaded
Name: "Servo"
Author: Michael Margolis, Arduino
Maintainer: Arduino <info@arduino.cc>
Sentence: Allows Arduino boards to control a variety of servo motors.
Paragraph: This library can control a great number of servos.<br />It makes careful use of timers: the library can control 12 servos using only 1 timer.<br />On the Arduino Due you can control up to 60 servos.
Website: https://www.arduino.cc/reference/en/libraries/servo/
Category: Device Control
Architecture: avr, megaavr, sam, samd, nrf52, stm32f4, mbed, mbed_nano, mbed_portenta, mbed_rp2040, renesas, renesas_portenta, renesas_uno, zephyr
Types: Arduino
Versions: [1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.1.0, 1.1.1, 1.1.2, 1.1.3, 1.1.4, 1.1.5, 1.1.6, 1.1.7, 1.1.8, 1.2.0, 1.2.1, 1.2.2, 1.3.0]
...
Le nom de la bibliothèque officielle est Servo (avec un ‘s’ majuscule), et on l’installe avec la commande :
1
arduino-cli lib install Servo
Avec la sortie :
1
2
3
4
Downloading Servo@1.3.0...
Servo@1.3.0 downloaded
Installing Servo@1.3.0...
Installed Servo@1.3.0
La version la plus récente 1.3.0 est installée par défaut dans le dossier ~/Arduino/libraries/.
Vous pouvez lister les bibliothèques installées avec la commande :
1
arduino-cli lib list
Avec en sortie :
1
2
Name Installed Available Location Description
Servo 1.3.0 - user -
Les bibliothèques sont souvent accompagnées d’exemples prêts à l’emploi.
1
arduino-cli lib examples Servo
1
2
3
Examples for library Servo
- /home/fleb/Arduino/libraries/Servo/examples/Knob
- /home/fleb/Arduino/libraries/Servo/examples/Sweep
Intégration dans un script
Arduino-CLI se prête très bien à l’automatisation. On peut l’intégrer dans un script pour compiler, téléverser ou même injecter des paramètres avant la compilation.
Exemple : module ESP32 configuré en serveur Web avec SSID et mot de passe externes On suppose que ce projet est versionné sur GitHub. Le code source est donc public ou partagé, tandis que les identifiants WiFi restent locaux et ne sont jamais commités.
Dans cet exemple, un script Python lit un fichier .env contenant les identifiants WiFi, génère automatiquement un fichier config.h, puis lance la compilation et le téléversement.
Fichier server/.env
1
2
SSID=xxxxxxxxxxxxx
PASSWORD=yyyyyyyyyyyyy
Ce fichier caché ainsi que le fichier config.h généré en Python seront dans la liste .gitignore afin de ne pas exposer les identifiants dans votre dépôt Github.
Sketch Arduino server/server.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <WiFi.h>
#include "config.h"
WiFiServer server(80);
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.print("Connexion au WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnecté !");
Serial.print("IP : ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (!client) return;
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/plain");
client.println();
client.println("Hello World!");
client.stop();
}
Script Python build.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env python3
import subprocess
import sys
from dotenv import dotenv_values # pip install dotenv
SKETCH = "server"
FQBN = "esp32:esp32:esp32"
PORT = "/dev/ttyUSB0"
# Chargement du fichier .env
env = dotenv_values(f"{SKETCH}/.env")
SSID = env.get("SSID")
PASSWORD = env.get("PASSWORD")
if not SSID or not PASSWORD:
print("Erreur : SSID ou PASS manquant dans .env")
sys.exit(1)
def run(cmd):
print(f"---> {cmd}")
result = subprocess.run(cmd, shell=True)
if result.returncode != 0:
print("Erreur : commande échouée.")
sys.exit(1)
# Génération du fichier config.h
config = f'''
#pragma once
const char* ssid = "{SSID}";
const char* password = "{PASSWORD}";
'''
with open(f"{SKETCH}/config.h", "w") as f:
f.write(config)
print("config.h généré")
# Compilation
run(f"arduino-cli compile --fqbn {FQBN} {SKETCH}")
# Téléversement
run(f"arduino-cli upload --fqbn {FQBN} -p {PORT} {SKETCH}")
print("Téléversement terminé")
Résultat : une fois le script build.py exécuté, l’ESP32 démarre un petit serveur Web accessible à l’adresse IP attribuée par votre Box/routeur. La page renvoie simplement un “Hello World!”.
Ce workflow est intéressant parce qu’il sépare clairement le code versionné et la configuration locale. Le dépôt Git ne contient que le sketch et le script Python : tout ce qui est sensible (.env, config.h) est généré ou stocké localement et exclu du dépôt. Dans un projet hébergé sur GitHub, cela évite toute fuite accidentelle d’identifiants et permet à chaque utilisateur de cloner le dépôt puis d’ajouter ses propres paramètres sans modifier le code source. On obtient ainsi un processus reproductible, sécurisé et évolutif : le code est partagé via Git, tandis que les identifiants restent sur la machine de l’utilisateur. Le script automatise ensuite la génération de config.h et le téléversement, ce qui simplifie les mises à jour et évite d’avoir à éditer les identifiants ou lancer les commandes à la main.
Conclusion
Arduino CLI offre une manière plus flexible et plus moderne de travailler avec les cartes compatibles avec l’environnement Arduino. Ce billet a montré comment compiler et téléverser en ligne de commande, puis comment intégrer ces actions dans un workflow Git pour rendre le développement plus fiable et automatisable. Cette approche constitue la base de mon projet Arduino LMS portable, où l’intégration d’Arduino CLI dans VS Code permet d’obtenir un environnement complet, portable et prêt à l’emploi.