Rolling Ohms dans ENPH 253
Chaque été, le cours ENPH 253 de l’École de physique appliquée de l’UBC lance des équipes de quatre personnes dans un sprint de six semaines : concevoir un robot totalement autonome chargé de rapatrier des « animaux » (des toutous) vers une zone sécurisée. Notre robot Rolling Ohms suivait la ligne à l’IR, saisissait les peluches amies avec un bras à servos, et catapultait les bestioles dangereuses grâce à des volants en TPU tournant à ~50 km/h, capables d’atteindre 2,5 m de hauteur.
Architecture embarquée
- Deux ESP32 sous FreeRTOS : Un ESP32 « cerveau » orchestrait la conduite, le bras et le lanceur (
src/complete_robot/complete_robot_main.c), tandis qu’une seconde carte gérait l’alignement sur la balise IR et la télémétrie haute fréquence. Chaque fonction tournait dans sa tâche FreeRTOS pour éviter qu’un PID ou une cinématique inverse ne bloque le reste. - PID de suivi de ligne : La tâche
lib/tasks/drive_system.clit deux capteurs de réflexion toutes les 10 ms, applique un correcteur PID autour d’un point d’opération de 900 mV et, si les deux capteurs voient le sol, relance un balayage lent en gardant la dernière direction connue. Cette logique nous a sauvés à l’intégration. - Balayage et prise des peluches : Le module
lib/logic/sweep.cbalaye l’axe de base, surveille les chutes de tension IR et déclenche une séquence coordonnée (avancer, fermer, se rétracter) avant de rendre la main à FreeRTOS. - Communication carte-à-carte :
lib/serial_comm/serial_protocol.cencapsule les commandes en JSON tramé via UART. Les deux ESP32 — ou l’application Python — peuvent ainsi pousser des gains PID, des poses de bras ou ordonner un tir, tout en laissant la télémétrie circuler grâce à des mutex sur les buffers. - Télémétrie et téléop Python :
python/serial_monitor_gui.pyfournit une interface Tkinter qui détecte automatiquement les ports série, trace les flux JSON en direct et expose des curseurs pour les servos, la cinématique X/Y/θ et le lanceur. Nous l’utilisions en parallèle de la tâche FreeRTOS de télémétrie qui publie tensions, état du panier et paramètres PID toutes les 100 ms. - DSP de balise : L’ESP32 dédié à la balise échantillonne la photodiode à 50 kS/s et exécute une transformée de Goertzel à fréquence arbitraire (
src/ir_reciever/reciever_main.c) pour distinguer le signal de secours à 1 kHz du bruit à 10 kHz. On oriente le robot en maximisant la composante 1 kHz et on renvoie l’amplitude sur un canal DAC pour le debug à l’oscilloscope.
Empilement PCB
Trois cartes KiCad, fabriquées chez JLCPCB, reliaient l’ensemble :
- Carte cerveau : ESP32-WROOM, connecteurs pour chaque périphérique (capteurs IR, servos MG90S, photodiodes de balise, FET du lanceur), adaptation de niveau et boutons de jeu. Avec le recul, on aurait dû ajouter des résistances de limitation pour les optocoupleurs des servos et éviter de boucler le 5 V en périphérie pour limiter le bruit.
- Carte H-Bridge : Étages MOSFET quadruples avec optocoupleurs, protection BJT et pilotage high-side pour alimenter quatre moteurs 12 V sans griller les GPIO. L’absence initiale de résistances de limitation sur les optos a demandé un peu de retouche, mais le driver FreeRTOS
h_bridgegère ensuite les rampes via LEDC et mutex. - Carte alimentation : Distribution d’un LiPo 15 V vers des rails logiques, bras et lanceur. Le placement trop dense rendait l’assemblage des condensateurs et dissipateurs délicat (un Dremel s’en souvient) ; la prochaine révision aura davantage d’espace et de cuivre.
Liens de dépôt :
Systèmes mécaniques
Toute la mécanique a été modélisée sous OnShape et produite en impression 3D, découpe laser PMMA et usinage. Quelques éléments marquants :
- Deux capots isolent les capteurs IR (ligne et balise) de la lumière ambiante, ce qui réduit le bruit ADC et justifie nos filtres logiciels.
- Le lanceur utilise des roues TPU avec des écrous et billes métalliques insérés pendant l’impression. On augmente ainsi l’inertie et on auto-équilibre les volants ; au final seules deux commandes PWM — arrêt et plein régime — se sont révélées utiles, le firmware servant surtout d’interrupteur intelligent.
- Le bras combine pièces imprimées et grappins en Delrin découpé. Un MOSFET dédié pilote le lanceur, et des plateaux indexés permettent de changer rapidement l’angle entre deux essais.
Notes de debug
- Les servos de la carte cerveau tiraient trop de courant sur les GPIO ; des résistances ajoutées après coup ont sauvé l’ESP32.
- Faire courir le 5 V autour du PCB a injecté du bruit dans les capteurs de ligne ; prochain spin : rails internes et plans de masse de garde.
- La densité de la carte puissance compliquait la soudure des condensateurs et l’installation des dissipateurs.
- Les optocoupleurs du H-bridge ont finalement reçu des résistances série — heureusement, les pads étaient accessibles.
Leçons retenues
- KiCad sur plusieurs cartes exige des revues d’interface rigoureuses (et des impressions échelle 1) avant la commande.
- Toujours limiter le courant des LED, optos et autres composants branchés sur du 3,3 V.
- Considérer que la future version de vous-même aura oublié les détails : documenter et concevoir pour un dépannage idiot-proof.
- Les vis mangent le temps ; prévoir des assemblages qui se clipsent ou se glissent pour rester dans le calendrier.
- Un bon outillage logiciel — comme l’appli de télémétrie Python — change la vie en intégration.
- Les revues de carte attrapent les erreurs bêtes (bonjour les optos sans résistances) avant que JLCPCB les grave.
- Ajouter des trous de fixation généreux et privilégier la fabrication 2D pour itérer rapidement.
- Lorsque le marché propose un H-bridge fiable, l’acheter peut éviter bien des nuits blanches.
- La collaboration serrée entre firmware, élec et méca est cruciale ; se mettre en silo nous a ralenti plus qu’un bug.