Table of Contents

Exercice 2 (TP5)

Organigramme

Programme

	/************************************************************************************************
	*       TPs sur  EID210 / Réseau CAN - VMD  (Véhicule Multiplexé Didactique)			
	*************************************************************************************************
	*       APPLICATION: Commande Essuie-glace à distance
	*************************************************************************************************
	*   TP Exercice n°2:  Réguler la vitesse du moteur essuie-glace avec correcteur P
	*-----------------------------------------------------------------------------------------------  		
 
	*   CAHIER DES CHARGES :					      				
	*  *********************						      			
	*      Réguler la vitesse du moteur EG avec pour consigne, l'entrée analogique du commodo E.G.
	* 		La commande du moteur se fait boucle fermé avec correcteur à action proportionnelle 
	*		     Commande = Kp*Ecart = Kp * (Consigne - Mesure)
	*------------------------------------------------------------------------------------------------
	*  NOM du FICHIER :  TP_Exercice 2.C			       				
	* ***************** 									
	*************************************************************************************************/
 
// Déclaration des fichiers d'inclusion
#include <stdio.h>
#include"Structures_Donnees.h"
#include"cpu_reg.h"
#include "eid210_reg.h"
#include "CAN_vmd.h"
#include "Aton_can.h"
 
// Déclarations des diverses trames de communication
Trame Trame_Recue;	// Pour la trame qui vient d'etre reçue par le controleur
// Trmes de type "IM" (Input Message -> trame de commande)
Trame T_IM_Asservissement; 	// Pour la commande du moteur
Trame T_IM_Commodo_EG;
Trame T_IRM_Commodo_EG;	// Pour l'acquisition des entrées Commodo EG
// Déclaration des variables 
// Pour les Indicateurs divers (variables binaires)
union byte_bits Indicateurs; // Structures de bits
#define I_Sens_Rotation Indicateurs.bit.b0 
#define I_Attente_Reponse_IRM Indicateurs.bit.b1 
#define I_Message_Pb_Affiche Indicateurs.bit.b2 
// Pour les résultats de conversion
unsigned short S_Mesure_Vitesse,S_Consigne,S_Temp;
unsigned char AN0H,AN1H,AN10L;
// Pour régulateur de vitesse
int Ecart,Resultat_Calcul;
unsigned char Cde_Moteur;
// Déclaration constante pour régulation
#define Kp 6	// Coefficient d'action proportionnelle -> Ce doit etre un entier
			//en fait valeur réelle Kp/16 = 6/16
 
//======================
// FONCTION PRINCIPALE
//======================
main()
{
//  INITIALISATIONS
//------------------
// Déclaration de variables locales à la fonction principale
// Les différents compteurs
unsigned int Cptr_Affichage,Cptr_TimeOut,Ctpr_Acquisition;
// Initilisation carte controleur réseau CAN
Init_Aton_CAN();
// Effacer l'écran
clsscr();
// Pour initialiser les liaison en entrées du noeud "Commodo Essuie-Glace"
T_IM_Commodo_EG.trame_info.registre=0x00;
T_IM_Commodo_EG.trame_info.champ.extend=1; // On travaille en mode étendu
T_IM_Commodo_EG.trame_info.champ.dlc=0x03; // Il y aura 3 données de 8 bits (3 octets envoyés)
T_IM_Commodo_EG.ident.extend.identificateur.ident=Ident_T_IM_Commodo_EG;
T_IM_Commodo_EG.data[0]=0x1F;	// première donnée -> "Adresse" du registre concernée 
						//(GPDDR donne la direction des I/O) adresse = 1Fh  page 16
T_IM_Commodo_EG.data[1]=0x7F; // deuxième donnée -> "Masque" 
					  //-> Tous les bits concernés sauf GP0 (voir doc page 16)
T_IM_Commodo_EG.data[2]=0x7F;	// Valeur ->  1 si Entrée et 0 si Sortie  (Toutes en entrées)
 
// Pour envoyer trame et test si réponse  (avec Time Out
I_Message_Pb_Affiche=0;
do {Ecrire_Trame(T_IM_Commodo_EG); 	// C'est la première trame envoyée
	 Cptr_TimeOut=0;				// On teste si le module répond bien			
	 do{Cptr_TimeOut++;}while((Lire_Trame(&Trame_Recue)==0)&&(Cptr_TimeOut<500));
	 if(Cptr_TimeOut==500)
		{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   ...  PUIS    \n");
			 printf("  FAIRE un Reset de la carte processeur EID 210  ...  PUIS  \n");
			 printf("  RECHARGER le programme et RELANCER \n");
			 do{}while(1);}}
    }while(Cptr_TimeOut==500);
// La première tramme est bien passée ... on peut continuer!
clsscr();
// Pour afficher titre
gotoxy(1,2);
printf("    ********************************************************************  \n");
printf("     TPs sur Reseau CAN    Application: Commande Essui-Glace              \n");
printf("    --------------------------------------------------------------------  \n");
printf("     TP Exercice  n°2:     REGULER LA VITESSE DU MOTEUR Essuie-Glace      \n");
printf("    ********************************************************************  \n");
printf("      - en agissant sur l'entree analogique 0 sur module Commodo_EG      \n");
printf("      - en boucle fermee en mode proportionnel Sr = Kp(Consigne -Mesure) \n");
printf("    ******************************************************************** \n");
 
 
// 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]=0x0C;	// Valeur ->  voir doc MCP25050 page 36
Ecrire_Trame(T_IM_Commodo_EG);
do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
// Trame de type "IRM" (trame interrogative): Données d'identification du commodo EG
T_IRM_Commodo_EG.trame_info.registre=0x00;
T_IRM_Commodo_EG.trame_info.champ.extend=1;
T_IRM_Commodo_EG.trame_info.champ.dlc=0x08; // On demande les valeurs de 8 rgistres
T_IRM_Commodo_EG.trame_info.champ.rtr=1;
T_IRM_Commodo_EG.ident.extend.identificateur.ident=Ident_T_IRM8_Commodo_EG; //
 
// Initialisation des différentes trames et envoi aux modules "Asservissement"
// 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; 
Ecrire_Trame(T_IM_Asservissement);
do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
// 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 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 ->  
Ecrire_Trame(T_IM_Asservissement);
do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
// Pour initialiser le rapport cyclique  (valeur initiale)
T_IM_Asservissement.data[0]=0x25; 	// Adresse du registre PWM1DC (Charger cde vitesse)
T_IM_Asservissement.data[1]=0xFF; 	// Masque -> tous les bits sont concernés
T_IM_Asservissement.data[2]=0;	// Valeur ->  Commande vitesse à 0
Ecrire_Trame(T_IM_Asservissement);
do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
// Pour activer les conversions Ana -> Num
T_IM_Asservissement.data[0]=0x2A; 	// Adresse du registre ADCON0  
T_IM_Asservissement.data[1]=0xF0; 	// Masque -> bits 7..4 concernés
T_IM_Asservissement.data[2]=0x80;	// Valeur ->  ADON=1 et "prescaler rate"=1:32
Ecrire_Trame(T_IM_Asservissement);
do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
// Pour définir le mode de conversion
T_IM_Asservissement.data[0]=0x2B; 	// Adresse du registre ADCON1  
T_IM_Asservissement.data[1]=0xFF; 	// Masque -> tous les bits sont concernés
T_IM_Asservissement.data[2]=0x0C;	// Valeur ->  voir doc MCP25050 page 36
Ecrire_Trame(T_IM_Asservissement);
do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
// Pour valider le séquenceur
T_IM_Asservissement.data[0]=0x2C; 	// Adresse du registre STON  
T_IM_Asservissement.data[1]=0xFF; 	// Masque -> tous les bits sont concernés
T_IM_Asservissement.data[2]=0xD2;	// Valeur ->  voir doc MCP25050 page 24
Ecrire_Trame(T_IM_Asservissement);
do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
// Pour valider le séquencement sur entrées analogiques 0 et 1
T_IM_Asservissement.data[0]=0x2C; 	// Adresse du registre STON  
T_IM_Asservissement.data[1]=0x03; 	// Masque -> tous les bits sont concernés
T_IM_Asservissement.data[2]=0x03;	// Valeur ->  voir doc MCP25050 page 24
Ecrire_Trame(T_IM_Asservissement);
do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
Cptr_Affichage=0;
Ctpr_Acquisition=0;
Cptr_TimeOut=0;
// BOUCLE PRINCIPALE
//*******************
while(1)
	{// Un trame donnant les états est recue à intervalles de temps réguliers
	 // Fonction 'Scéduleur' du module 'Asservissement' est activée
	if(Lire_Trame(&Trame_Recue)!=1) // Un trame résultat n'est pas arrivée ?
	 	{Cptr_TimeOut++;
	 	 if(Cptr_TimeOut==10000)
			{clsscr(),gotoxy(2,10);
		 	 printf(" Pas de trame resultats de conversion depuis trop longtemps\n");
		 	 printf("  Il faut recharger et relancer le programme \n");
		 	 do{}while(1);}} // Stop 
	 else {Cptr_TimeOut=0;
		 if(Trame_Recue.ident.extend.identificateur.ident==Ident_T_OB_Asservissement)
			// On teste si l'identificateur est correct
			{AN1H =Trame_Recue.data[3]; 	// On récupére les MSB de la mesure vitesse
			 AN10L =Trame_Recue.data[4]; // On récupére les LSB AN1 et AN0
	 	 	 // Traiter les données et reconstituer les résultats
			 S_Mesure_Vitesse=(unsigned short)(AN1H);	//Transfert avec transtypage
			 S_Mesure_Vitesse=S_Mesure_Vitesse<<2;	// Décaler de 2 bits vers poids forts
			 S_Temp=(unsigned short)(AN10L&0xC0); // Pour ne récupérer que les 2 bits AD1 et AD0
			 S_Mesure_Vitesse=S_Mesure_Vitesse|(S_Temp>>6);
			 // Calculer la grandeur de commande
			 Ecart = S_Consigne - S_Mesure_Vitesse;
			 Resultat_Calcul = (Kp*Ecart)>>4;
		    	 if(Resultat_Calcul>255)Resultat_Calcul=255;
			 if(Resultat_Calcul<0)Resultat_Calcul=0;
		 	 Cde_Moteur=(unsigned char)(Resultat_Calcul);	
			 T_IM_Asservissement.data[0]=0x25; 	// Adresse du registre PWM1DC (Charger cde vitesse)
			 T_IM_Asservissement.data[1]=0xFF; 	// Masque -> tous les bits sont concernés
			 T_IM_Asservissement.data[2]=Cde_Moteur;	// Valeur ->  Commande vitesse
			 Ecrire_Trame(T_IM_Asservissement);
			 do{}while(Lire_Trame(&Trame_Recue)==0); // Attendre réponse
			 // Acquisition de la consigne
			 Ecrire_Trame(T_IRM_Commodo_EG);
			 do{}while(Lire_Trame(&Trame_Recue)==0);
			 if(Trame_Recue.ident.extend.identificateur.ident==Ident_T_IRM8_Commodo_EG)
				{AN0H =Trame_Recue.data[2]; // On récupére les MSB entree analogique Commodo EG
			 	 AN10L =Trame_Recue.data[4]; // On récupére les LSB AN1 et AN0
	 	 	       // Traiter les données et reconstituer les résultats
			 	 S_Consigne=(unsigned short)(AN0H);	//Transfert avec transtypage
			 	 S_Consigne=S_Consigne<<2;	// Décaler de 2 bits vers poids forts
			 	 S_Temp=(unsigned short)(AN10L&0x0C); // Pour ne récupérer que les 2 bits AD1 et AD0
			 	 S_Consigne=S_Consigne|(S_Temp>>2);
				}
			}} // Fin acquisition et traitement
 
	Cptr_Affichage++;
	if(Cptr_Affichage==20000)
		{Cptr_Affichage=0;
		 gotoxy(1,12);
 		 printf("  Valeur de l'entree Consigne:                  \n");
		 printf("  Valeur de l'entree Mesure vitesse:            \n");
		 printf("  Ecart = Consigne - Mesure:                    \n");
		 printf("  Valeur de la Commande moteur:                 \n");
		// Afficher grandeurs
		gotoxy(1,12);
		 printf("  Valeur de l'entree Consigne: %d\n",S_Consigne);
		 printf("  Valeur de l'entree Mesure vitesse: %d\n",S_Mesure_Vitesse);
		 printf("  Ecart = Consigne - Mesure: %d\n",Ecart);
		 printf("  Valeur de la commande moteur:%d\n",Cde_Moteur);
		 printf("  On doit verifier la relation:\n");
		 printf("  Commande moteur = (Kp*Ecart)/16 avec Kp= %d\n",Kp);}	 		 	 
	} //  Fin boucle principale
} // Fin fonction principale