La programmation Multi-Thread sous C++ Builder 1. ORIGINE DU SUJET Le sujet du présent examen a pour origine la réfection d’un banc de mesure de puissance à la jante d’automobiles. 2. OBJECTIF Vérifier certains savoir-faire liés aux compétences, réaliser et tester en couvrant les champs technologiques «Informatique» et «Automatisme». En particulier, le domaine étudié est l’interface homme / machine sous Windows avec l’architecture document - vue du modèle SDI et la programmation Multi-thread ainsi que la synchronisation par échange de message. Points techniques abordés : 3. Application basée sur le modèle SDI Boutons de commande Zone d’édition Thread Messages Traitement d’exceptions CONDITIONS DE REALISATION Travail individuel : 4 heures dont 1h30 d’analyse Une partie des documents est distribuée à l’issue de ce temps P r og r ammat i on M ul t i - T hr e ad, 4. MISE EN SITUATION 4.1. Objectif L’objectif de ce projet est de réaliser la réfection d’un banc de puissance à la jante AUTO TECHNIC GAZ du Mans. Cette réfection permet également l’automatisation du relevé des mesures par l’intermédiaire d’un ordinateur équipé d’une carte d’entrées / sorties multifonctions et de son logiciel d’exploitation. 4.2. Définition de la partie opérative La partie opérative existante est représentée par la figure ci-dessous. La voiture, par l’intermédiaire de ses roues motrices, entraîne les rouleaux du banc. Le couple résistant produit par le frein électromagnétique sur les rouleaux ainsi que leur vitesse de rotation sont relevés pour différentes valeurs de vitesse prédéterminées. Codeur incrémental (mesure de la vitesse) Rouleau d’entraînement Frein electro-magnétique Jauge de contrainte (mesure du couple) Dispositif de blocage des rouleaux pour la manœuvre du véhicule La prise de différentes valeurs simulant un accroissement de dénivellation de la route permet de tracer la caractéristique de puissance et de couple de la voiture. Les rouleaux ont une circonférence d’un mètre linéaire. A partir de cette donnée et de la vitesse de rotation des rouleaux, la vitesse du véhicule en Kilomètre par heure est facilement déduite. L Y C E E D U G R E S I VA U D A N MEYLAN 1 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, 4.3. Définition de la partie commande Cette partie fait l’objet du développement à la charge d’une équipe d’électrotechniciens. Elle est constituée d’une armoire de commande renfermant entre autre un gradateur pour la commande du frein, un micro automate TSX, un afficheur déporté et un boîtier de commande pour piloter le système du véhicule. L’ordinateur et l’automate dialoguent entre eux par l’intermédiaire d’entrées / sorties «tout ou rien » afin de synchroniser le processus de mesure. Des commutateurs et autres poussoirs assurent la mise en marche et la configuration du système. Des voyants sur l’armoire permettent de suivre l’évolution du processus. E/S TOR (5+3) E/S Analogique Partie à informatiser L Y C E E D U G R E S I VA U D A N MEYLAN 2 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, 4.4. Echange avec l’armoire de commande Le dialogue entre l’armoire et l’ordinateur se fait par une liaison fil à fil sur des entrées / sorties TOR. La signification des différents signaux a été définie en collaboration avec l’équipe des électrotechniciens qui réalisent l’armoire. Il en résulte : En entrée pour l’ordinateur Bit 0 Etat de l'armoire Le bit est au niveau haut lorsque l’Armoire est prête et au niveau bas pour signaler un défaut. Bit 1 Type d'acquisition Le bit est au niveau haut pour "PUISSANCE" et au niveau bas pour "ACCELERATION". Bit 2 Arrêt Demandé Le bit est au niveau haut lorsque l’opérateur a appuyé sur le bouton «Fin » Bit 3 Début Cycle Le bit est au niveau haut lorsque l’opérateur a appuyé sur le bouton «Début Cycle ». En sortie pour l’ordinateur Bit 0 Cycle de mesure en cours Le bit est au niveau haut lorsque les mesures sont en cours. Permet l’allumage du voyant «Cycle en cours ». Bit 1 Ordinateur prêt Le bit est au niveau haut lorsque le PC de supervision est prêt à acquérir des mesures. Permet l’allumage du voyant «Prêt ». Bit 2 Fin de mesure Le bit est au niveau haut lorsque l’acquisition des mesures est terminée. Chacun de ces bits est respectivement relié soit au mot d’entrées (8 bits) soit au mot de sorties (8 bits également) de la carte d’entrées / sorties multifonctions et plus particulièrement au groupe d’entrées / sorties TOR de cette carte. L’étude présentée ici porte uniquement sur la gestion de cet échange entre l’armoire de commande et l’ordinateur. L’examen de la description d’un des cas d’utilisation présenté ciaprès en montre l’importance. L Y C E E D U G R E S I VA U D A N MEYLAN 3 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, 4.5. Exemple le cas d’utilisation : « Mesure de la puissance » Détail du cas d’utilisation : Réf. : UC 4 / BPJ Etends le cas d’utilisation Réalisation d’un essai Utilise le cas d’utilisation Régulation de la vitesse des rouleaux Pré Conditions Le contrôleur a paramètré une vitesse d'attente et suffisamment de paliers de mesure pour tracer une courbe représentative. La valeur de la vitesse d'attente est inférieure aux paliers de mesure. Description détaillée A la demande d'un contrôle de puissance en mode automatique, la courbe de puissance et les acquisitions qui la composent sont initialisées. Le rafraîchissement des entrées / sorties de l'armoire est lancé pour obtenir les commandes du contrôleur au niveau de l'armoire et l'informer de l'évolution du processus. Le banc de puissance fixe la vitesse d'attente à partir des paramètres de l'essai qui ont été présélectionnés et lance la régulation de la vitesse des rouleaux. Le voyant "Ordinateur prêt" clignote. Lorsque la vitesse du véhicule est stabilisée à la vitesse d'attente, le voyant "Ordinateur prêt " reste allumé et le contrôleur peut appuyer sur le bouton "Début cycle". A partir de cet instant, une nouvelle série de mesures qui compose les acquisitions est créée. Le voyant "Cycle en cours" s'allume à son tour. Le régulateur reçoit alors une nouvelle consigne de vitesse désignant un premier palier de mesures. La vitesse à nouveau stabilisée, la valeur du couple et de la vitesse sont ajoutées aux acquisitions de la série de mesures courante, la puissance est calculée et la courbe de puissance est doté des nouveaux points C= f(V) et P = f(V). Le procédé reprend pour chaque palier de mesure. A la fin de la série de mesures, le voyant "Fin de cycle" s'allume et le voyant "Cycle en cours" s'éteint. Le régulateur reçoit alors la valeur de la vitesse d'attente comme consigne, le voyant "Ordinateur prêt" se remet à clignoter jusqu'à ce que la vitesse du véhicule se stabilise à nouveau. Le contrôleur à partir du boîtier de commande dispose de deux possibilités, soit refaire une nouvelle série de mesures avec les mêmes paliers en appuyant sur le bouton "Début cycle" ou arrêter les acquisitions en appuyant sur le bouton "Arrêt". Dans les deux cas le voyant "Fin de cycle" s'éteint. Lorsqu'il choisit l'arrêt, il relâche petit à petit la pédale d'accélérateur et rétrograde chaque rapport de vitesse pour arrêter le véhicule. Pendant ce temps, le régulateur libère progressivement le frein jusqu'à annulation de la force de freinage. A la fin de l'essai, ou lorsqu'il est choisi de l'interrompre, le contrôleur appui sur le bouton "Arrêt des acquisitions" sur le panneau de contrôle de l'ordinateur, le voyant "Ordinateur prêt" s'éteint et l'utilisateur est invité à sauvegarder ses acquisitions sur disque. Il conduit pour partie au développement des classes BancDePuissance et ArmoireDeCommande. Il conduit pour partie au développement des classes Régulateur et PropriétésEssai. Il conduit au développement de la classe CourbesAcquisition qui réalise l’affichage des courbes pendant les acquisition ainsi que la partie de la classe Acquisition permettant le stockage des données. A prévoir également pour cette classe la sauvegarde sur disque. Réf. : OSD4 / BPJ Diagramme de séquence : L Y C E E D U G R E S I VA U D A N MEYLAN 4 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, «user» Courbes Acquisition Demande de courbes de puissance Initialisation du stockage des données Initialisation de l'acquisition Activation de la surveillance de l'armoire Obtention de la vitesse d'attente Le frein reçoit la consigne de vitesse d'attente Activation de la régulation de vitesse Clignotement du voyant "Ordinateur prêt" Répéter Vitesse d'attente stabilisée Allumage voyant "Ordinateur prêt" Mise à jour des sorties Suivant l'action du contrôleur Cas Appui sur Début Mesure Départ de la procédure de mesures Création d'une nouvelle série de mesures changement de consigne Obtention première vitesse de la série Indication de la première consigne de vitesse Allumage voyant "Début cycle" Si le voyant fin de cycle est allumé Extinction du voyant "Fin de cycle" FSi Pour chaque palier de mesure Vitesse de consigne atteinte Mémorisation du points de mesure Passage au palier de mesure suivant Obtention du palier de vitesse suivant Indication de la nouvelle consigne de vitesse Si on est revenu à la vitesse d'attente Extinction du voyant cycle en cours Allumage voyant fin de cycle Clignotement du voyant "Ordinateur prêt" FSi Fin Pour Cas Appui sur Arrêt Arrêt de la procédure de mesure Extinction du voyant "Fin de Cycle" Extinction du voyant "Fin de cycle" FCas Jusqu'à "Arrêt de l'acquisition" ou "Arrêt" «user» Propriétés Essai «user» Armoire De Commande «business» Banc De Puissance «business» Acquisitions «business» Régulateur Courbe Puissance Initialiser Series Mesures Initialiser Acquisitions Puissance Active Surveillance Obtenir Vitesse Fixer Consigne Régulation de la vitesse des rouleaux Ecrire Mot Sorties Vitesse Stabilisée Allumer Voyant Ecrire Mot Sorties Début Mesures Créer Nouvelle Serie Lancer Acquisition Puissance Obtenir Vitesse Fixer Consigne Ecrire Mot Sorties Ecrire Mot Sorties Vitesse Stabilisée Mémoriser Mesures Changer Consigne Freinage Obtenir Vitesse Fixer Consigne Ecrire Mot Sorties Ecrire Mot Sorties Ecrire Mot Sorties Arrêt Mesure Eteindre Voyant Ecrire Mot Sorties Recommandations pour la conception : L’application doit séparer l’IHM de la partie commande. La classe Acquisition constitue le document de l’application. Elle contient les données et en organise la sauvegarde et la restitution. La structure de données permettant de mémoriser les différentes séries de mesure est à définir. Elle doit impérativement utiliser les classes conteneur de la librairie STL. La classe Courbe De Puissance constitue une vue de l’application. Elle reçoit des messages qui lui permettent de tenir à jour l’affichage, de transmettre les données dans le document et d’appeler des méthodes de la classe Banc De Puissance. Cette dernière réalise les traitements correspondants à ce type d’essai. L Y C E E D U G R E S I VA U D A N MEYLAN 5 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, 5. PREPARATION 5.1. Analyse 1. Proposer une interface Homme – Machine permettant de visualiser l’état du système et son pilotage. Elle doit permette de montrer l’état des entrées du systèmes, la vitesse des rouleaux et le couple exercé. 5.2. Conception 2. Compléter le diagramme de classes issue de l’analyse pour qu’il soit implémenté sous C++ Builder en séparant l’IHM de l’application. 3. En utilisant le document réponse, indiquer les relations qui doivent être implémentées sous la forme de pointeurs et celles qui sont déjà implémentées par Builder dans ce dernier cas préciser la méthode qui fournit le pointeur. La méthode int CArmoireDeCommande : :Run() a pour rôle la gestion des entrées / sorties TOR de l’armoire de commande. Elle permet ainsi de faire fonctionner les voyants et de lire les commandes de l’utilisateur. L’état des voyants est mis à jour par la méthode void EcrireMotSorties(BYTE Valeur) de cette même classe. Les commandes de l’utilisateur sont transmises par l’envoi du message MESSAGE_ARMOIRE à la vue. 4. A partir du diagramme de séquence et en respectant le diagramme de classes, indiquer les paramètres à fournir au constructeur de la classe CArmoireDeCommande pour que la méthode Run puisse tenir son rôle justifier votre réponse. 5. En déduire l’algorithme de la méthode Run sachant que l’attribut BYTE m_Boutons représente l’état antérieur des entrées, BYTE m_Voyants celui des sorties et bool m_Clignotant indique que le voyant Ordinateur_Prêt clignote. Pour un fonctionnement correct, il est préconisé d’endormir le Thread pendant 250 ms à chaque tour de boucle avec l’instruction Dormir(250). On souhaite par ailleurs un clignotement d’environ 1 seconde pour le voyant Ordinateur_Prêt. 6. Pour la transmission de message Windows propose deux mécanismes, indiquer celui retenu pour l’application, justifier votre réponse. 7. Après l’étude du diagramme de classe et du diagramme de séquence indiquer où le Thread Surveillance_Armoire doit-il être instancié, créé, lancé, suspendu sachant que l’application ne s’arrête réellement que lors de l’appui sur «Fichier - Quitter». Justifier votre réponse. L Y C E E D U G R E S I VA U D A N MEYLAN 6 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, 6. CODAGE La vue partielle du diagramme de classe de conception nous amène à l’élaboration d’un projet répondant au modèle SDI et la conception du prototype suivant permettant de visualiser l’état du système et de piloter l’application. Cette ressource est identifiée par IDD_PROPRIETE_ACQUISITION_FORM, les zones de texte statique par IDC_STATIC_NOM_DE_LA_ZONE, les zones d’édition par IDC_EDIT_ NOM_DE_LA_ZONE de même pour les autres ressources. Prend la valeur «Puissance » ou «Accélération en fonction de la valeur du bit 1 Les zones d’édition ne font l’objet d’aucun traitement ici . 1. Implémenter les différentes relations entre les classes métiers présentent sur le diagramme de classes nécessaires au fonctionnement de l’application sous la forme de pointeurs. 2. Sachant que la méthode CAcquisitionsDoc : :OnNewDocument() permet d’instancier la classe CBancDePuissance et de créer suspendu ce Thread, que le constructeur de CBancDePuissance en fait de même avec la classe CArmoireDeCommande, réaliser le code nécessaire à ces opérations en tenant compte des questions 4 et 7 de la préparation. 3. En vous aidant du code de la classe CCarteACL8112 fournie, coder l’algorithme de la méthode int CArmoireDeCommande : :Run() L Y C E E D U G R E S I VA U D A N MEYLAN 7 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, 4. Les différentes classes instanciées dans la classe CCarteACL8112 font appel à une gestion d’erreurs par boites de dialogue. Pour rester en phase avec l’architecture demandée, modifier la classe CentreesSorties en utilisant une gestion d’erreurs par exceptions. 5. Réaliser le code nécessaire dans la classe CPropriétésAcquisitionView pour la réception du message «MESSAGE_ARMOIRE », mettre à jour l’affichage en fonction du paramètre wParam accompagnant ce message. 6. Pour des raisons de mise au point, la régulation de la vitesse des rouleaux exprimée par l’utilisation d’un cas d’utilisation dans le diagramme de séquence est remplacée par l’apparition et la disparition de la boîte de dialogue cidessous. La création non modale de cette boîte doit se faire dans la méthode CPropriétéAcquisitionView : :OnInitInstance(), compléter le code des méthodes OnBoutonLancer et OnBoutonArrêter de la classe CPropriétéAcquisitionView et des appels successifs en respectant le diagramme de séquence pour faire apparaître et disparaître la boîte de simulation. 7. L’appui sur le bouton de la boîte de dialogue envoi le message «VITESSE_STABILISEE » le paramètre de ce message prend l ‘état de la case à cocher. Réaliser le code nécessaire au traitement de ce message dans la classe CAcquisitionPropriétéView. 8. En respectant le plus fidèlement possible le diagramme de séquence proposé, coder les différents éléments non réalisés jusqu’à présent. L Y C E E D U G R E S I VA U D A N MEYLAN 8 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, 7. ANNEXES 7.1. Diagramme des cas d’utilisation Diagramme de cas d'utilisation(UCD00001.DAT) uses Paramètrage d'un essai Régulation de la vitesse des rouleaux uses Mesure de la puissance Acquisition de la vitesse et du couple Mesure de l'accélération ou de la décélération extends uses Contrôle de la vitesse extends Réalisation d'un essai Parmètrage du véhicule uses Contrôleur Exploitation des résultats uses Parmètrage d'une courbe Type : Diagramme de cas d'utilisation Page Réf. : UCD / BPJ Date de dernière modification : 18/11/00 Par : Philippe CRUCHET 7.2. L Y C E E D U G R E S I VA U D A N MEYLAN 9 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, 7.3. Sources 7.3.1. Code de la classe CCarteACL8112 // CarteACL8112.cpp: implementation of the CCarteACL8112 class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "CarteACL8112DLL.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CCarteACL8112DLL::CCarteACL8112DLL() { //Instanciation des classes qui compose la carte rCAN = new CCAN(); rCNA = new CCNA(); rEntrees = new CEntreesSorties(); rSorties = new CEntreesSorties(); rTimer = new CTimer0(); } CCarteACL8112DLL::CCarteACL8112DLL(short NombreConversion) { //Instanciation des classes qui compose la carte rCAN = new CCAN(NombreConversion); rCNA = new CCNA(); rEntrees = new CEntreesSorties(); rSorties = new CEntreesSorties(); rTimer = new CTimer0(); } CCarteACL8112DLL::~CCarteACL8112DLL() { //Destruction des instances delete rCAN; delete rCNA; delete rEntrees; delete rSorties; delete rTimer; } void CCarteACL8112DLL::ConfigurerCarte(int AdresseCarte ,short NumCarte) { /* *Cette méthode initialise la carte 8112DG avec son adresse et un numéro */ if(W_8112_Initial(NumCarte,AdresseCarte)!=ERR_NoError) L Y C E E D U G R E S I VA U D A N MEYLAN 10 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, { AfxMessageBox("Erreur configuration carte"); } } 7.3.2. Code de la classe CEntreesSorties // EntreesSorties.cpp: implementation of the CEntreesSorties class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" //#include "bancderouleaux.h" #include "EntreesSorties.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CEntreesSorties::CEntreesSorties() { } CEntreesSorties::~CEntreesSorties() { } unsigned char CEntreesSorties::LireEntrees(short PoidFaible) { /* *Cette méthode retourne les 8 bits de poid fort ou faible des entrées TOR */ unsigned char MotLu = 0; if(W_8112_DI(PoidFaible,&MotLu) != ERR_NoError) AfxMessageBox("Erreur Lecture Entrées TOR"); return(MotLu); } void CEntreesSorties::EcrireSorties(unsigned char Mot,short Poid) { /* *Cette méthode écrit les 8 bits de poid fort ou faible */ if(W_8112_DO(Poid,Mot) != ERR_NoError) AfxMessageBox("Erreur Ecriture Sorties TOR"); } unsigned int CEntreesSorties::LireBitEntrees(short NumBit) { L Y C E E D U G R E S I VA U D A N MEYLAN 11 / 14 APSII DAI 2002 P r og r ammat i on M ul t i - T hr e ad, /* *cette méthode retourne l'état du bit(0 à 15) lu */ unsigned int Valeur=0; if(W_8112_DI_Channel(NumBit,&Valeur)!= ERR_NoError) AfxMessageBox("Erreur Lecture Entrées TOR"); return(Valeur); } L Y C E E D U G R E S I VA U D A N MEYLAN 12 / 14 APSII DAI 2002 7.4. Diagramme de classes 1 «user» Armoire De Commande 1 «business» Acquisitions 1 «business» Banc De Puissance 1 Ecrire Mot Sorties Obtenir Choix Utilisateur Lire Mot Entrées Obtenir Vitesse Initialiser Series Mesures Créer Nouvelle Serie Obtenir Coefficient Obtenir Couple «user» Capteur Couple 1 Obtenir Temps 1 1 1 Lancer Acquisition Puissance Ouvrir Vehicule Lire Vitesse Arrivée Initialiser Contrôle Accélération Changer Consigne Vitesse 1 1 1 1* 1 1 «business» Chronomètre 1 «business» Régulateur Déclencher Fixer Consigne Arrêter Activer Régulateur de vitesse Lire Temps 1 Fixer Vitesse Depart Fixer Consigne freinage Renommer Série «business» Base De Registres Fixer Vitesse Arrivée Modifier Etat Série Arrêter Acquisition Modifier Valeur Lire Vitesse Départ Obtenir Série Eteindre Voyant 1 Fabriquer Liste Véhicules Supprimer Série Clignoter Voyant 1 Lire Consigne Freinage Obtenir Paramètres Série Changer Consigne Freinage «user» Frein Fabriquer Liste Marques Annuler Mise A Jour Véhicule Initialiser Acquisitions Puissance Lire Vitesse Obtenir Vitesse Valider Mise A Jour Vehicule Allumer Fin Cycle Obtenir Vitesse d'attente Mémoriser Mesures Supprimer véhicule Lancer Régulation 1 1 Modifier Véhicule Lancer Courbe Puissance «user» Capteur Vitesse 1 Ajouter véhicule Allumer Voyant Lire Couple «user» Propriétés Essai Commenter Série Obtenir Commentaire 1 1 Commenter Essai 1 1 1 1 1 1 1 1 «user» Propriétés Acquisition 1 «user» Courbes Acquisition 1 1 «user» Menu Courbe «user» Propriétés Exploitation 1 «user» Fiche Essai 1 «user» Fiche Courbe 1 1 «user» Propriétés Véhicule 1 1 «business» Véhicule 1 «user» Courbes Exploitation Changer Axe Vitesse «business» Procès Verbal 1 1 Imprimer Entete Imprimer Courbes Imprimer Tableaux