Lecteur PWM Arduino Efficace & Décodeur Récepteur RC avec Fail-Safe Intégré
Composants et fournitures
| Arduino UNO | 1 |
| Servomoteur SG90 | 2 |
À propos du projet
Ce projet propose un code générique et efficace pour lire un récepteur RC (ou tout signal PWM) sur n'importe quelle broche d'entrée Arduino, avec fail-safe en cas de perte du signal émetteur.
La vidéo ci-dessous montre un Arduino Uno agissant comme mélangeur de servos grâce au code PWMread_RCfailsafe.ino (disponible en bas de page).
Les fonctions de ce fichier gèrent les registres d'interruption pour vous et s'adaptent facilement à différents projets utilisant différentes broches.
Dans l'exemple vidéo :
- Le fail-safe s'active quand le récepteur perd le signal : canal profondeur = cabré max, canal aileron = neutre.
- La direction du servo bleu est pilotée par la gaz.
- L'amplitude (rates) du servo bleu est réglée par le curseur latéral de l'émetteur.
- Le mélange est activé/désactivé par l'interrupteur « gear » de l'émetteur.
Sommaire
- Comment les servos sont contrôlés par PWM
- Exemples d'utilisation d'Arduino en modélisme RC / robotique
- Vue d'ensemble du code : décodage PWM récepteur RC avec fail-safe
- Comment utiliser
PWMread_RCfailsafe.ino - Afficher la fréquence et la période de trame du récepteur
- Exemple de mélange de servos
- Justification de l'approche
- Limitations
Comment les servos et variateurs sont contrôlés par PWM ?
On suppose que vous comprenez les signaux PWM pour servos/variateurs. Voici une bonne vidéo explicative.
Connaissances requises : IDE Arduino, variables float/boolean/int, boucles if/for, tableaux, bibliothèque Servo.
Exemples d'utilisation d'Arduino en modélisme RC / robotique
Votre imagination est la seule limite :
- Mélange de servos, allumage/extinction de lumières, commande pompes/vannes, séquences personnalisées…
- Créer un contrôleur (stabilisation de vol/autopilote, tenue de cap/altitude/profondeur, auto-nivellement, détection/évitement, retour à la base…)
- Réagir à une perte de signal ou basse tension batterie…
- Utiliser le même émetteur pour plusieurs modèles/projets sans changer les réglages ni utiliser la mémoire de modèle.
Vue d'ensemble du code : Décodage PWM récepteur RC avec fail-safe
Ce code mesure les signaux PWM par interruptions sur changement d'état (Pin Change Interrupts). Les fonctions automatisent la configuration des interruptions et l'extraction des données sur n'importe quelle broche numérique ou analogique (sauf A6/A7) sur Uno, Nano, Pro Mini. Facile à utiliser même pour débutants.
Objectif principal : créer un « module » générique de lecture récepteur RC avec fail-safe, déplaçable rapidement entre projets. Le code d'exemple dans « Comment utiliser » est un moyen vers cette fin.
Note : incompatible avec SoftwareSerial ou toute bibliothèque utilisant les interruptions sur changement d'état.
Fonctionnement interne (pour les curieux) :
- Les broches d'entrée sont listées dans un tableau (longueur variable).
- Une fonction d'initialisation active les interruptions sur changement d'état en configurant les registres appropriés pour chaque broche.
- Un changement de tension sur une broche sélectionnée déclenche l'une de 3 routines de service d'interruption (ISR) selon le port :
ISR(PCINT0_vect)→ Port B,ISR(PCINT1_vect)→ Port C,ISR(PCINT2_vect)→ Port D. - Dans chaque ISR, une boucle FOR + tests IF déterminent quelle broche a changé et à quel canal RC elle correspond. L'instant de l'interruption est capturé via
micros()avant de retourner auloop()principal. - Les intervalles de temps entre changements donnent la largeur d'impulsion et la période de répétition.
- Des drapeaux (flags) sont positionnés dans chaque ISR pour signaler la réception de nouvelles impulsions.
- Ces drapeaux sont exploités par les autres fonctions pour extraire et traiter les données collectées par les ISR.
La vidéo YouTube de Joop Brokking (premières 8 min) explique clairement cette méthode d'interruption sur changement d'état pour mesurer le PWM d'un récepteur RC.
Tout ce détail est géré par PWMread_RCfailsafe.ino (téléchargeable en bas).
Info utile sur la manipulation de ports : tronixstuff.com
En plus de la gestion d'interruption, une fonction dédiée RC_decode() convertit une largeur d'impulsion (1000–2000 µs) en signal de commande ±100%. Un fail-safe vérifie la validité du signal émetteur (tolérances : 10–330 Hz, 500–2500 µs). Si le signal est perdu, RC_decode() retourne une valeur de fail-safe prédéfinie.
Les valeurs d'étalonnage par émetteur et positions de fail-safe par canal sont réglables dans PWMread_RCfailsafe.ino.
Comment utiliser PWMread_RCfailsafe.ino
Étape 1 : Exemple de montage hardware avec Arduino Uno
Si vous suivez l'exemple avec un Uno :
- Alimentez le récepteur via 5V et GND.
- Connectez les fils de signal du récepteur aux broches 2 à 7 de l'Aruno (fils femelle-mâle). (Récepteur 2 canaux → broches 2 et 3 seulement).
- Pour l'exemple mélangeur servos : fil signal servo 1 → broche 9, servo 2 → broche 10.

Étape 2 : Copier PWMread_RCfailsafe.ino dans le dossier du sketch
Un sketch exemple RC_Read_Example est fourni en téléchargement. Utilisez-le comme sketch principal. Copiez-collez le fichier PWMread_RCfailsafe.ino dans le même dossier. À la réouverture dans l'IDE, un second onglet apparaît avec le code.

Étape 3 : Spécifier les broches d'entrée
Ouvrez l'onglet PWMread_RCfailsafe, descendez à « USER DEFINED VARIABLES » et entrez les broches dans le tableau pwmPIN[].
Note : nombre de broches libre, ordre libre. Plus d'entrées = plus de temps passé dans la routine d'interruption. A6/A7 (analogiques seulement) inutilisables. Arduino Mega non supporté actuellement (facile à ajouter si demande).
Note : le 1er élément = canal 1, 2e = canal 2… Si vous utilisez tous les canaux du récepteur, alignez l'ordre.

Étape 4 : Examiner les fonctions disponibles

Étape 5 : Afficher les largeurs d'impulsion brutes sur le port série
Téléversez RC_Read_Example, allumez l'émetteur, affichez les largeurs d'impulsion brutes via print_RCpwm() quand RC_avail() signale de nouvelles données sur tous les canaux.

Étape 6 : Étalonner l'émetteur
À partir des largeurs brutes affichées, modifiez manuellement les tableaux RC_min[], RC_mid[], RC_max[] pour calibrer chaque canal en ±100%.

Étape 7 : Afficher les canaux étalonnés
Commentez print_RCpwm(). Utilisez RC_decode(channel) pour obtenir chaque canal en ±1, puis affichez avec decimal2percentage() + Serial.println().

Étape 8 : Régler le fail-safe
Ajustez les positions de fail-safe dans RC_failsafe[] pour chaque canal (plage ±1). Coupez/remettez l'émetteur pour vérifier le fonctionnement.
L'entrée RC est maintenant utilisable dans votre sketch.
Note : vous devrez peut-être désactiver le fail-safe du récepteur, sinon l'Arduino ne pourra pas détecter la perte de signal émetteur.

Afficher la fréquence et la période de trame du récepteur
La période et la fréquence de répétition peuvent être affichées sur le port série. Vérifiez la dispo de nouvelles données sur le canal choisi avec PWM_read(numéro canal), puis utilisez PWM_period() et PWM_freq(). Exemple dans RC_FrameRate.ino.
Utilisez de préférence le canal 1 (premier impulsé par trame). PWM_read() utilise les mêmes drapeaux que RC_decode() : appelez PWM_read() en premier.

La période du récepteur indique le temps dispo avant la prochaine trame. Si RC_avail() ne détecte pas de nouvelles données après un temps prédéterminé (ex: 21 ms), lancez RC_decode() pour déclencher le fail-safe et/ou faire tourner le programme (ex: régulateur PID) à fréquence stable.
C'est ce que fait le if suivant dans RC_Read_Example.ino :
now = millis();
if (RC_avail() || now - rc_update > 21) {
rc_update = now;
// mettre à jour les données RC via RC_decode()
// exécuter un régulateur PID
// appliquer le mélange de servos
// positionner les servos
}
Exemple de mélange de servos
RC_ServoMixer_Example.ino montre comment mélanger deux canaux récepteur (canaux 2 et 3 : profondeur et aileron). Le sketch illustre aussi la définition de direction, rate et sub-trim des servos. La bibliothèque Servo pilote les servos sur broches 9 et 10.

Le mélange s'obtient par addition/soustraction des deux canaux, limité à ±1. Deux sorties : une par servo.
mix1 = canal2 - canal3 (prof - ail)
mix2 = canal2 + canal3 (prof + ail)
Avant de commander les servos, convertissez le signal ±100% en largeur d'impulsion µs équivalente. Dans l'exemple, la fonction calc_uS() fait cela.

La direction, le rate et le sub-trim de chaque servo servent à calculer la largeur d'impulsion appropriée.
Impulsion neutre standard = 1500 µs, plage normale ±500 µs → min 1000 µs (-100%), max 2000 µs (+100%). Avec rate, direction, sub-trim :
impulsion µs = 1500 + (position_servo_% × rate × direction + sub_trim) × 500
Direction, rate, sub-trim peuvent être statiques ou modifiés dynamiquement par le sketch selon une autre entrée récepteur ou autre moyen.
Justification de l'approche
On peut lire un récepteur RC avec pulseIn(PIN, HIGH), mais cette fonction bloque le loop() en attendant le début et la fin de l'impulsion, gaspillant du temps CPU. Avec plusieurs entrées, des données peuvent être perdues.
Pour la vitesse, mieux vaut utiliser les interruptions sur changement d'état + manipulation directe des ports, laissant le loop() tourner avec un délai minimal. Mais c'est plus complexe et chronophage que pulseIn().
D'où l'idée : écrire un code générique réutilisable. Il suffit de copier-coller un fichier .ino (fonctions + routines ISR) dans le dossier du sketch principal, spécifier les broches d'entrée, et utiliser les fonctions dans le sketch.
Limitations
La fonction micros()
Le chronométrage microsecondes sur Arduino utilise micros(), qui compte par pas de 4 µs. Précision de 4 µs sur des impulsions 1000–2000 µs : amplement suffisant en pratique.
Amélioration possible à 0,5 µs via interruptions timer : instructables.com.
Efficacité de PWMread_RCfailsafe.ino
Pour un récepteur 6 ou 9 canaux : 1,4–2,0% du temps CPU dans les routines ISR, tout à fait acceptable.
Temps d'exécution de chaque ISR selon le nombre de canaux :
| 1 canal | < 8 µs |
| 2 canaux | < 12 µs |
| 3 canaux | < 16 µs |
| 4 canaux | < 20 µs |
| 5 canaux | < 20 µs |
| 6 canaux | < 24 µs |
Note : plus de canaux = ISR plus longue (boucle FOR sur chaque canal à chaque appel ISR). Cette surcharge est négligeable pour signaux RC basse fréquence (50 Hz).
En plus : ~4 µs pour entrer/sortir d'une ISR. Pour une impulsion, l'ISR s'exécute 2 fois (front montant + front descendant).
Temps pour mesurer 1 impulsion avec 6 entrées RC : 2 × (4 + 24) = 56 µs (largeur d'impulsion minimale mesurable).
Temps pour lire 6 canaux : 6 × 56 = 336 µs.
Avec une période de répétition de 20 ms, l'interruption tourne 0.000336 / 0.02 = 1,68% du temps. Bien mieux que pulseIn() qui bloquerait jusqu'à 20 ms par broche.
FYI : avec 2 entrées RC seulement : 0.000032 / 0.02 = 0,16% du temps.
Fréquence pratique maximale (Hz)
Pour d'autres usages, fréquence max pratique suggérée : 2,5 kHz. Cela donne 100 pas de résolution via micros() (±0,025 kHz).
Avec 1 entrée à cette fréquence : 3% du temps en interruption → duty cycle minimal mesurable = 0,03 → impulsion minimale = 12 µs.
Pour fréquences plus élevées, réécrivez l'ISR pour votre application.
Code
PWMread_RCfailsafe.ino— fonctions + routines ISR (copier dans dossier sketch principal)RC_Read_Example.ino— exemple affichage données brutes pour étalonnage + fail-safeRC_FrameRate.ino— exemple affichage période/fréquence trame récepteurRC_ServoMixer_Example.ino— exemple mélange 2 canaux → 2 servos
Le code complet de PWMread_RCfailsafe.ino est inclus dans la section Code du projet original (très long, non reproduit ici pour concision).
Schémas
Récepteur RC alimenté par 5V/GND des broches ICSP, 6 signaux sur broches 2–7.
Micro servo 1 : 5V + GND, signal broche 9.
Micro servo 2 : 3,3V + GND, signal broche 10.

Processus de fabrication
- Maîtriser les entrées/sorties en C : Fonctions standards et fichiers
- Créer des animations et jeux sur LCD avec Arduino UNO
- Construire un Voltmètre Intelligent avec Arduino et Smartphone – Projet DIY Facile
- Enregistreur de Température et Humidité Arduino avec DHT11 et Shield Ethernet
- Lire température et humidité avec DHT11 sur Blynk – Tutoriel Arduino pas à pas
- Contrôle Arduino UNO depuis Python 3 – Communication Série et Démo LED
- Automates Cellulaires Temps Réel sur Arduino avec Écran OLED 128x64
- Construire une Radio FM Compacte avec Arduino Nano et RDA5807M
- Circuit d'entrée analogique isolée pour Arduino : Protection contre les parasites industriels