App Inventor Arduino Bluetooth : ton appli Android avec HC-05
Piloter Arduino en Bluetooth avec App Inventor : câblage du HC-05, ListPicker, blocs boutons et curseurs, LED, relais, servo, capteurs, APK et Android 12.
Piloter un Arduino en Bluetooth avec App Inventor est le moyen le plus rapide de créer ta propre appli Android sans écrire une seule ligne de Java ou de Kotlin. Dans MIT App Inventor, l'outil gratuit du MIT qui fonctionne dans le navigateur, tu glisses des boutons, des curseurs et des zones de texte sur l'écran, puis tu définis leur comportement avec des blocs qui s'emboîtent comme des pièces de puzzle. Le téléphone se connecte à un module Bluetooth HC-05 relié à l'Arduino ; chaque appui dans l'appli part vers l'Arduino sous forme d'une courte commande texte, et l'Arduino renvoie ses mesures au téléphone par le même chemin.
À la fin de ce guide, tu auras une appli de télécommande qui fonctionne vraiment : un ListPicker qui se connecte au HC-05 depuis une liste, des boutons qui allument et éteignent une LED et un relais, deux curseurs (Slider) pour la luminosité de la LED et l'angle du servo, et des étiquettes qui affichent en direct la température et l'humidité d'un DHT11. Tu verras étape par étape le code Arduino, chaque bloc App Inventor, la création de l'APK et la solution au problème d'autorisations Bluetooth apparu avec Android 12. Si tu n'as jamais utilisé le HC-05, jette d'abord un œil au guide du module Bluetooth HC-05.

Qu'est-ce qu'App Inventor et comment communique-t-il avec Arduino ?
MIT App Inventor est un environnement gratuit de création d'applis développé par le Massachusetts Institute of Technology (MIT) ; tu te connectes avec ton compte Google et tu travailles dans le navigateur. Il propose deux vues : dans le Designer, tu prépares l'apparence de l'appli en faisant glisser des composants, et dans l'éditeur Blocks, tu écris avec des blocs colorés des règles comme « quand on appuie sur le bouton, fais ceci ». Pour tester l'appli sans l'installer, on utilise l'appli MIT AI2 Companion du Play Store ; une fois le travail terminé, un clic génère un fichier APK installable.
Côté Bluetooth, c'est le composant BluetoothClient qui fait le travail. Il utilise le profil SPP (Serial Port Profile, profil de port série) du Bluetooth classique, justement celui du HC-05. Résultat : un câble série invisible entre le téléphone et l'Arduino. Quand l'appli envoie « L1 » avec le bloc SendText, l'Arduino lit ces deux caractères avec bt.read(), comme si tu les avais tapés dans le moniteur série. Tout ce que l'Arduino envoie avec bt.print() arrive dans le bloc ReceiveText du téléphone. Côté Arduino, aucune bibliothèque Bluetooth particulière n'est nécessaire.
| Couche | Rôle | Dans ce projet |
|---|---|---|
| Interface (Designer) | Composants visibles à l'écran | ListPicker, 5 Button, 2 Slider, Label |
| Logique (Blocks) | Blocs qui réagissent aux événements | Événements Click, PositionChanged et Timer |
| BluetoothClient | Connexion SPP, envoi et réception de données | Connect, SendText, ReceiveText |
| HC-05 | Pont entre Bluetooth et UART | 9600 bauds, code PIN 1234 |
| Arduino | Interprète les commandes, pilote les sorties, lit le capteur | LED, relais, servo, DHT11 |
Matériel nécessaire
| Matériel | Quantité | Remarque |
|---|---|---|
| Arduino Uno (ou Nano) | 1 | Code et broches identiques sur les deux |
| Module Bluetooth HC-05 ou HC-06 | 1 | Bluetooth classique ; le HM-10 (BLE) ne fonctionne pas de cette façon |
| Résistances de 1 kΩ et 2 kΩ | 1 de chaque | Pont diviseur pour la broche RXD du HC-05 (2,2 kΩ convient aussi) |
| LED et résistance de 220 Ω | 1 de chaque | LED à luminosité réglable (D5, PWM) |
| Module relais 5 V | 1 | Pour commander une lampe ou un ventilateur |
| Servomoteur SG90 | 1 | Commande de 0 à 180° par curseur |
| Capteur de température et d'humidité DHT11 | 1 | Données à afficher sur le téléphone |
| Téléphone Android | 1 | Le HC-05 ne fonctionne pas avec l'iPhone |
| Breadboard et fils de connexion | — | Une masse (GND) commune est indispensable |





Montage : branchement du HC-05, de la LED, du relais, du servo et du DHT11
La carte du HC-05 possède un régulateur, sa broche VCC accepte donc 5 V, mais ses broches de données fonctionnent en logique 3,3 V. L'Arduino lit sans problème le signal 3,3 V de la broche TXD du module ; en revanche, le signal TX en 5 V de l'Arduino doit arriver sur la broche RXD à travers un pont diviseur de tension : D11 → 1 kΩ → RXD, RXD → 2 kΩ → GND. RXD reçoit ainsi 5 × 2 / 3 ≈ 3,3 V. On relie le HC-05 aux broches D10 et D11 avec SoftwareSerial plutôt qu'aux broches série matérielles du Uno (0 et 1) : tu peux ainsi téléverser du code module branché et garder le moniteur série pour le débogage. Tu peux vérifier la résistance de la LED avec le calculateur de résistance pour LED.
| Liaison | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| HC-05 VCC | 5V | Inutile (Bluetooth intégré) | VBUS (5 V) |
| HC-05 GND | GND | — | GND |
| HC-05 TXD | D10 (RX de SoftwareSerial) | — | GP1 (UART0 RX) |
| HC-05 RXD | D11, via un pont 1 kΩ / 2 kΩ | — | GP0 (UART0 TX), sans pont |
| LED (+ 220 Ω) | D5 (PWM) | GPIO 2 (LED intégrée) | GP15 |
| IN du module relais | D7 | GPIO 26 | GP14 |
| Signal du servo (orange) | D9 | — (ajout possible avec ESP32Servo) | GP13 |
| Données du DHT11 | D2 | GPIO 4 | GP16 |
Protocole de communication : qu'enverra le téléphone ?
Avant d'écrire du code, il faut décider quelle « langue » parleront le téléphone et l'Arduino. Dans ce projet, chaque commande se compose d'une lettre, suivie d'un nombre et enfin d'un caractère de retour à la ligne (\n, ASCII 10). Ce retour à la ligne est essentiel : les données Bluetooth peuvent arriver en morceaux, et si « S1 » et « 35 » arrivent séparément, l'Arduino attend le retour à la ligne et traite « S135 » comme une seule commande. Comme les commandes sont du texte lisible, tu peux aussi les tester à la main avec n'importe quelle appli de terminal Bluetooth.
| Commande | Sens | Signification |
|---|---|---|
| L1 / L0 | Téléphone → Arduino | Allumer la LED à fond / l'éteindre |
| P0 … P255 | Téléphone → Arduino | Luminosité de la LED (valeur analogWrite) |
| R1 / R0 | Téléphone → Arduino | Activer / relâcher le relais |
| S0 … S180 | Téléphone → Arduino | Angle du servo (degrés) |
| 24.5;41 | Arduino → téléphone | Température (°C) et humidité (%), séparées par un point-virgule |
Au lieu de texte, App Inventor peut aussi envoyer un seul octet (0–255) avec le bloc Send1ByteNumber, que l'Arduino lit directement comme un nombre. C'est court et rapide, mais cela ne convient qu'à un seul curseur : si deux curseurs et quatre boutons envoient des octets, l'Arduino ne peut pas savoir si un 90 reçu est un angle de servo ou une luminosité. Le format lettre + nombre + retour à la ligne coûte quelques octets de plus, mais à 9600 bauds environ 960 caractères passent par seconde : tu ne verras jamais la différence.
Le code Arduino
Les bibliothèques Servo et SoftwareSerial sont fournies avec l'IDE Arduino. Pour le DHT11, installe DHT sensor library (Adafruit) depuis le gestionnaire de bibliothèques ; quand il propose les dépendances, choisis Install all pour ajouter aussi Adafruit Unified Sensor. Comme on n'utilise pas les broches 0 et 1, inutile de débrancher le HC-05 pendant le téléversement.
1#include <SoftwareSerial.h>
2#include <Servo.h>
3#include <DHT.h>
4
5SoftwareSerial bt(10, 11); // RX, TX → HC-05 TXD, RXD (bölücü üzerinden / via divider)
6Servo servo;
7DHT dht(2, DHT11); // DHT11 veri pini D2 / data pin D2
8
9const int LED_PIN = 5; // PWM destekli pin / PWM-capable pin
10const int ROLE_PIN = 7;
11const int SERVO_PIN = 9;
12const int ROLE_ACIK = LOW; // çoğu röle modülü LOW ile çeker / most relay modules are active LOW
13const int ROLE_KAPALI = HIGH;
14
15String komut = ""; // gelen satırın tamponu / buffer for the incoming line
16unsigned long sonGonderim = 0;
17
18void komutIsle(String k) {
19 k.trim(); // boşluk ve \r temizle / strip spaces and \r
20 if (k.length() == 0) return;
21 Serial.println(k); // hata ayıklama / debugging
22 char tur = k.charAt(0); // komut harfi / command letter
23 int deger = k.substring(1).toInt(); // harften sonraki sayı / number after the letter
24
25 switch (tur) {
26 case 'L': // L1 / L0 → LED aç, kapat / LED on, off
27 analogWrite(LED_PIN, deger == 1 ? 255 : 0);
28 break;
29 case 'P': // P0..P255 → parlaklık / brightness
30 analogWrite(LED_PIN, constrain(deger, 0, 255));
31 break;
32 case 'R': // R1 / R0 → röle / relay
33 digitalWrite(ROLE_PIN, deger == 1 ? ROLE_ACIK : ROLE_KAPALI);
34 break;
35 case 'S': // S0..S180 → servo açısı / servo angle
36 servo.write(constrain(deger, 0, 180));
37 break;
38 }
39}
40
41void setup() {
42 pinMode(LED_PIN, OUTPUT);
43 pinMode(ROLE_PIN, OUTPUT);
44 digitalWrite(ROLE_PIN, ROLE_KAPALI); // açılışta röle kapalı / relay off at start
45 servo.attach(SERVO_PIN);
46 servo.write(90); // orta konum / centre position
47 dht.begin();
48 Serial.begin(9600); // Seri Monitör / Serial Monitor
49 bt.begin(9600); // HC-05 veri modu hızı / HC-05 data mode baud rate
50}
51
52void loop() {
53 // 1) Telefondan gelen komutları satır satır oku / read commands from the phone line by line
54 while (bt.available()) {
55 char c = bt.read();
56 if (c == '\n') { // satır bitti / line complete
57 komutIsle(komut);
58 komut = "";
59 } else if (komut.length() < 16) { // aşırı uzun satırı kes / cap overlong lines
60 komut += c;
61 }
62 }
63
64 // 2) 2 saniyede bir sensör verisini gönder / send sensor data every 2 seconds
65 if (millis() - sonGonderim >= 2000) {
66 sonGonderim = millis();
67 float t = dht.readTemperature();
68 float h = dht.readHumidity();
69 if (!isnan(t) && !isnan(h)) {
70 bt.print(t, 1); // örnek / example: 24.5
71 bt.print(';');
72 bt.print(h, 0); // örnek / example: 41
73 bt.print('\n'); // println değil, \r gitmesin / not println, no \r
74 }
75 }
76}- Tampon de ligne : loop() ajoute chaque caractère reçu à la variable komut (commande) ; à l'arrivée de \n, il transmet la ligne à komutIsle() et vide le tampon. Au-delà de 16 caractères, le reste est ignoré, pour que des données parasites ne remplissent pas la mémoire.
- trim() : Certaines applis de terminal ajoutent aussi \r en fin de ligne ; trim() le supprime avec les espaces, si bien que « L1\r » est toujours reconnu comme « L1 ».
- Lettre et nombre : charAt(0) donne la lettre de la commande et substring(1).toInt() le nombre qui suit. constrain() ramène la valeur dans une plage sûre : même si le téléphone envoie 300 par erreur, le servo n'est jamais poussé au-delà de 180°.
- Envoi non bloquant : Le capteur est lu toutes les 2 secondes grâce à millis(). Comme il n'y a pas de delay(), les commandes reçues entre-temps sont traitées sans attente ; détails dans millis() ou delay().
- print('\n') au lieu de println : println() termine la ligne par \r\n. App Inventor n'utilise que \n comme séparateur, donc le \r resterait collé à la fin de la valeur d'humidité ; n'envoyer que \n garde un découpage propre sur le téléphone.
- Relais actif à l'état bas : La plupart des modules relais s'activent quand IN passe à LOW. Si le tien s'active sur HIGH, il suffit d'échanger les valeurs des constantes ROLE_ACIK (marche) et ROLE_KAPALI (arrêt).
Concevoir l'interface dans App Inventor (Designer)
- Ouvre ai2.appinventor.mit.edu dans ton navigateur, connecte-toi avec ton compte Google et crée un projet nommé BlueGraysRemote avec Projects > Start new project.
- Depuis le groupe Layout de la Palette, fais glisser un HorizontalArrangement et places-y un ListPicker (Text : Connecter), un Button (Text : Déconnecter) et un Label (Text : Non connecté).
- Ajoute en dessous deux autres HorizontalArrangement : dans le premier, les boutons Allumer LED et Éteindre LED ; dans le second, Allumer relais et Couper relais. Avec Width sur Fill parent, les boutons sont plus faciles à toucher.
- Ajoute deux Slider : pour la luminosité MinValue 0, MaxValue 255, ThumbPosition 0 ; pour le servo MinValue 0, MaxValue 180, ThumbPosition 90. Place au-dessus de chacun un Label qui indique son rôle.
- Ajoute deux autres Label pour la température et l'humidité et monte leur FontSize à environ 20.
- Depuis le groupe Connectivity, ajoute un BluetoothClient ; dans le panneau Properties, règle DelimiterByte sur 10 et coche NoLocationNeeded.
- Depuis le groupe Sensors, ajoute un Clock ; règle TimerInterval sur 200 et décoche TimerEnabled. On activera le minuteur par blocs une fois la connexion établie.
| Composant | Nom (Rename) | Réglage important |
|---|---|---|
| ListPicker | LP_Connect | Text : Connecter |
| Button × 5 | BTN_Disconnect, BTN_LedOn, BTN_LedOff, BTN_RelayOn, BTN_RelayOff | Width : Fill parent |
| Slider | SLD_Brightness | MinValue 0, MaxValue 255 |
| Slider | SLD_Servo | MinValue 0, MaxValue 180, ThumbPosition 90 |
| Label | LBL_Status, LBL_Temp, LBL_Hum | FontSize 20 (pour les valeurs) |
| BluetoothClient | BluetoothClient1 | DelimiterByte 10, NoLocationNeeded coché |
| Clock | Clock1 | TimerInterval 200, TimerEnabled désactivé |
Se connecter au HC-05 avec un ListPicker
Commence par appairer le HC-05 dans les réglages Bluetooth du téléphone (code PIN généralement 1234, sinon 0000). Cette étape est obligatoire : BluetoothClient1.AddressesAndNames ne liste que les appareils appairés et ne recherche pas les nouveaux appareils à proximité. Chaque élément est un texte composé de l'adresse MAC puis du nom de l'appareil, par exemple « 98:D3:31:F5:2A:10 HC-05 ». Tu peux passer ce texte complet au bloc Connect ; App Inventor supprime lui-même tout ce qui suit le premier espace. Le bloc renvoie true si la connexion réussit et false sinon.
- Dans l'événement when LP_Connect.BeforePicking, place set LP_Connect.Elements to BluetoothClient1.AddressesAndNames. La liste se remplit à nouveau avec les appareils appairés à chaque ouverture.
- Dans l'événement when LP_Connect.AfterPicking, ajoute un bloc if et branche call BluetoothClient1.Connect address: LP_Connect.Selection dans sa condition.
- Dans la partie then du if, mets LBL_Status.Text sur « Connecté » et lance la lecture des données avec set Clock1.TimerEnabled to true ; dans la partie else, écris « Échec de connexion ».
- Dans l'événement when BTN_Disconnect.Click, fais d'abord set Clock1.TimerEnabled to false, puis call BluetoothClient1.Disconnect, et enfin mets LBL_Status.Text sur « Non connecté ». Arrêter le minuteur en premier évite une lecture et un message d'erreur après la fermeture de la liaison.
Envoyer des données : boutons et curseurs
L'envoi se fait avec un seul bloc : call BluetoothClient1.SendText text. Quand tu écris « L1\n » dans un bloc texte, App Inventor transforme le \n final en caractère de retour à la ligne. Envoyer sans connexion provoque l'erreur 515 ; c'est donc une bonne habitude d'entourer chaque envoi d'un test if BluetoothClient1.IsConnected. Pour un curseur, tu colles le nombre à la lettre et au retour à la ligne avec un bloc join : join("S", round(thumbPosition), "\n").
| Événement (event) | Texte envoyé | Résultat sur l'Arduino |
|---|---|---|
| BTN_LedOn.Click | L1\n | La LED s'allume à pleine luminosité |
| BTN_LedOff.Click | L0\n | La LED s'éteint |
| BTN_RelayOn.Click | R1\n | Le relais colle, la lampe branchée s'allume |
| BTN_RelayOff.Click | R0\n | Le relais se relâche |
| SLD_Brightness.PositionChanged | join("P", round(thumbPosition), "\n") | analogWrite(5, valeur) |
| SLD_Servo.PositionChanged | join("S", round(thumbPosition), "\n") | servo.write(angle) |
Quand tu fais glisser un curseur du doigt, l'événement PositionChanged se déclenche des dizaines de fois par seconde et thumbPosition renvoie des valeurs décimales comme 87,4. Si tu envoies à chaque événement, le même angle part encore et encore, le tampon du HC-05 se remplit et le servo bouge par à-coups, avec du retard. La solution est simple : crée une variable global lastAngle ; n'envoie que si la valeur arrondie avec round(thumbPosition) est différente, puis mets la variable à jour. Ainsi, les données ne partent que lorsque l'angle change réellement. Applique la même astuce au curseur de luminosité avec global lastBrightness.
Recevoir des données : afficher les mesures sur le téléphone
L'Arduino envoie une ligne « 24.5;41 » toutes les 2 secondes. App Inventor n'a pas d'événement qui se déclenche tout seul à l'arrivée de données ; on utilise donc le composant Clock pour vérifier à intervalles réguliers s'il y a du nouveau. Comme DelimiterByte vaut 10 dans le Designer, donner -1 comme numberOfBytes au bloc ReceiveText lui fait lire jusqu'au retour à la ligne et renvoyer la ligne sans le \n. Un minuteur de 200 ms vérifie bien plus souvent que les données n'arrivent (toutes les 2000 ms), donc rien ne s'accumule dans le tampon.
- Place une condition if BluetoothClient1.IsConnected dans when Clock1.Timer.
- Ajoute à l'intérieur une seconde condition : call BluetoothClient1.BytesAvailableToReceive > 0.
- Range la ligne reçue dans une variable locale avec initialize local line to call BluetoothClient1.ReceiveText numberOfBytes: -1.
- Transforme la ligne en liste avec le bloc split text line at ";" : « 24.5;41 » devient la liste à deux éléments [24.5, 41]. Garde le résultat dans une variable locale nommée parts.
- if length of list parts = 2, mets LBL_Temp.Text sur join("Température : ", select list item parts index 1, " °C") et LBL_Hum.Text sur join("Humidité : ", select list item parts index 2, " %"). Vérifier le nombre d'éléments évite les erreurs dues à des lignes reçues à moitié ou corrompues.
Le problème d'autorisations Bluetooth sous Android 12 et plus
Les autorisations Bluetooth ont changé avec Android 12 (API 31). L'ancienne autorisation BLUETOOTH, accordée automatiquement à l'installation, a été remplacée par BLUETOOTH_CONNECT et BLUETOOTH_SCAN, que l'utilisateur doit accepter pendant l'exécution de l'appli ; dans les réglages du téléphone, elles apparaissent sous le nom Appareils à proximité. Si elle n'a pas été accordée, App Inventor ouvre la fenêtre d'autorisation à la première tentative, mais interrompt le bloc en cours. D'où des symptômes bien connus : la liste s'ouvre vide au premier appui sur Connecter, le message « Error 908: The permission ... has been denied » apparaît (avec BLUETOOTH_CONNECT ou BLUETOOTH_SCAN comme nom), ou bien, si l'utilisateur a refusé une fois, l'appli ne redemande plus jamais.
- Dans l'événement when Screen1.Initialize, vérifie la version d'Android : si select list item (split Screen1.PlatformVersion at ".") index 1 ≥ 12, donne à call Screen1.AskForPermission la valeur BluetoothConnect de la liste Permission. Ces autorisations n'existent pas sous Android 11 et versions antérieures, et les demander provoque là aussi l'erreur 908 : la vérification de version est donc importante.
- Dans l'événement when Screen1.PermissionGranted, si l'autorisation accordée est BLUETOOTH_CONNECT (contains text: permissionName, piece: "CONNECT"), demande ensuite BluetoothScan. AskForPermission n'accepte qu'une autorisation à la fois, il faut donc les enchaîner ainsi.
- Dans l'événement when Screen1.PermissionDenied, affiche avec un Notifier un message indiquant le chemin « Paramètres > Applications > BlueGraysRemote > Autorisations > Appareils à proximité > Autoriser ». Intercepter cet événement montre à l'utilisateur une explication claire au lieu d'une fenêtre d'erreur en anglais.
- Laisse NoLocationNeeded coché sur le BluetoothClient dans le Designer ; ce réglage indique à Android que l'appli n'utilise pas le Bluetooth pour déterminer la position.
- Teste toujours aussi avec l'APK : les autorisations de l'AI2 Companion appartiennent à l'appli Companion, alors que ton APK demande ses propres autorisations après l'installation.
| Erreur | Signification | Solution |
|---|---|---|
| Error 507: Unable to connect. Is the device turned on? | Connexion au module impossible | Vérifie l'alimentation du HC-05, l'appairage et qu'il n'est pas connecté à un autre téléphone ; si ça échoue encore, décoche Secure sur le BluetoothClient et réessaie |
| Error 515: Not connected to a Bluetooth device. | Envoi ou lecture sans connexion | Entoure les blocs d'envoi et du Clock d'un test IsConnected |
| Error 516: Unable to write: Broken pipe | Liaison coupée en cours de route (plus d'alimentation, hors de portée) | Arrête le Clock, appelle Disconnect et reconnecte-toi ; alimente séparément le servo et le relais |
| Error 908: The permission … has been denied | Pas d'autorisation Appareils à proximité sous Android 12+ | Demande-la par blocs ou accorde-la à la main dans les Paramètres |
| La liste s'ouvre vide | Module non appairé ou autorisation tout juste demandée | Appaire le HC-05 dans les réglages du téléphone puis, après avoir accordé l'autorisation, appuie de nouveau sur Connecter |
Tester l'appli et générer l'APK
Pendant le développement, inutile d'installer un APK à chaque modification. Installe l'appli MIT AI2 Companion depuis le Play Store ; avec l'ordinateur et le téléphone sur le même réseau Wi-Fi, choisis Connect > AI Companion dans App Inventor et scanne le QR code ou saisis le code de 6 caractères affiché à l'écran. Chaque modification faite dans le Designer ou dans les blocs apparaît aussitôt sur le téléphone. Une fois l'appli terminée, génère le fichier installable ainsi :
- Sélectionne Screen1 dans le Designer et renseigne AppName (le nom affiché sur le téléphone), Icon (un PNG carré), VersionCode et VersionName.
- Dans le menu du haut, choisis Build > Android App (.apk). La compilation prend en général une ou deux minutes.
- À la fin, une fenêtre s'ouvre avec un QR code et un bouton de téléchargement. Tu peux scanner le QR code avec le téléphone pour télécharger directement le fichier, ou enregistrer l'APK sur l'ordinateur et le copier sur le téléphone par câble. Le lien du QR code n'est valable que peu de temps (environ 2 heures).
- À l'ouverture de l'APK sur le téléphone, Android te demande d'autoriser le navigateur ou le gestionnaire de fichiers à installer des applis inconnues. Si Play Protect affiche un avertissement, tu peux poursuivre avec l'option d'installation malgré tout dans les détails ; cet avertissement est courant pour les applis hors Play Store dont la signature est inconnue.
- Au premier lancement de l'appli, accepte l'autorisation Appareils à proximité, appuie sur Connecter et choisis le HC-05 dans la liste.
La même appli avec un ESP32, sans HC-05

L'ESP32 classique intègre à la fois le Bluetooth classique et le BLE. La bibliothèque BluetoothSerial présente l'ESP32 au téléphone comme un appareil SPP : tu peux donc utiliser l'appli que tu viens de créer sans rien changer. Appaire l'appareil « BlueGrays-ESP32 » dans les réglages Bluetooth du téléphone, choisis-le dans la liste de l'appli, et c'est tout. Attention : les ESP32-S3, ESP32-C3 et ESP32-C6 ne gèrent que le BLE ; ils n'ont pas de BluetoothSerial et, côté App Inventor, il faut l'extension BluetoothLE. Pour travailler en BLE, consulte le guide ESP32 Bluetooth et BLE.
1#include "BluetoothSerial.h"
2#include <DHT.h>
3
4BluetoothSerial SerialBT;
5DHT dht(4, DHT11); // DHT11 veri pini GPIO 4 / data pin GPIO 4
6
7const int LED_PIN = 2; // çoğu DevKit'te kart üstü LED / onboard LED on most DevKits
8const int ROLE_PIN = 26;
9
10String komut = "";
11unsigned long sonGonderim = 0;
12
13void setup() {
14 pinMode(ROLE_PIN, OUTPUT);
15 digitalWrite(ROLE_PIN, HIGH); // aktif LOW röle kapalı / active-LOW relay off
16 dht.begin();
17 SerialBT.begin("BlueGrays-ESP32"); // telefonda görünecek ad / name shown on the phone
18}
19
20void loop() {
21 while (SerialBT.available()) {
22 char c = SerialBT.read();
23 if (c == '\n') {
24 komut.trim();
25 int deger = komut.substring(1).toInt();
26 if (komut.startsWith("L")) {
27 analogWrite(LED_PIN, deger == 1 ? 255 : 0); // LED aç, kapat / LED on, off
28 } else if (komut.startsWith("P")) {
29 analogWrite(LED_PIN, constrain(deger, 0, 255)); // parlaklık / brightness
30 } else if (komut.startsWith("R")) {
31 digitalWrite(ROLE_PIN, deger == 1 ? LOW : HIGH); // röle / relay
32 }
33 komut = "";
34 } else if (komut.length() < 16) {
35 komut += c;
36 }
37 }
38
39 if (millis() - sonGonderim >= 2000) { // Uno koduyla aynı biçim / same format as the Uno
40 sonGonderim = millis();
41 float t = dht.readTemperature();
42 float h = dht.readHumidity();
43 if (!isnan(t) && !isnan(h)) {
44 SerialBT.print(t, 1);
45 SerialBT.print(';');
46 SerialBT.print(h, 0);
47 SerialBT.print('\n');
48 }
49 }
50}Le code comprend les mêmes commandes que la version Uno et envoie les données au même format « température;humidité » ; il ignore les commandes S, faute de servo branché. La bibliothèque Servo d'Arduino ne fonctionne pas sur l'ESP32 ; pour ajouter un servo, installe la bibliothèque ESP32Servo et utilise les mêmes appels attach() et write(), par exemple sur le GPIO 13. Alimente le module relais par la broche VIN (5 V) ; si son entrée IN ne commute pas de façon fiable avec le signal 3,3 V de l'ESP32, choisis un module relais compatible 3,3 V. Plus de détails dans Qu'est-ce qu'un module relais ?
Avec le Raspberry Pi Pico et MicroPython

Le Raspberry Pi Pico standard n'a pas de Bluetooth : tu relies donc le HC-05 aux broches UART0 (GP0 et GP1). Comme les broches du Pico fonctionnent en 3,3 V, pas besoin de pont diviseur cette fois ; alimente le module par la broche VBUS, qui fournit les 5 V de l'USB. Les Pico W et Pico 2 W ont bien un Bluetooth intégré, mais MicroPython n'y gère que le BLE ; pour dialoguer avec le BluetoothClient classique d'App Inventor, le HC-05 reste la solution la plus simple. Le code ci-dessous comprend les mêmes commandes, pilote le servo en PWM à 50 Hz et envoie les données au même format ; le module dht est déjà inclus dans le firmware MicroPython du Pico.
1from machine import UART, Pin, PWM
2import dht
3import time
4
5bt = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1)) # GP0 → HC-05 RXD, GP1 ← HC-05 TXD
6led = PWM(Pin(15))
7led.freq(1000)
8role = Pin(14, Pin.OUT, value=1) # aktif LOW röle kapalı / active-LOW relay off
9servo = PWM(Pin(13))
10servo.freq(50) # servo 50 Hz ister / servos need 50 Hz
11sensor = dht.DHT11(Pin(16))
12
13def komut_isle(k):
14 if not k:
15 return
16 tur, deger = k[0], int(k[1:] or 0) # harf + sayı / letter + number
17 if tur == 'L':
18 led.duty_u16(65535 if deger == 1 else 0)
19 elif tur == 'P':
20 led.duty_u16(min(max(deger, 0), 255) * 257) # 0-255 → 0-65535
21 elif tur == 'R':
22 role.value(0 if deger == 1 else 1)
23 elif tur == 'S':
24 aci = min(max(deger, 0), 180)
25 servo.duty_ns(544000 + aci * 1856000 // 180) # 544-2400 µs darbe / pulse
26
27tampon = b''
28son = time.ticks_ms()
29while True:
30 if bt.any():
31 tampon += bt.read()
32 while b'\n' in tampon: # tam satır geldi mi? / full line received?
33 satir, tampon = tampon.split(b'\n', 1)
34 try:
35 komut_isle(satir.decode().strip())
36 except ValueError:
37 pass # bozuk komutu atla / skip malformed command
38 if len(tampon) > 32:
39 tampon = b'' # satır sonu hiç gelmedi / no newline arrived
40 if time.ticks_diff(time.ticks_ms(), son) >= 2000:
41 son = time.ticks_ms()
42 try:
43 sensor.measure()
44 bt.write('{:.1f};{}\n'.format(sensor.temperature(), sensor.humidity()))
45 except OSError:
46 pass # sensör okunamadı / sensor read failed
47 time.sleep_ms(10)Idées de projets avec App Inventor et Arduino
- Voiture pilotée en Bluetooth : Associe les boutons de direction aux lettres F, B, L et R et entraîne les moteurs avec un L298N ; toutes les étapes sont dans le guide fabriquer une voiture robot Arduino.
- Tableau de bord domotique : Commande une lampe, une prise et un ventilateur depuis un seul écran avec un module relais à quatre canaux ; pour des idées, vois le projet de maison connectée Arduino.
- Lampe à choix de couleur : Règle séparément le rouge, le vert et le bleu d'une LED RGB avec trois curseurs.
- Bras robotisé : Ajoute un curseur par articulation et commande les servomoteurs depuis ton téléphone.
- Surveillance de serre : Affiche sur le téléphone les mesures du DHT11 et du capteur d'humidité du sol, et ajoute un bouton qui lance la pompe quand la terre est sèche.
- Commande vocale : Avec le composant SpeechRecognizer d'App Inventor, crée une appli qui envoie L1 quand tu dis « allume la lumière ».
Erreurs fréquentes et solutions
- L'appli se connecte mais la LED reste éteinte : Les fils TXD et RXD du HC-05 sont inversés, ou les broches SoftwareSerial du code ne correspondent pas au montage. Le TXD du module doit aller sur le RX de l'Arduino (D10).
- Les commandes sont ignorées : Le \n manque dans le bloc texte ; l'Arduino attend le retour à la ligne. Vérifie si les commandes reçues apparaissent dans le moniteur série.
- Caractères incompréhensibles : La vitesse du HC-05 diffère de celle de bt.begin(). Le module sort d'usine à 9600 bauds ; si elle a été modifiée par commandes AT, adapte le code.
- Le servo tremble ou la connexion coupe : Le servo fait chuter la ligne 5 V de l'Arduino ; alimente-le avec une source 5 V séparée et relie les masses. Un léger tremblement peut aussi venir de SoftwareSerial, qui bloque brièvement les interruptions pendant la réception ; pour une solution durable, utilise un Arduino Mega ou un ESP32, qui disposent de ports série matériels libres. De temps en temps, le servo peut aussi sauter brièvement à un mauvais angle : la bibliothèque DHT coupe les interruptions pendant environ 5 ms à chaque mesure, et une commande qui arrive à ce moment-là peut être corrompue ; la commande suivante du curseur rectifie la position.
- Les valeurs arrivent en retard sur le téléphone : L'intervalle du Clock est plus long que celui d'envoi de l'Arduino, et les lignes s'accumulent. Garde TimerInterval plus court que l'intervalle d'envoi.
- L'appli se fige : DelimiterByte est resté à 0, ou l'Arduino ne termine pas ses lignes par \n ; ReceiveText(-1) attend un séparateur qui ne vient jamais.
- Rien ne marche sur iPhone : Le HC-05 utilise le Bluetooth classique, qu'iOS n'autorise pas. Pour un iPhone, il faut un module BLE (HM-10) ou un ESP32.
Associer App Inventor et Arduino est la façon la plus ludique d'apprendre à la fois le développement d'applis et l'électronique. Une fois la connexion et le protocole en place, le même squelette devient la télécommande d'une voiture, d'une maison connectée ou d'une serre ; seules changent les lettres envoyées par les boutons. Dans l'appli BlueGrays, tu trouveras pas à pas, avec schémas et code, les projets allumer une LED depuis le téléphone en Bluetooth et voiture Bluetooth avec L298N.
Questions fréquentes
Une appli App Inventor Bluetooth fonctionne-t-elle sur iPhone ?
Pas avec un HC-05 ou un HC-06. Ces modules utilisent le Bluetooth classique (SPP), et iOS ne permet pas aux applis ordinaires d'ouvrir ce type de liaison série. Pour dialoguer avec un iPhone, il faut passer à un module BLE comme le HM-10 ou à un ESP32 ; pour les projets avec HC-05, un téléphone Android reste le choix le plus simple.
Pourquoi la liste Bluetooth est-elle vide dans App Inventor ?
AddressesAndNames ne liste que les appareils déjà appairés avec le téléphone : appaire donc d'abord le HC-05 dans les réglages Bluetooth avec le code 1234. Sous Android 12 et plus, la liste s'ouvre aussi vide la première fois si l'autorisation Appareils à proximité n'a pas été accordée ; accorde-la et appuie de nouveau sur Connecter. Vérifie aussi que le Bluetooth est activé.
Comment corriger l'erreur 507 dans App Inventor ?
L'erreur 507 signifie « Unable to connect. Is the device turned on? » : le téléphone n'a pas pu ouvrir de connexion avec le module. Vérifie que le HC-05 est alimenté, que sa LED clignote rapidement et qu'il n'est pas connecté à un autre téléphone. Si le problème persiste, supprime l'appairage et refais-le, ou essaie de désactiver la propriété Secure du BluetoothClient.
Comment créer un APK avec App Inventor ?
Ouvre le projet et clique sur Build > Android App (.apk) dans le menu du haut. Une fois la compilation terminée, scanne le QR code avec le téléphone ou télécharge l'APK sur l'ordinateur puis copie-le sur le téléphone. Pendant l'installation, il faudra autoriser l'installation d'applis inconnues.
App Inventor peut-il se connecter à un ESP32 en Bluetooth ?
Oui. Avec la bibliothèque BluetoothSerial, l'ESP32 classique se comporte comme un appareil SPP, et le BluetoothClient d'App Inventor s'y connecte comme à un HC-05. Les ESP32-S3 et ESP32-C3 ne gèrent que le BLE : sur ces cartes, il faut l'extension BluetoothLE.
Peut-on publier une appli App Inventor sur Google Play ?
Oui. L'option Android App Bundle (.aab) du menu Build produit un fichier que tu peux envoyer sur Google Play ; il te faut pour cela un compte développeur Google Play. Les mises à jour doivent être signées avec la même clé, alors sauvegarde ton keystore avec Projects > Export keystore.
Projets à réaliser après cet article
Voir tous les projets
Clignotement d'une LED
Le tout premier bonjour de l'électronique : allumer et éteindre une seule LED. L'Arduino allume et éteint la LED à intervalles très courts, la lumière clignote donc rapidement. Tu vois de la façon la

Température et humidité avec DHT11
Quelle température fait-il dans ta chambre, et l'air est-il humide ou sec ? Le capteur DHT11 mesure la température et l'humidité, et l'Arduino affiche les valeurs sur un écran LCD à deux lignes, mises

Contrôler une LED depuis un téléphone via Bluetooth
Une petite répétition pour allumer et éteindre les lumières de ta chambre depuis ton téléphone. Le module Bluetooth transmet à l'Arduino les lettres envoyées par ton téléphone ; une lettre allume la L

Voiture contrôlée par Bluetooth avec L298N
Transforme ton téléphone en télécommande et pilote ta propre voiture robot. L'Arduino reçoit, via un module Bluetooth, les ordres d'une appli de télécommande sur ton téléphone et fait tourner les roue

Utilisation du servomoteur
Le bras d'un petit servomoteur tourne tour à tour vers trois positions : tout au début, pile au milieu et tout au bout, en attendant deux secondes à chaque arrêt. L'Arduino indique au moteur l'angle à

Utilisation d'une LED RVB
Trois couleurs se cachent dans une seule LED : la LED RGB s'allume en rouge, puis en vert, puis en bleu, chaque couleur allumée une demi-seconde puis éteinte une demi-seconde, avant que tout recommenc

Ampoule 220V avec bouton poussoir (Push)
Tant que tu appuies sur le bouton, une vraie ampoule de 220 volts reste allumée, et elle s'éteint dès que tu relâches. Le petit signal de l'Arduino ne peut pas allumer l'ampoule directement : un relai

Communication unidirectionnelle entre 2 Arduino
Tu fais discuter deux Arduino par un seul fil : appuie sur le bouton de l'un et la LED de l'autre s'allume, appuie encore et elle s'éteint. La carte qui envoie signale l'appui par un court message, et
Autres articles
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 160 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

