====== TP6 - Exercice ====== ===== Organigramme ===== {{:fr:supervisors:solutions:wiper:organigramme_solution_tp6.png?600|}} ===== Programme ===== /*************************************************************************************** * TPs sur EID210 / Réseau CAN - VMD (Véhicule Multiplexé Didactique) **************************************************************************************** * APPLICATION: Commande Essuie-glace à distance **************************************************************************************** * TP Exercice n°3: Commande du système essuie glace avant *--------------------------------------------------------------------------------------- * CAHIER DES CHARGES : * ********************* * On souhaite une commande normale de l'essuie glace à partir du commodo destiné * à cet effet: * - position 'arrêt' (noté P0) (ni P1, ni P2,ni P3) * - position P1 (GP4) 'intermittant' -> le balai fait des "aller-retours" séparés par * une attente dont la durée est réglée par l'entrée analogique AN0 * - position P2 (GP5) -> le balai fait des "aller-retours" avec une vitesse faible * - position P3 (GP6) -> le balai fait des "aller-retours" avec une vitesse moyenne * - position P4 (GP7) -> le balai fait des "aller-retours" avec une vitesse élevée * Dans le mode 'intermittent', l'intervalle de temps entre deux battements est générée * par le 'temporisateur programmable intégré dans le micro-controleur * On affichera à l'écran, les états des diverses entrées commodo. *--------------------------------------------------------------------------------------- * NOM du FICHIER : TP_Exercice 3.C * ***************** *****************************************************************************************/ // Déclaration des fichiers d'inclusion #include #include"Structures_Donnees.h" #include"cpu_reg.h" #include "eid210_reg.h" #include "CAN_vmd.h" #include "Aton_can.h" // Déclaration des variables // Pour les Indicateurs divers (variables binaires) union byte_bits Indicateurs,FC; // Structures de bits #define I_Autorise_Cycle Indicateurs.bit.b0 // Pour autoriser 1 battement #define I_Intermittent Indicateurs.bit.b1 #define I_Message_Pb_Affiche Indicateurs.bit.b2 #define Etat_Arret Indicateurs.bit.b3 // Etat "balai à l'arrêt en fin de course droite" #define Etat_Rot_Droite Indicateurs.bit.b4 // Etat "balai en rotation droite" #define Etat_Rot_Gauche Indicateurs.bit.b5 // Etat "balai en rotation gauche" // Pour les fins de course #define Etat_FC FC.valeur // Pour l'ensemble des fins de course #define fs FC.bit.b7 // Pour fin de surcourse #define fcg FC.bit.b6 // Pour fin de course gauche #define fcd FC.bit.b5 // Pour fin de course droit // Pour la position Commodo_EG #define Commodo_EG_Pos1 Commodo_EG.bit.GP4 #define Commodo_EG_Pos2 Commodo_EG.bit.GP5 #define Commodo_EG_Pos3 Commodo_EG.bit.GP6 #define Commodo_EG_Pos4 Commodo_EG.bit.GP7 // Déclarations des diverses trames de communication Trame Trame_Recue; // Pour la trame qui vient d'etre reçue par le controleur // Trames de type "IM" (Input Message -> trame de commande) Trame T_IM_Asservissement; // Pour la commande du moteur Trame T_IM_Commodo_EG; // Pour l'initialisation Commodo Essuie Glace // Trames de type "IRM" (Input Message -> trame interrogative) Trame T_IRM_Acquisition_FC; // Pour l'acquisition de l'état des fins de courses Trame T_IRM_Etat_Commodo_EG; // Pour l'acquisition de l'état Commodo Essuie Glace // Varibles diverses unsigned char Valeur_Analogique,Cde_Vitesse,Tempo_Fin,Compteur_Passage_Irq,Compteur_Secondes; unsigned char Valeur_Commodo_EG_Mem,Valeur_Analogique_Mem; // Pour les temporisation // Déclaration constantes #define Vitesse_Lente 30 #define Vitesse_Moyenne 50 #define Vitesse_Rapide 70 #define Tempo1 3 // en secondes #define Tempo2 6 #define Tempo3 9 #define Tempo4 12 #define Tempo5 15 // Fonction d'interruption "Base de Temps" //======================================== void irq_bt() // Fonction exécutée toute les 10 mS {if(I_Intermittent) // Si mode intermittent actif {Compteur_Passage_Irq++; if(Compteur_Passage_Irq==100) // Une Seconde s'est écoulée {Compteur_Passage_Irq=0; Compteur_Secondes++; if(Compteur_Secondes>=Tempo_Fin) {Compteur_Secondes=0; I_Autorise_Cycle=1;} }} } // Fin de la fonction d'interruption //====================== // FONCTION PRINCIPALE //====================== main() { // Déclaration de variables locales à la fonction principale int Cptr_Affichage=0,Cptr_TimeOut; // INITIALISATIONS //------------------ // Pour initialiser la carte industrielle controleur CAN Init_Aton_CAN(); clsscr(); // Pour effacer l'écran // Trame de type "IM" (trame de commande): Données d'identification T_IM_Asservissement.trame_info.registre=0x00; T_IM_Asservissement.trame_info.champ.extend=1; T_IM_Asservissement.trame_info.champ.dlc=0x03; T_IM_Asservissement.trame_info.champ.rtr=0; T_IM_Asservissement.ident.extend.identificateur.ident=Ident_T_IM_Asservissement; // Pour définir des Entrées/Sorties T_IM_Asservissement.data[0]=0x1F; // Adresse du registre GPDDR (direction de E/S) // doc MCP25050 Page 16 T_IM_Asservissement.data[1]=0xEF; // Masque -> Bit 7 non concerné T_IM_Asservissement.data[2]=0xE3; // Valeur -> 1 si Entrée et 0 si Sortie // GP7=fs Entrée; GP6=fcg Entree; GP5=fcd Entrée; GP4=ValidIP Sortie; // GP3=PWM2 Sortie; GP2=PWM1 Sortie; GP1=AN1 Entrée; GP0=AN0 Entrée; I_Message_Pb_Affiche=0; do {Ecrire_Trame(T_IM_Asservissement); // C'est la première trame envoyée au module Cptr_TimeOut=0; // 'Asservissement' -> on teste s'il répond bien do{Cptr_TimeOut++;}while((Lire_Trame(&Trame_Recue)==0)&&(Cptr_TimeOut<100)); if(Cptr_TimeOut==100) {if(I_Message_Pb_Affiche==0) {I_Message_Pb_Affiche=1; gotoxy(2,10); printf(" Pas de reponse a la trame de commande en initialisation \n"); printf(" Verifier si alimentation 12 V est OK \n");}} }while(Cptr_TimeOut==100); clsscr(); // Pour effacer l'écran au cas ou message afiché // Pour mettre à 0 les sorties T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x1C; // Masque -> sorties GP4,3,2 sont consernées T_IM_Asservissement.data[2]=0x00; // Valeur -> les 3 sorties à 0 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour définir sortie GP2 en PWM1 T_IM_Asservissement.data[0]=0x21; // Adresse du registre T1CON T_IM_Asservissement.data[1]=0xB3; // Masque -> seuls bit 7;5;4;1;0 consernés T_IM_Asservissement.data[2]=0x80; // Valeur -> TMR1ON=1; Prescaler1=1 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour définir fréquence signal sortie PWM1 T_IM_Asservissement.data[0]=0x23; // Adresse du registre PR1 T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=0xFF; // Valeur -> PR1=255 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour définir sortie GP3 en PWM2 T_IM_Asservissement.data[0]=0x22; // Adresse du registre T2CON T_IM_Asservissement.data[1]=0xB3; // Masque -> seuls bit 7;5;4;1;0 consernés T_IM_Asservissement.data[2]=0x80; // Valeur -> TMR2ON=1; Prescaler2=1 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour définir fréquence signal sortie PWM2 T_IM_Asservissement.data[0]=0x24; // Adresse du registre PR2 T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=0xFF; // Valeur -> PR2=255 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour initialiser le rapport cyclique du signal PWM1 T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=0; // Valeur -> PWM1DC=0 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour initialiser le rapport cyclique du signal PWM2 à 0 T_IM_Asservissement.data[0]=0x26; // Adresse du registre PWM2DC T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés T_IM_Asservissement.data[2]=0; // Valeur -> PWM2DC=0 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour Valider le circuit de puissance T_IM_Asservissement.data[0]=0x1E; // Adresse du registre GPLAT (Registre I/O) T_IM_Asservissement.data[1]=0x10; // Masque -> sortie GP4 (ValidIP) est conserné T_IM_Asservissement.data[2]=0x10; // Valeur -> ValidIP=1 Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Masque pour les commandes IM futures T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés // Pour acquérir l'état des fin de course // Trame de type "IRM" (trame interrogative): Données d'identification T_IRM_Acquisition_FC.trame_info.registre=0x00; T_IRM_Acquisition_FC.trame_info.champ.extend=1; T_IRM_Acquisition_FC.trame_info.champ.dlc=1; T_IRM_Acquisition_FC.trame_info.champ.rtr=1; T_IRM_Acquisition_FC.ident.extend.identificateur.ident=Ident_T_IRM1_Asservissement; // Demande état registre GPIN // Pour initialiser le module "commmodo EG" // Trame de type "IM" (trame de commande): Données d'identification T_IM_Commodo_EG.trame_info.registre=0x00; T_IM_Commodo_EG.trame_info.champ.extend=1; T_IM_Commodo_EG.trame_info.champ.dlc=0x03; // On demande les valeurs de 8 rgistres T_IM_Commodo_EG.trame_info.champ.rtr=0; T_IM_Commodo_EG.ident.extend.identificateur.ident=Ident_T_IM_Commodo_EG; // // Pour activer les conversions Ana -> Num T_IM_Commodo_EG.data[0]=0x2A; // Adresse du registre ADCON0 T_IM_Commodo_EG.data[1]=0xF0; // Masque -> bits 7..4 concernés T_IM_Commodo_EG.data[2]=0x80; // Valeur -> ADON=1 et "prescaler rate"=1:32 Ecrire_Trame(T_IM_Commodo_EG); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour définir le mode de conversion T_IM_Commodo_EG.data[0]=0x2B; // Adresse du registre ADCON1 T_IM_Commodo_EG.data[1]=0xFF; // Masque -> tous les bits sont concernés T_IM_Commodo_EG.data[2]=0x0E; // Valeur -> voir doc MCP25050 page 36 (GP0 -> Entrée Analogique) Ecrire_Trame(T_IM_Commodo_EG); do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse // Pour acquérir les résultats de conversion A->N et états commmodo EG // Trame de type "IRM" (trame interrogative) Commodo EG: Données d'identification T_IRM_Etat_Commodo_EG.trame_info.registre=0x00; T_IRM_Etat_Commodo_EG.trame_info.champ.extend=1; T_IRM_Etat_Commodo_EG.trame_info.champ.dlc=0x08; // On demande les valeurs de 8 rgistres T_IRM_Etat_Commodo_EG.trame_info.champ.rtr=1; T_IRM_Etat_Commodo_EG.ident.extend.identificateur.ident=Ident_T_IRM8_Commodo_EG; // // Pour initialiser système (Enmener le balai en position sur fin de course droit) T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC T_IM_Asservissement.data[1]=0xFF; // Masque -> tous les bits sont consernés Ecrire_Trame(T_IRM_Acquisition_FC); // Envoi trame d'acquisition de l'état des fins de course do{}while(Lire_Trame(&Trame_Recue)==0); //On attend la réponse Etat_FC=~Trame_Recue.data[0]; // On récupére l'état des fin de course if(fcd==0) //SI le balai EG n'est pas en position droit, on commande une rotation à droite {T_IM_Asservissement.data[2]=Vitesse_Lente; // Valeur -> Pour vitesse lente Ecrire_Trame(T_IM_Asservissement); // Envoi trame de commande moteur do{}while(Lire_Trame(&Trame_Recue)==0); //On attend la réponse while(fcd==0) {Ecrire_Trame(T_IRM_Acquisition_FC); // Envoi trame d'acquisition états fins de course do{}while(Lire_Trame(&Trame_Recue)==0); //On attend la réponse Etat_FC=~Trame_Recue.data[0]; // On récupére l'état des fin de course } } T_IM_Asservissement.data[2]=0; // Valeur -> Pour vitesse nulle Ecrire_Trame(T_IM_Asservissement); do{}while(Lire_Trame(&Trame_Recue)==0); //On attend la réponse // Initialisation des variables d'état système Etat_Arret=1,Etat_Rot_Droite=0,Etat_Rot_Gauche=0; I_Autorise_Cycle=0,I_Intermittent=0; Compteur_Secondes=0,Compteur_Passage_Irq=0; // Pour afficher titre du TP gotoxy(1,2); printf("***********************\n"); printf(" TPs sur Reseau CAN\n"); printf(" Commande Essui-Glace\n"); printf(" A distance\n"); printf(" -----------------------\n"); printf(" TP Exercice 3:\n"); printf(" Commande systeme ESSUI GLACE\n"); printf("******************************\n"); // Pour initialiser la base de temps et temporisations SetVect(96,&irq_bt); // mise en place de l'autovecteur PITR = 0x0048; // Une interruption toutes les 10 millisecondes PICR = 0x0760; // 96 = 60H // BOUCLE PRINCIPALE //******************* while(1) { // Acquérir l'état des fins de courses //------------------------------------- Ecrire_Trame(T_IRM_Acquisition_FC); // Envoi trame d'acquisition des états fin de course Cptr_TimeOut=0; do{Cptr_TimeOut++;}while((Lire_Trame(&Trame_Recue)==0)&&(Cptr_TimeOut<10000)); if(Cptr_TimeOut==10000) {clsscr(),gotoxy(2,10); printf(" Pas de reponse a la trame interrogative pour fins de courses \n"); printf(" Il faut recharger et relancer le programme \n"); do{}while(1);} // Stop else { if(Trame_Recue.ident.extend.identificateur.ident==Ident_T_IRM1_Asservissement) // On teste si l'identificateur est correct {Etat_FC=~Trame_Recue.data[0];}} // On récupére l'état des fin de course // Acquérir l'état Commodo Essuie Glace //-------------------------------------- Ecrire_Trame(T_IRM_Etat_Commodo_EG); // Envoi trame d'acquisition des états fin de course Cptr_TimeOut=0; do{Cptr_TimeOut++;}while((Lire_Trame(&Trame_Recue)==0)&&(Cptr_TimeOut<10000)); if(Cptr_TimeOut==10000) {clsscr(),gotoxy(2,10); printf(" Pas de reponse a la trame interrogative pour fins de courses \n"); printf(" Il faut recharger et relancer le programme \n"); do{}while(1);} // Stop else { if(Trame_Recue.ident.extend.identificateur.ident==Ident_T_IRM8_Commodo_EG) // On teste si l'identificateur est correct {Valeur_Commodo_EG=~(Trame_Recue.data[1]&0xF0); // On récupére l'état commodo EG Valeur_Analogique=Trame_Recue.data[2];}} // On récupére l'état molette EG // Traiter l'état Commodo Essuie Glace //------------------------------------- if(Valeur_Commodo_EG!=Valeur_Commodo_EG_Mem) // Si changement sur entrées binaires {if(Commodo_EG_Pos4){I_Autorise_Cycle=1,I_Intermittent=0,Cde_Vitesse=Vitesse_Rapide;} // (on autorise les cycles du balai, avec une vitesse rapide, si on est en position 4 sur le commodo) else {if(Commodo_EG_Pos3){I_Autorise_Cycle=1,I_Intermittent=0,Cde_Vitesse=Vitesse_Moyenne;} // (on autorise les cycles du balai, avec une vitesse rapide, si on est en position 3 sur le commodo) else {if(Commodo_EG_Pos2){I_Autorise_Cycle=1,I_Intermittent=0,Cde_Vitesse=Vitesse_Lente;} // on autorise les cycles du balai, avec une vitesse lente, si on est en position 2 sur le commodo) else {if(Commodo_EG_Pos1) {I_Intermittent=1,Cde_Vitesse=Vitesse_Lente; // Position "Intermittent" Compteur_Passage_Irq=0; Compteur_Secondes=0; } else {I_Intermittent=0; // Position "Arret" }}}} printf("Bh %x\n",Valeur_Commodo_EG); }// Fin si changement etat entrées binaires if(Valeur_Analogique!=Valeur_Analogique_Mem) {printf("Ad %d\n",Valeur_Analogique); if(Valeur_Analogique>=200)Tempo_Fin=Tempo5; // Selon la position de la molette else {if(Valeur_Analogique>=150)Tempo_Fin=Tempo4; // la tempo plus ou moins longue else {if(Valeur_Analogique>=100)Tempo_Fin=Tempo3; else {if(Valeur_Analogique>=50)Tempo_Fin=Tempo2; else {if(Valeur_Analogique>=1)Tempo_Fin=Tempo1;}}}} } // Mise à jour des grandeurs mémorisées Valeur_Analogique_Mem=Valeur_Analogique; Valeur_Commodo_EG_Mem=Valeur_Commodo_EG; // Traitement du diagramme des états "système" //-------------------------------------------- if(Etat_Arret) // Si le système est dans l'état "Arret" {if(I_Autorise_Cycle) // Si on un cycle a été autorisé {I_Autorise_Cycle=0; Etat_Arret=0,Etat_Rot_Gauche=1; // Evolution etat système T_IM_Asservissement.data[2]=Cde_Vitesse; // On commande la rotation à gauche T_IM_Asservissement.data[0]=0x26; // Adresse du registre PWM2DC Ecrire_Trame(T_IM_Asservissement); while(Lire_Trame(&Trame_Recue)==0){}; // On attend la réponse //if(I_Intermittent)Compteur_Secondes=0,Compteur_Passage_Irq=0; }} if(Etat_Rot_Gauche) // Si le système est dans l'état "Rotation à Gauche" {if(fcg) // Si on est arrivé en fin de course gauche {Etat_Rot_Gauche=0,Etat_Rot_Droite=1; // Evolution etat système T_IM_Asservissement.data[2]=0; // On arrête la rotation à gauche T_IM_Asservissement.data[0]=0x26; // Adresse du registre PWM2DC Ecrire_Trame(T_IM_Asservissement); while(Lire_Trame(&Trame_Recue)==0){}; // On attend la réponse T_IM_Asservissement.data[2]=Cde_Vitesse; // On commande la rotation gauche T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC Ecrire_Trame(T_IM_Asservissement); while(Lire_Trame(&Trame_Recue)==0){}; // On attend la réponse }} if(Etat_Rot_Droite) // Si le système est dans l'état "Rotation à droite" {if(fcd) // Si on est arrivé en fin de course droit {if(Commodo_EG_Pos2|Commodo_EG_Pos3|Commodo_EG_Pos4) {Etat_Rot_Droite=0,Etat_Rot_Gauche=1; // Evolution etat système T_IM_Asservissement.data[2]=0; // On arrête la rotation à droite T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC Ecrire_Trame(T_IM_Asservissement); while(Lire_Trame(&Trame_Recue)==0){}; // On attend la réponse T_IM_Asservissement.data[2]=Cde_Vitesse; // On commande la rotation à gauche T_IM_Asservissement.data[0]=0x26; // Adresse du registre PWM2DC Ecrire_Trame(T_IM_Asservissement); while(Lire_Trame(&Trame_Recue)==0){}; // On attend la réponse } else {Etat_Rot_Droite=0,Etat_Arret=1; // Evolution etat système T_IM_Asservissement.data[2]=0; // On arrête la rotation à droite T_IM_Asservissement.data[0]=0x25; // Adresse du registre PWM1DC Ecrire_Trame(T_IM_Asservissement); while(Lire_Trame(&Trame_Recue)==0){}; // On attend la réponse if(I_Intermittent)Compteur_Passage_Irq=0,Compteur_Secondes=0; }}} // Afficher l'état système //------------------------- /* Cptr_Affichage++; if(Cptr_Affichage==200) {Cptr_Affichage=0; gotoxy(1,6); if(I_Intermittent)printf(" Essuie glace avant en intermittent \n"); else {if(Commodo_EG_Pos2)printf(" Essuie glace avant en vitesse lente \n"); else {if(Commodo_EG_Pos3)printf(" Essuie glace avant en vitesse rapide \n"); else {printf(" Essuie glace avant à l'arret \n");}}} printf(" Commande lave glace avant: %d\n",Cde_Lave_Glace_Av); gotoxy(1,10); printf(" Commande essuie glace arriere: %d\n",Cde_EG_Ar); printf(" Commande lave glace arriere: %d\n",Cde_Lave_Glace_Ar); } // Fin "Afficher l'état" */ } // Fin boucle principale } // Fin fonction principale