TP 12 — Mini-projet : le tableau de bord
Objectifs
Réunir les outils de cette partie dans un programme complet et organisé : des tâches aux rôles clairs, des échanges par files et par état partagé, une surveillance par chien de garde, et une mesure de la charge.
Durée indicative : trois séances de 3 h, en binôme. Prérequis : les TP 1 à 11 de cette partie.
Le cahier des charges
La carte devient le tableau de bord d’un robot. Elle doit :
Mesurer la température (TMP102, 1 Hz) et le cap (gyroscope, 50 Hz, zéro mesuré au démarrage), et la tension de la batterie (ADC, TP 6 de la partie 1, 2 Hz, moyenne glissante).
Afficher sur l’écran, à 10 images par seconde, trois pages au choix :
mesures : température, tension, cap avec sa boussole ;
système : charge du processeur, marge de pile de chaque tâche, nombre d’erreurs I²C ;
alarmes : la liste des alarmes en cours.
SW1 passe à la page suivante.
Refroidir : le ventilateur (TP 4 de la partie 1) démarre au-dessus de 35 °C et s’arrête en dessous de 32 °C.
Signaler par le voyant RGB (TP 2 de la partie 1) : vert si tout va bien, orange si la batterie est faible (moins de 10,5 V), rouge clignotant en cas d’alarme de température ou de batterie très faible (moins de 10 V). Le buzzer bipe une fois à chaque nouvelle alarme.
Remettre le cap à zéro par un appui long (plus d’une seconde) sur SW2.
Rendre compte au terminal série, une fois par seconde, d’une ligne d’état complète, envoyée par DMA.
Se surveiller : le chien de garde redémarre la carte si l’une des tâches de mesure ou d’affichage cesse de donner signe de vie ; au redémarrage suivant, l’écran affiche « WDG » pendant 3 s.
Contraintes
Une tâche par rôle (mesure, affichage, actionneurs, journal, surveillance), avec une priorité justifiée.
Chaque périphérique a un seul propriétaire, ou une protection explicite.
Aucun
HAL_Delaydans les tâches, aucune variable partagée sans protection, aucune attente active.Les événements (appuis, alarmes) passent par des files ; les états (dernières mesures) par une structure protégée.
La charge du processeur reste sous 30 %, et chaque tâche garde au moins 25 % de sa pile libre.
Ce qu’il faut rendre
Un schéma de l’architecture : les tâches, leurs priorités et leurs périodes, les files, les mutex, les sémaphores, et qui possède quel périphérique.
Le code, commenté, dans un projet CubeIDE propre.
Un tableau de mesures : charge du processeur par tâche, marge de pile par tâche, période réelle de la tâche gyroscope (moyenne et écart maximal).
Une démonstration de cinq minutes, qui montre en particulier le redémarrage par chien de garde : un appui sur SW4 fige volontairement une tâche de mesure.
Grille indicative
Critère |
Points |
|---|---|
Les fonctions 1 à 7 marchent |
7 |
Architecture : rôles, priorités et échanges justifiés |
4 |
Respect des contraintes |
3 |
Mesures : charge, piles, régularité |
3 |
Qualité du code et des commentaires |
2 |
Démonstration |
1 |
Éléments de correction : une architecture possible
Il n’y a pas une solution, mais toute bonne solution répond aux mêmes questions : qui fait quoi, à quel rythme, avec quelle urgence, et qui possède quoi. En voici une, qui respecte le cahier des charges.
Les tâches
Tâche |
Priorité |
Période |
Rôle et ressources possédées |
|---|---|---|---|
|
AboveNormal |
20 ms |
gyroscope (I2C3), intégration du cap ; la plus régulière, donc la plus prioritaire |
|
AboveNormal |
10 ms |
SW1 à SW4, anti-rebond, appui long sur SW2 ; envoie des
événements dans |
|
Normal |
500 ms |
TMP102 (I2C2) à 1 Hz, batterie (ADC2) à 2 Hz, moyenne glissante ; détecte les franchissements de seuils (hystérésis) et envoie les alarmes |
|
Normal |
événements |
ventilateur (TIM12), voyant RGB (TIM1 + PWM logiciel TIM7), buzzer ; réagit aux alarmes, clignote avec le délai de sa file |
|
BelowNormal |
100 ms |
écran (SPI3, DMA, double tampon), pages ; reçoit SW1 par file |
|
BelowNormal |
1 s |
ligne d’état sur UART5 par DMA |
|
Low |
500 ms |
IWDG1 ; relance seulement si |
Les échanges
État : une structure
g_state(température, tension, pourcentage, cap, alarmes, erreurs I²C, charge, marges de pile), protégée par un mutex ; chaque tâche y écrit ses champs, l’affichage et le journal en font une copie.Événements :
eventQueue(boutons → affichage et cap),alarmQueue(capteurs → actionneurs). Une alarme n’est envoyée qu’au franchissement d’un seuil.Fins de transfert : un sémaphore par DMA (SPI3, UART5), levé par le rappel de fin, jamais de travail dans les interruptions.
Les erreurs qui coûtent des points
un
HAL_Delayoublié dans une initialisation appelée depuis une tâche (screen_init) ;printfappelé depuis plusieurs tâches : soit une seule tâche écrit, soit un mutex sur la liaison série ;le chien de garde relancé par une seule tâche, sans vérifier les autres (TP 5) ;
un tampon DMA en DTCM, ou sans nettoyage de cache (TP 6) ;
le cap remis à zéro par l’appui long dans l’interruption, ou par écriture directe de
g_statesans le mutex : c’estimuTaskqui possède le cap, l’appui long doit lui envoyer un événement ;la mesure de charge sur le tableau cumulé plutôt que sur une fenêtre (TP 9) ;
des priorités justifiées par l’importance (« l’écran, c’est ce qu’on voit ») plutôt que par l”urgence.
Le message « WDG » : au démarrage, lire RCC_FLAG_IWDG1RST avant
d’effacer les drapeaux, et le transmettre à displayTask (un champ de
l’état, ou un événement au démarrage).
Pour aller plus loin
Enregistrer : gardez les 100 dernières alarmes, horodatées par la RTC (TP 9 de la partie 1), dans la flash SPI.
Piloter un servomoteur (TP 10 de la partie 1) : il pointe toujours vers le nord de départ, quel que soit le cap.
Passer à ROS : c’est l’objet de la partie 3.
Après le TP
Pour rendre la carte au robot, voir Remettre la carte en état RatBot.