Etape 0 : Prise en main du matériel
-
Maitrise du microcontrôleur
-
Relecture des programmes
La maitrise théorique du matériel et la relecture des programmes ont été faites dans les temps malgré la difficulté de reprendre un programme préexistant et les documentations du capteur et du microcontrôleur entièrement rédigées en anglais. La maitrise réelle d’un point de vue pratique du microcontrôleur a été un peu plus longue au vu du fait qu’un fichier manquait pour pouvoir recompiler le programme s’exécutant sur cet appareil.
Etape 1 : Etude de fiabilité du capteur de champs
-
Procédure de test
-
Expérimentation
-
Analyse des résultats
Cette étude a été réalisée afin de savoir quels étaient les capteurs en état de fonctionner. En effet ces capteurs étant utilisés depuis plusieurs années pour des TP à l’IUP un certain nombre d’entre eux ne sont plus en état de fonctionnement. Nous avons d’ailleurs pu observer lors d’une erreur de manipulation que ces capteurs sont plutôt fragiles.
Etape 2 : Finalisation de l’IHM de mesure
-
Correction de la partie mesure de champ
-
Ou remplacement du capteur et réécriture de cette partie du programme
-
Ajout des fonctions Boussole et Moyennage
Cette étape qui était déjà en cours lors des 2 dernières années et consistant à obtenir des mesures cohérentes de la part du capteur de champ magnétique a enfin abouti. En effet une fois l’étape 0 terminée complètement par la maitrise pratique du microcontrôleur nous avons pu retravailler le code qui permettait d’obtenir les mesures depuis le microcontrôleur ce qui par la suite a permis d’obtenir des mesures cohérentes.
Etape 3 : Rendre les programmes de commande et de mesure compatibles
-
Etude des méthodes de passage CVI<->Labview
-
Mise en place des méthodes les plus efficaces
-
Simplification de l’IHM
L’étude des méthodes de passage de CVI vers Labview ne nous laissait pas vraiment le choix en effet les seuls moyens de réaliser cette adaptation sont : la réécriture du programme en Labview ou l’utilisation de DLL. Au vu du fait qu’une conversion totale était impossible au vu du cahier des charges, nous nous sommes donc tournés vers l’utilisation d’une DLL. Cette adaptation en Labview a aussi été l’occasion d’une simplification de l’IHM, le programme Labview n’ayant pour seul objectif que la mesure de champ contrairement à son homologue en CVI capable de gérer aussi la mesure de température, la génération de PWMs et les conversion analogique/numérique.
Etape 4 : Réalisation d’une IHM commune avec le projet de contrôle du bras
-
Fabrication d’un support pour fixer le capteur sur le bras
-
Codage de l’IHM commune
Cette étape a commencé à être abordée par l’étude des possibilités de mise en place de la chaine de mesure de champ magnétique au niveau du bras. Il a été décidé que le capteur serait placé sur le bras mais que le microcontrôleur et la plaquette de connexion seraient eux déportés à environ 2 mètres. Cette décision nécessite une adaptation qui n’a pu être réalisée faute de temps, la connexion de nouveaux câbles sur le capteur.
Chacune de ces étapes a donc été l’occasion de rencontrer de nouveaux problèmes que nous avons dus surmontés.
Par exemple le microcontrôleur n’exécute pas certaine ligne de code de manière conventionnelle, lors d’un test nous nous sommes ainsi aperçus qu’une boucle réalisant plusieurs fois la même action ne donnait pas le même résultat que de répéter cette action hors d’une boucle. De plus alors que nous lui envoyons des données de configurations identiques pour toutes les PWMs seule la première semble respecter les spécifications envoyées.
Par moment nous avons aussi cherché des problèmes matériels, connaissant les problèmes survenus les années précédentes, alors que le problème venait d’une mauvaise compilation de notre programme.
La dernière grosse difficulté était la compréhension détaillée des différentes documentations rédigées en anglais ainsi que la communication avec le fabricant du capteur de champ magnétique basé aux Pays-Bas. Nous les avons contacté lors de notre recherche de l’erreur puis plus tard lorsque nous avons eu besoin du logiciel permettant de faire fonctionner le kit d’évaluation qui était inaccessible car le lien était mort.
IV.2. Bilan pédagogique
Dans ce projet nous avons pu développer nos compétences en particulier en programmation. En effet, la mesure du champ magnétique par le capteur se code en C, langage que nous avons appris à manipuler au cours de l’année 3 IMACS. La commande du microcontrôleur qui pilote le capteur est quand à elle réalisée sous CVI que nous avons vu cette année en 4 GP et qui reprends les bases du langage C avec une interface simplifiée pour l’utilisateur. Nous avons aussi pu nous exercer sur un autre langage d’instrumentation Labview, que nous avons étudié cette année. Il était en effet important d’utiliser Labview pour pouvoir mettre notre partie du code en commun avec l’autre binôme travaillant sur le bras robotisé sous un seul programme.
De plus sur un plan purement gestion de projet nous avons appris à mener à bien un projet en autonomie, à travailler en équipe ce qui sera un plus pour notre travail en tant qu’ingénieur. Effectivement, nous avons pu travailler et échanger avec nos tuteurs de projet, nous avons aussi eu la chance d’avoir une partie commune avec un autre projet, ce qui nous a permis de se gérer mutuellement avec l’autre binôme. Un projet n’étant pas un travail où l’on maîtrise tous les paramètres, on a appris à anticiper à mesurer certains risque et à les prendre en compte, en un mot à nous organiser. On a tout d’abord définit un planning avec le diagramme de Gantt, où l’on a répertorié chronologiquement les différentes étapes pour mettre à bien notre projet en estimant le temps nécessaire à chacune d’elle.
De par ce projet nous avons donc été confrontés à une situation réelle, avec des contraintes que l’on ne maîtrisait pas toutes mais qu’il a fallu anticiper et nous y adapter. Nous avons alors développé nos compétences techniques et managériales en termes de gestion de projet et de travail en équipe, situation que rencontre l’ingénieur dans son travail de tous les jours.
V. Annexes
Annexe 1 : Description des programmes gsf_projet, fonctions et one.c
Ces programmes ce divisent en 6 grandes parties gérant chacune un des points clefs du programme :
-
L’envoie et la réception de mot de 16 bits
-
La communication RS 232
-
Le module PWM
-
Le module CAN
-
La mesure de champ magnétique
-
La mesure de température humidité
A partir de ce point nous allons détailler le fonctionnement de ces programmes le gsf_projet.c ne sera pas encadré, le fonctions.c sera encadrée en rouge et le one.c en bleu.
Librairies et déclaration de variables
Programme principal et face avant
Comme dans tous programmes possédant une interface graphique la fonction main du gsf_projet est très courte car elle sert uniquement à lancer les fenêtres d’affichage.
Cette portion de code permet l’affichage de l’IHM comportant une barre de menu permettant de choisir le module à charger ensuite.
Ce programme qui est exécuté sur l’ordinateur fonctionne en parallèle de celui qui s’exécute sur le microcontrôleur. Ce dernier permet de déclarer d’autres variables, d’appeler les fonctions d’initialisation, et le réglage des lignes entrées/sorties que nous utiliserons par la suite avec les capteurs. Enfin la partie la plus importante de ce programme est la boucle infinie qui attend la réception des commandes en provenance de l’ordinateur. En fonction de cette commande différentes instructions seront exécutées.
Etablissement de la liaison RS 232
Parmi les fonctions exécutées lors du lancement du programme dans le microcontrôleur l’une d’elles permet l’initialisation du port série :
Lors de l’utilisation de la chaine de mesure cette fonction sera exécutée dès que le microcontrôleur sera en mode « Run ». Une fois ceci fait on peut lancer la communication depuis l’IHM en allant dans le menu « Communication ».
Il suffit alors de choisir le bon port série et de valider. Une fois la liaison correctement établie la fenêtre se ferme et une diode verte s’allume sur la fenêtre de lancement.
Envoie et réception de données sur le port RS 232
Une fois la liaison RS 232 toutes les fonctionnalités du programme sont accessibles. Pour cela il faut cependant pouvoir envoyer des ordres au microcontrôleur et récupérer ses réponses. Pour cela deux fonctions ont été créées même si on ne les utilise pas forcément dans la plupart des cas.
Ces deux fonctions ont des équivalents dans le one qui sont elles toujours utilisées pour l’envoi ou la réception d’un caractère.
Gestion des PWMs
Les PWM sont des signaux carrés paramétrables en période, pourcentage de temps haut, forme du signal et choix de l’horloge. Pour plus de renseignements se référer au chapitre 16 du la documentation du microcontrôleur.
Ces PWM peuvent être gérer depuis le menu « PWM » de l’IHM où l’utilisateur choisira alors les réglages qui lui conviennent avant de valider. Elles sont aussi utilisées par le capteur de champ magnétique mais sont dans ce cas là préréglées dans le programme.
En plus de régler les PWM ce menu nous permet aussi de les lancer en appuyant sur le bouton OFF qui passe alors à ON.
De son côté lors de la réception des paramètres le microcontrôleur va modifier ses registres.
Ces modifications s’appliquent de la même façon sur les autres voies donc nous ne le détaillons pas.
Puis lancer la génération si celle-ci est validée.
Conversion analogique numérique
Au nombre de 16 et possédant une résolution de 10 bits ces convertisseurs programmables en types d’échantillonnage et de conversion sont décris en détails chapitre 17 du manuel.
La conversion analogique numérique peut être lancée depuis le menu « Mesure » de l’IHM
De la même manière que précédemment l’utilisateur va pouvoir régler les différents paramètres qu’il désire utiliser dans l’interface puis valider son choix.
Le lancement et l’arrêt de la conversion sont ensuite possibles en cliquant sur l’un des deux boutons situés en dessous de la zone de paramétrage.
Gestion du capteur de champ magnétique
Le capteur que nous utilisons étant un capteur tridimensionnel il est en réalité constitué de 3 capteurs. Ces derniers communiquent en SPI avec le microcontrôleur et lors d’une mesure le capteur envoie 6 octets au microcontrôleur : 2 par direction. Le temps de conversion du capteur est fixé par l’horloge branchée sur son entrée CLK.
La liaison SPI du point de vue du capteur est détaillée dons son manuel d’utilisation et il en est de même pour le microcontrôleur dont le chapitre 12 du manuel s’attarde sur les communications SPI.
La mesure se fait à partir du même menu que la conversion A/N. Le bouton On/Off Capteur permet de générer l’horloge de conversion et lance la communication SPI.
Une fois le capteur lancé par l’activation de ce bouton le bouton « Lancement de la mesure » permet d’envoyer au microcontrôleur directement ou pas l’intermédiaire d’un timer l’ordre d’acquisition de mesures. On récupère ensuite les mesures dans les trois directions de l’espace et suivant le mode d’acquisition et les options : on moyenne ses valeurs, on les affiche, on indique la direction pointée par les capteurs sur la boussole et/ou on trace la norme du champ magnétique (pour ce dernier uniquement en mode permanent).
Les parties de code concernant Hy et Hz ont été supprimées pour économiser de l’espace car elles sont en tous points identiques à celles concernant Hx. Si l’option Boussole est cochée sur la face avant le programme utilisera aussi la fonction suivante :
On remarquera qu’une partie du code est exécuté 6 fois à la suite. Cette manière de codé ce passage hors d’une boucle est un choix délibéré car l’exécution de ce code dans une boucle n’est pas fonctionnelle pour une raison inconnue.
Si on est en mode permanent c’est le timer qui définira la durée entre 2 mesures. Cependant sachant que le temps de conversion avec l’horloge choisie est de 0.13s il ne faudra pas régler une valeur inférieure pour le timer. Par défaut le timer est de 0.19s.
Le code qui s’exécute est alors le même que précédemment on passe juste en plus dans la partie qui trace la norme.
Le bouton « arrêt de la mesure » permet de stopper l’acquisition du capteur et le timer si le mode permanent était enclenché.
Gestion du capteur de température et d’humidité
Pour ce capteur la communication n’est pas une liaison série normalisée. Cependant en générant avec le microcontrôleur une horloge et une ligne de données on pourra tout de même commander ce capteur et récupérer les mesures. La liste des commandes disponibles se trouve dans le manuel du capteur.
Une fonction à était spécialement créée pour généré le signal de début de transmission nécessaire avant tout message envoyé au capteur.
Ici seule la première boucle d’attente est représentée.
Une seconde fonction permet de réinitialiser la communication.
Enfin, le one comprend des fonctions d’envoi et de réception d’un octet vers le capteur. Le changement de la valeur du bit de donnée se fait sur front descendant de l’horloge.
Lors de l’envoi d’un octet au capteur, à la fin de la transmission, le capteur force la ligne Data à 0 pour accuser réception de l’octet. Le micro doit alors relâcher la ligne data et la mettre en entrée. Lorsque l’accusé de réception est bien reçu, le micro envoie un 9eme tick d’horloge.
Les instructions d’attente ne sont pas représentées à partir de ce point.
Lors de la réception d’un octet envoyé par le capteur, le micro récupère successivement chacun des 8 bits et les assemble. A la fin de la transmission, le micro doit mettre la ligne data à 0 pour accuser réception de l’octet, il génère ensuite un 9eme tick d’horloge pour signifier la fin de la transmission de l’octet.
La mesure de température et d’humidité se fait aussi à partir de la fenêtre Mesure. Elle comprend trois parties : l’initialisation du capteur, la mesure de température, et la mesure d’humidité.
Fonction s_softreset : cette fonction envoie la séquence de reset de la connexion, ainsi que la commande de reset du capteur.
La mesure de la température se fait en deux temps : l’envoi de la commande de mesure au capteur, et la récupération de la valeur mesurée. Pendant la mesure, l’horloge est à 0, et la ligne data est à 1. Il est nécessaire d’attendre que le capteur signale la fin de la mesure en mettant la ligne data à 0 avant de récupérer la valeur mesurée.
Le calcule de la température s’effectue en respectant les formules données page 9 de la notice du capteur.
La mesure du taux d’humidité suit les mêmes étapes que celle de la température :
Le calcul est encore une fois réalisé en respectant la formule donnée par le constructeur dans la documentation.
Enfin on peut lire et écrire le registre d’état du capteur à l’aide des fonctions suivantes :
Cette dernière callback permet de fermer le menu « Mesure » lors de l’appui sur le bouton quitter.
Annexe 2 : Transformation du code CVI en DLL
La méthode employée
Pour pouvoir transformer le plus facilement possible le code des callback CVI en DLL nous avons commencé par séparer ces fonctions du corps du programme CVI où se situent les callbacks.
Ensuite le plus gros du travail a donc été d’adapter chacune de ces fonctions séparées à une structure de fonction C. En effet dans la DLL il n’est plus possible d’utiliser les GetCtrlVal et SetCtrlVal qui nous permettent habituellement sous CVI d’échanger des informations avec notre face avant.
Après un certain temps de réflexion nous nous sommes dit que tout ce que l’on faisait avec des GetCtrlVal uniquement ressemblait à faire passer par valeur la variable à la fonction et que tout ce qui requérait l’usage d’un SetCtrlVal ressemblait à un passage par pointeur.
Pour le reste nous avons utilisé les capacités de CVI à créer un template de DLL et au final à la compiler.
Le résultat de ce travail : Une DLL
//==============================================================================
// Include files
#include
#include
#include
#include
#include
#include
#include "Projet_Multi_DLL_v2.h"
//************* FONCTIONS DE GESTION DE LA COMMUNICATION RS-232 **************
/* Permet de vérifier le bon fonctionnement de la communication Série et allume une Led de la face avant si la connection et bonne */
int Demarrage_RS_232(int com, int* avancement)
{
int i=0;
int ret = 0;
int erreurcom = 0;
*avancement = 5 ; //progression
erreurcom = OpenComConfig (com, "", 9600, 0, 8, 1, 512, 512); // ouverture du port serie
if( erreurcom!=0)
{
MessagePopup ("Boot", "Port non initialisé : Relancez le programme ");
return -1;
}
else SetComTime (com, 5);
*avancement = 10 ;
ComWrtByte (com,0x32 ); // envoi de 0x32 pour dialogue avec le c167
*avancement = 12 ;
ret=ComRdByte (com); // retour d'info c167 0x55
if(ret!=0x55)
{
MessagePopup ("Boot", "Pas de communication");
MessagePopup ("Boot", "Verifier l'alimentation du microcontroleur et relancez le programme");
return -2;
}
else
{
for(i=0;i<9;i++)
{
*avancement = 12+i ;
}
Delay(1);
}
return 0;
}
/* Ferme le port de communication RS 232 */
void Stop_RS_232(int com)
{
CloseCom (com);
}
//*************** FONCTIONS DE GESTION DE LA MESURE DE CHAMP MAGNETIQUE ************
/* Realise une mesure de champ magnetique mettre mode à 0 si monocoup ou 1 si permanent */
void Mesure_Champ(int com, int mode, int moyennage, double* Hx, double* Hy, double* Hz, double* Module)
{
int H1,H2,H;
int i=0;
double Hcalc = 0;
double norme = 0;
double *Hx2, *Hy2, *Hz2;
Hx2=malloc(moyennage*sizeof(double));
Hy2=malloc(moyennage*sizeof(double));
Hz2=malloc(moyennage*sizeof(double));
for(i=0;i
{
ComWrtByte (com, 0x63); // mesure de champ magnetique
Delay(0.140); // plop
H1=ComRdByte (com) & 0x0FF; //MSB
Delay(0.010); //plop
H2=ComRdByte (com) & 0x0FF; //LSB
H=(H1<<8)+H2;
if (H<0x8000)
{
Hcalc=H*0.33;
}
else
{
Hcalc=((H-0xFFFF)-1) *0.33;
}
Hx2[i]=Hcalc;
Delay(0.010); // plop
H1=ComRdByte (com) & 0x0FF; //MSB
Delay(0.010); //plop
H2=ComRdByte (com) & 0x0FF; //LSB
H=(H1<<8)+H2;
if (H<0x8000)
{
Hcalc=H*0.33;
}
else
{
Hcalc=((H-0xFFFF)-1) *0.33;
}
Hy2[i]=Hcalc;
Delay(0.010); // plop
H1=ComRdByte (com)& 0x0FF;
Delay(0.010); //plop
H2=ComRdByte (com)& 0x0FF; //LSB
H=(H1<<8)+H2;
if (H<0x8000)
{
Hcalc=H*0.33;
}
else
{
Hcalc=((H-0xFFFF)-1) *0.33;
}
Hz2[i]=Hcalc;
}
Mean(Hx2, moyennage, Hx);
Mean(Hy2, moyennage, Hy);
Mean(Hz2, moyennage, Hz);
*Module=0;
if (mode==1)
{
norme=sqrt((*Hx)*(*Hx)+(*Hy)*(*Hy)+(*Hz)*(*Hz)); // calcul de la norme du champ magnetique
*Module=norme;
}
}
/* Arrete la mesure du champ */
void Arret_Mesure_Champ(int com)
{
ComWrtByte (com, 0x66);
}
/* Demarre le capteur de champ */
void Demarrage_Capteur(int com, int ancienne_valeur, double* Hx, double* Hy, double* Hz)
{
if(ancienne_valeur)
{
ComWrtByte (com,0x64); //etat OFF dans One
*Hx=0;
*Hy=0;
*Hz=0;
}
else
{
ComWrtByte (com, 0x65); // etat ON dans One
}
}
//**************** MESURE TEMPERATURE ET HUMIDITE *********************************
/* Initialise les capteurs */
void Init_Capteur(int com, int* erreur)
{
// initialisation capteur
ComWrtByte (com, 0x68); // softreset (remise a 0 de la variable d'erreur)
*erreur= ComRdByte(com);
if( *erreur!=0)
{
MessagePopup ("mesure", "erreur lors du softreset!");
}
}
/* Realise une mesure de température */
double Mesure_Temp(int com, int* erreur)
{
double temp = 0, temp1 = 0, temp2 = 0;
ComWrtByte (com, 0x69); // envoi de la commande
*erreur = ComRdByte(com);
if( *erreur!=0)
{
MessagePopup ("mesure", "erreur lors de la mesure de temperature!");
}
ComWrtByte (com, 0x79); // lecture de la mesure
temp = ComRdByte(com); //MSB
temp= temp*256;
temp1= ComRdByte(com); //LSB
temp=temp+temp1;
temp2= -40.1 + 0.01 * temp;// valable pour une mesure en degré C au format 14 bits et pour VDD=5V (cf table 8 datasheet SHT1x page9)
return temp2;
}
/* Realise une mesure d'humidité */
double Mesure_Humi(int com, int* erreur)
{
double hum = 0, hum1 = 0, hum2 = 0;
ComWrtByte (com, 0x70); // envoi de la commande
*erreur = ComRdByte(com);
if( *erreur!=0)
{
MessagePopup ("mesure", "erreur lors de la mesure d'humidité!");
}
ComWrtByte (com, 0x73); // lecture de la mesure
hum = ComRdByte(com); //MSB
hum=hum*256;
hum2= ComRdByte(com);//LSB
hum=hum+hum2;
hum1 = -2.0468 + (0.0367*hum) - (1.5955*0.000001*hum*hum); // valable pour une mesure sur 12 bits (cf table 6 datasheet SHT1x page8)
return hum1;
}
/* Lecture du registre de statut */
void Lecture_Statut(int com, int* erreur)
{
int valstatut = 0;
ComWrtByte (com, 0x71); //commande de lecture du registre de statut
valstatut = ComRdByte(com);
ComRdByte(com);
*erreur = ComRdByte(com);
if( *erreur!=0)
{
MessagePopup ("lecture du registre", "erreur!");
}
*erreur = 0;
}
/* Gestion complète de la mesure de temperature et d'humidite */
void Mesure_Temp_Humi(int com, int* erreur, double* temp, double* humi)
{
Init_Capteur(com, erreur);
*temp = Mesure_Temp(com, erreur);
*humi = Mesure_Humi(com, erreur);
Lecture_Statut(com, erreur);
}
//==============================================================================
// DLL main entry-point functions
int __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
if (InitCVIRTE (hinstDLL, 0, 0) == 0)
return 0; /* out of memory */
break;
case DLL_PROCESS_DETACH:
CloseCVIRTE ();
break;
}
return 1;
}
int __stdcall DllEntryPoint (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
/* Included for compatibility with Borland */
return DllMain (hinstDLL, fdwReason, lpvReserved);
}
Dostları ilə paylaş: |