bonjours ,je développe actuellement un contrôleur moteur a base du microprocesseur NXP lpc2138 j utilise uvision3 comme compilateur et le kit mcb2130 mais je bloque a effectuer une fonction d asservissement position et vitesse .le driver moteur de puissance es un LMD18200t
voici le code aidez moi SVP
#include <LPC21xx.H> /* LPC21xx definitions */
#include <MATH.H> /* Math definition */
#include <LPC213X.H>
#include "Timer.h"
#define CPU_CLOCK 60000000 /* CPU Clock */
#define VPB_CLOCK (CPU_CLOCK/4) /* VPB Clock */
/*************************************************************************************************************************/
/**************************************** PROGRAMME Sound DATA *****************************************************/
/*************************************************************************************************************************/
//ces valeurs sont uniquement utilisé pour informé d une erreur sonore a utilisé avec le dac ;-)
//faut utilisé logicielle de convertion wavtohex.exe pour faire une bak de donné son ;-)
//faire attention de l emplacement mémoire
unsigned int Index = 0;/**************** Sound Data Index **************/
const char SoundData[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,
};
/*************************************************************************************************************************/
/**************************************** PROGRAMME tempo **********************************************************/
/*************************************************************************************************************************/
extern long volatile timeval;
void wait (unsigned long t) /* fonction wait la valeur de t es en ms */
{
unsigned long i;
i = timeval;
while ((i + (t/10)) != timeval);
}
/*************************************************************************************************************************/
/**************************************** PROGRAMME GPIO ***********************************************************/
/*************************************************************************************************************************/
/*ecriture sur le port p1 bit 16 a 23*/
void write_p1_16_23(int data)
{
IODIR1 = 0xFF0000; /* P1.16..23 défini comme sortie */
data <<= 16; /*décalage a gauche de 16*/
IOSET1 |= data; /* Turn on LED */
}
/*ecriture sur le port p0 bit 16 a 23*/
void write_p0_16_23(int data)
{
IODIR0 = 0xFF0000; /* P0.16..23 defini comme sortie */
data <<= 16; /*décalage a gauche de 16*/
IOSET0 |= data; /* Turn on LED */
}
/*lecture du port p1 bit 16 a 23*/
char read_p1_16_23(void)
{
int data;
IODIR1 = 0x000000; /* P1.16..23 defini comme entrée */
data=(unsigned char)(IOPIN1>>16); /* lecture du P1_16_23 et decalé data de 16 */
return(data);
}
/*************************************************************************************************************************/
/**************************************** PROGRAMME DRIVER LMD18200T ***********************************************/
/*************************************************************************************************************************/
/////////////////////////////////////
// initialisation du pwm2 //
/////////////////////////////////////
void init_pwm2(void)
{
//initialisation PWM2
PINSEL0 |= 0x00028000; //Enable pin 0.7 as PWM2
PWMPR = 0x00000001; //Load prescaler
PWMPCR = 0x0000404; //PWM channel 2 double edge control, output enabled
PWMMCR = 0x00000003; //On match with timer reset the counter "utilisé pour déterminé la frequence PWM ici 29.80khz"
PWMMR0 = 0x00000100; //set cycle rate to 256=hex100 "la période PWM fractionné en 256 " ces la resolution du PWM "
PWMMR1 = 0x00000000; //set rising edge of PWM2 to 0 ticks
PWMMR2 = 0x00000000; //set falling edge of PWM2 to 0 ticks
PWMLER = 0x00000007; //enable shadow latch for match 0 - 2
PWMEMR = 0x00000280; //Match 1 and Match 2 outputs set high
PWMTCR = 0x00000002; //Reset counter and prescaler
PWMTCR = 0x00000009; //enable counter and PWM, release counter from reset
}
////////////////////////////////////////////////////////////////////
// remise a zero du controle moteur p1.16"brake=0" p1.17"sign=0" //
////////////////////////////////////////////////////////////////////
void init_sens_brake_moteur(void)
{
IOCLR1= 0x00030000; //effacer p1_16 a p1_17 c utilisé uniquement pour la remise a zero du controle moteur
//brake=0 et signe=0 apret un mouvement moteur
}
/*************************************************************************************************************************/
/*************************************** meusure de l'image du courant LMD18200T ***********************************/
/*************************************************************************************************************************/
unsigned long mesure_courant(void)
{
unsigned long imageI;
unsigned long imageI1;
unsigned long vali=0;
init_timer(); //??????????????????????????????????????????????????????????????????????????????.........WHY.........?????
PINSEL1 = 0x01080000; /* enable ADC */
DACR = 0x00008000; /* DAC Output set to Middle Point */
IODIR1 = 0xFF0000; /* P1.16..23 defined as Outputs */
//conversion ADC de l'image du courant
AD0CR = 0x00200402; /* Setup A/D: 10-bit AIN0 @ 3MHz */
AD0CR |= 0x01000000; /* Start A/D Conversion */
do {
vali = AD0DR; /* Read A/D Data Register */
}
while ((vali & 0x80000000) == 0); /* Wait for end of A/D Conversion */
AD0CR &= ~0x01000000; /* Stop A/D Conversion */
vali=imageI; /*changement de variable*/
imageI >>=6; /* decalage de 6 de la valeur i moteur */
imageI1=(imageI & 0x3ff); /*recuperation uniquement de la valeur de la conversion 10bit*/
write_p0_16_23(imageI1);
IOCLR0 = imageI1;
return(imageI1); /* renvoi de la valeur mesuré */
}
////////////////////////////////////////////////////////////////////////
// fonction1 affiche valeur du courant //
////////////////////////////////////////////////////////////////////////
void affiche_courant1 (void) //fonction pour veriffier ci adc fonctionne toujours ;-) //
{
unsigned int volume;
unsigned int val;
init_timer();
/***********************************************/
/* test sortie DAC avec generateur de fonction */
/***********************************************/
PINSEL1 = 0x01080000; /* enable DAC */
DACR = 0x00008000; /* DAC Output set to Middle Point */
IODIR1 = 0xFF0000; /* P1.16..23 defined as Outputs */
/****************************************************************************************/
/* test entrée ADC avec avec affichage de la valeur convertie sur le port 0 de fonction */
/****************************************************************************************/
AD0CR = 0x00200402; /* Setup A/D: 10-bit AIN0 @ 3MHz */
AD0CR |= 0x01000000; /* Start A/D Conversion */
do {
val = AD0DR; /* Read A/D Data Register */
}
while ((val & 0x80000000) == 0); /* Wait for end of A/D Conversion */
AD0CR &= ~0x01000000; /* Stop A/D Conversion */
val=val>>=6; /* decalage Data register de 6 */
volume=val<<=14; /* decalage Data register de 14 */
IOSET1 = volume; /* Turn on LED */
wait (10); /* call wait function 10ms*/
IOCLR1 = volume; /* Turn off LED */
}
////////////////////////////////////////////////////////////////////////
// fonction2 affiche valeur du courant //
////////////////////////////////////////////////////////////////////////
void affiche_courant2 (void) //fonction pour veriffier ci adc fonctionne toujours ;-) //
{
unsigned int volume;
unsigned int val;
init_timer();
/***********************************************/
/* test sortie DAC avec generateur de fonction */
/***********************************************/
PINSEL1 = 0x01080000; /* enable DAC */
DACR = 0x00008000; /* DAC Output set to Middle Point */
IODIR0 = 0xFF0000; /* P1.16..23 defined as Outputs */
/****************************************************************************************/
/* test entrée ADC avec avec affichage de la valeur convertie sur le port 0 de fonction */
/****************************************************************************************/
AD0CR = 0x00200402; /* Setup A/D: 10-bit AIN0 @ 3MHz */
AD0CR |= 0x01000000; /* Start A/D Conversion */
do {
val = AD0DR; /* Read A/D Data Register */
}
while ((val & 0x80000000) == 0); /* Wait for end of A/D Conversion */
AD0CR &= ~0x01000000; /* Stop A/D Conversion */
val=val>>=6; /* decalage Data register de 6 */
volume=val<<=14; /* decalage Data register de 14 */
IOSET0 = volume; /* Turn on LED */
wait (10); /* call wait function 10ms*/
IOCLR0 = volume; /* Turn off LED */
}
////////////////////////////////////////////////////////////////////////////////////////////////
// fonction3 affiche valeur du courant et renvoi la valeur //
////////////////////////////////////////////////////////////////////////////////////////////////
unsigned long affiche_courant3 (void) //fonction pour veriffier ci adc fonctionne toujours ;-) //
{
unsigned int volume=0;
unsigned int val=0;
unsigned long imageI1=0;
init_timer();
/***********************************************/
/* test sortie DAC avec generateur de fonction */
/***********************************************/
PINSEL1 = 0x01080000; /* enable DAC */
DACR = 0x00008000; /* DAC Output set to Middle Point */
IODIR0 = 0xFF0000; /* P1.16..23 defined as Outputs */
/****************************************************************************************/
/* test entrée ADC avec avec affichage de la valeur convertie sur le port 0 de fonction */
/****************************************************************************************/
AD0CR = 0x00200402; /* Setup A/D: 10-bit AIN0 @ 3MHz */
AD0CR |= 0x01000000; /* Start A/D Conversion */
do {
val = AD0DR; /* Read A/D Data Register */
}
while ((val & 0x80000000) == 0); /* Wait for end of A/D Conversion */
AD0CR &= ~0x01000000; /* Stop A/D Conversion */
val=val>>=6; /* decalage Data register de 6 */
imageI1=val; /* affectation de la valeur val a volume */
//affichage de la valeur du courant
volume=val<<=14; /* decalage Data register de 14 */
IOSET0 = volume; /* Turn on LED */
wait (10); /* call wait function 10ms*/
IOCLR0 = volume; /* Turn off LED */
return(imageI1); /* renvoi de la valeur mesuré */
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////
//mouvement standard non codé ACC VMAX DEC//
////////////////////////////////////////////
//p1.16=brake p1.17=sign
//faut rajouté la meusure de courant IMAX,l'asservissement vitesse et de position ,
//lecture du codeur
//lecture du capteur de home ,sc1,sc2
//lecture de la protection temperature LMD18200T,time out ,Vmin
void fnl_lmd18200(unsigned long pwm,int brake,int sign,unsigned long acc,unsigned long tmpvmax,unsigned long dec,unsigned long imax)
{
unsigned long ic0; //premiere valeur du courant apret la mesure
unsigned long ic1; //seconde valeur du courant apret la mesure
unsigned long i; //période de la pulse positive du signal PWM "vitesse max "
unsigned long t; //variable temporel de l'accélération
int control_M; //valeur de controle moteur "sens moteur et brake moteur"
control_M=0; //remise a zero du controle moteur"sens et brake "
control_M=(brake|(sign<<1));//faire un ou logique entre brake et (sign avec decalage a gauche de 1)
write_p1_16_23(control_M);//ecriture sur le port1 "P1.16 a P1.17"_____"brake et sign"
//I=((pwm/100)*255); //calcul pwm% vers valeur comprise entre 0 et 255 ???????????????a revoir????
//////////////////////////////
// phase d'accélération //
//////////////////////////////
for (i=0;i<pwm;i++)
{
for (t=0;t<acc;t++) //valeur de l'accélération tempo
{
//lecture de la vitesse & position réel ???????????????????
//correction de la vitesse & position ???????????????????
PWMMR2 = i; //modulation du signal pwm
PWMLER = 0x00000007; //enable shadow latch for match 0 - 2
//lecture du courant par interuption timer sera plus judicieux!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ic0=0;
ic1=0;
ic0=affiche_courant3 ();//lecture du courant et affichage sur p1_16 a p1_23
ic1=affiche_courant3 ();//lecture du courant et affichage sur p1_16 a p1_23
//test du overload courant ci c oui stop moteur sa fonctionne pas ?????????????????????????????????????????????????????????????????
// if ((ic0>=imax)&&(ic1>=imax)) //ci ya overload avec ic0 et overload avec ic1 faire un arret moteur
// {
// while(1){
// PWMMR2 = 0; //arret du moteur
// PWMLER = 0x00000007; //enable shadow latch for match 0 - 2
//
// } ;//boucle sans fin faut bien sortir de cette boucle un jours ;-)
// }
}
}
///////////////////////////
// phase vitesse max //
///////////////////////////
for (t=0;t<tmpvmax;t++) //tempo a la vitesse max
{
//lecture de la vitesse réel & position réel ??????????????
//correction de la vitesse & position ???????????????????
PWMMR2 = i; //modulation du signal pwm
PWMLER = 0x00000007; //enable shadow latch for match 0 - 2
//lecture du courant par interuption timer sera plus judicieux!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ic0=0;
ic1=0;
ic0=affiche_courant3 ();//lecture du courant et affichage sur p1_16 a p1_23
ic1=affiche_courant3 ();//lecture du courant et affichage sur p1_16 a p1_23
//test du overload courant ci c oui stop moteur sa fonctionne pas ?????????????????????????????????????????????????????????????????
// if ((ic0>=imax)&&(ic1>=imax)) //ci ya overload avec ic0 et overload avec ic1 faire un arret moteur
// {
// while(1){
// PWMMR2 = 0; //arret du moteur
// PWMLER = 0x00000007; //enable shadow latch for match 0 - 2
//
// } ;//boucle sans fin faut bien sortir de cette boucle un jours ;-)
// }
}
////////////////////////////////
// phase de déccelération //
////////////////////////////////
for (i=pwm;i>0;i--)
{
for (t=0;t<dec;t++) //valeur de l'accélération tempo
{
//lecture de la vitesse réel & position réel ??????????????
//correction de la vitesse & position ???????????????????
PWMMR2 = i; //modulation du signal pwm
PWMLER = 0x00000007; //enable shadow latch for match 0 - 2
//lecture du courant par interuption timer sera plus judicieux!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ic0=0;
ic1=0;
ic0=affiche_courant3 ();//lecture du courant et affichage sur p1_16 a p1_23
ic1=affiche_courant3 ();//lecture du courant et affichage sur p1_16 a p1_23
//test du overload courant ci c oui stop moteur sa fonctionne pas ?????????????????????????????????????????????????????????????????
// if ((ic0>=imax)&&(ic1>=imax)) //ci ya overload avec ic0 et overload avec ic1 faire un arret moteur
// {
// while(1){
// PWMMR2 = 0; //arret du moteur
// PWMLER = 0x00000007; //enable shadow latch for match 0 - 2
//
// } ;//boucle sans fin faut bien sortir de cette boucle un jours ;-)
// }
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////
// mouvement simple //
///////////////////////////////////
//p1.16=brake p1.17=sign
void driver_lmd18200(int pwm,int brake,int sign)//largeur de la pulse"pwm 0-255";frein"brake 0-1";sens de rotation"sign 0-1"
{
int control1_M;
control1_M=0;
control1_M=(brake|(sign<<1));//faire un ou logique entre brake et (sign avec decalage a gauche de 1)"mise en forme de l'octet"
write_p1_16_23(control1_M);//ecriture sur le port1 "P1.16 a P1.17"_____"brake et sign"
PWMMR2 = pwm; //valeur du pwm
PWMLER = 0x00000007; //enable shadow latch for match 0 - 2
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// mouvement d'apret une fonction math //
//////////////////////////////////////////////////////
//diferantes fonction testé .
//a modiffier pour ne pas depassé 255 en Y et ne jamais etre négatif
//y=t;//la fonction math de accélération
//y=256-t;//la fonction math de décélération
//y=128;
//y=(256/t)-1; //la fonction math a executé
//y=(2048/t)-1; //la fonction math a executé
//y=(t*t/128); //la fonction math a executé
//y= ((256/t)-1+(t*t/128));//la fonction math a executé
//y=256/log10(t)-100;//la fonction math a executé
//y=((128*log10(t+10)-128)/t)*60;//la fonction math a executé
//y=sqrt(t)*32;//la fonction math a executé racine caré de t
//y=127*cos(t*0.025)+127;//la fonction math sinus "0.025 c la frequence"
//y=256*sin(t*0.025);//la fonction math sinus mono alternance "0.025 c la frequence"
//y=128*sin(t*0.05)+128;//la fonction math sinus mono alternance "0.05 c la frequence"
//remarque dec que y prend la valeur négative c'es considéré comme 256 comment remedier a sa ????
//je suppose qui faudrai metre une limite de y positive et negativee car y ne peut prendre que
//une valeur comprise entre 0et 256
//accélération en foncion cos avec un déphasage
void driver_fonction_math1(unsigned long x,unsigned long tacc,int brake,int sign)//nombre de point utilié en x,tacc,brake,sign
{
unsigned int y;//la valeur apret calcule de la fonction
unsigned long t;//valeur temporelle1
unsigned long s;//valeur temporelle 2
for (t=0;t<x;t++) // temp de la fonction
{
for (s=0;s<tacc;s++) // tempo
{}
y=127*cos((t+120)*0.025)+127;//la fonction math sinus "0.025 c la frequence"
//lecture de la vitesse & position réel ???????????????????
//correction de la vitesse & position ???????????????????
driver_lmd18200(y,brake,sign);//largeur de la pulse"pwm 0-255";frein"brake 0-1";sens de rotation"sign 0-1"
}
}
//décélération en fonction cos
void driver_fonction_math2(unsigned long x,unsigned long tdec,int brake,int sign)//nombre de point utilié en x,tdec,brake,sign
{
unsigned int y;//la valeur apret calcule de la fonction
unsigned long t;//valeur temporelle1
unsigned long s;//valeur temporelle2
for (t=0;t<x;t++) // temp de la fonction
{
for (s=0;s<tdec;s++) // tempo
{}
y=127*cos(t*0.025)+127;//la fonction math cos "0.025 c la frequence"
//lecture de la vitesse & position réel ???????????????????
//correction de la vitesse & position ???????????????????
driver_lmd18200(y,brake,sign);//largeur de la pulse"pwm 0-255";frein"brake 0-1";sens de rotation"sign 0-1"
}
}
//fonction cloche "fonction de gauss" pas encore operationelle prb valeur du PWM faut voir autre chose
void driver_fonction_math3(unsigned long PWM,int BRAKE,int SIGNE,unsigned long ACC,unsigned long TMPVMAX,unsigned long DEC)
{
driver_fonction_math1(PWM/2,ACC,BRAKE,SIGNE);//nombre de point fenetre a utilisé sur l axe des x,tdec,brake,sens
fnl_lmd18200(PWM,BRAKE,SIGNE,0,TMPVMAX,0,2000000000) ;//vmax=pwm0-255,brake0-1,signe0-1,tacc0-infini,tvmax0-infini,tdec0-infini
driver_fonction_math2(PWM/2,DEC,BRAKE,SIGNE);//nombre de point fenetre a utilisé sur l axe des x,tdec,brake,sens
init_sens_brake_moteur();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// fonction correction vitesse et position pas encore terminé //
/////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned long correction_PID(unsigned long PWM1,unsigned long KP,unsigned long KI,unsigned long KD,unsigned long position,unsigned long vitesse)
{
//pas encore etudier
unsigned long PWM2; //valeur apret calcul de la correction
PWM2=0; //mise a zero de la valeur de sortie
PWM1=0; //mise a zero de la valeur d'entrée
KP=0; //juste pour pas avoir de warning compillation
KD=0; //juste pour pas avoir de warning compillation
KI=0; //juste pour pas avoir de warning compillation
position=0; //juste pour pas avoir de warning compillation
vitesse=0; //juste pour pas avoir de warning compillation
return (PWM2); //retour de la valeur PWM apret corection
}
/***************************************************************************************************************************************/
/***************************************************************************************************************************************/
/***************************************************************************************************************************************/
/***************************************** PROGRAMME PRINCIPALE **************************************************/
/***************************************************************************************************************************************/
/***************************************************************************************************************************************/
/***************************************************************************************************************************************/
void main(void)
{
int code_mouvement;//00=faire une home;01=faire un mouvement cw;02=faire un mouvement ccw
switch (code_mouvement)//ici le code du mouvement ce fait par rs 232
{
case (0x00):
///faire une home
break;
case (0x1):
///faire un mouvement cw
break;
case (0x02):
///faire un mouvement cw
break;
};
init_pwm2(); //initialisation du pwm2 pin 0.7
//faire des mouvements allez retour en utilisant les fonctions mouvements moteur
while(1) //boucle sans fin
{
//mouvement1:
fnl_lmd18200(255,0,0,1,50,1,1023) ;//vmax=pwm0-255,brake0-1,signe0-1,tacc0-infini,tvmax0-infini,tdec0-infini,imax0-1023
init_sens_brake_moteur();
//mouvement2:
fnl_lmd18200(255,0,1,1,50,1,1023) ;//vmax=pwm0-255,brake0-1,signe0-1,tacc0-infini,tvmax0-infini,tdec0-infini,imax0-1023
init_sens_brake_moteur();
//mouvement3:
driver_fonction_math1(128,40000,0,0);//nombre de point fenetre a utilisé sur l axe des x,tacc,brake,sens
fnl_lmd18200(255,0,0,0,100,0,800) ;
driver_fonction_math2(128,40000,0,0);//nombre de point fenetre a utilisé sur l axe des x,tdec,brake,sens
init_sens_brake_moteur();
//mouvement4:
// driver_fonction_math3(255,0,1,25000,250000,25000);
}
}