Bonjour, je souhaite réaliser un asservissement en position pour moteur DC. pour cela j'aimerais utiliser un dspic 33FJ12MC201 car il possède un encodeur pour les codeurs optiques, plusieurs pwm, et qu'il est pas cher lol.
J'ai déjà réalisé quelques programmes pour pic 16F, mais sous Pic C compiler.
C'est donc la première fois que j'utilise MPLab.
J'ai tenté de déchiffrer la datasheet pou savoir quoi mettre dans quels registres...
mais en simulation sous MPLab, mes interruptions de se déclenchent pas et ma pwm n'a pas l'air de bouger.
Je voudrais savoir si quelque chose manquerais dans le code.
habituellement avec PIC c compiler, des fonctions sont toutes prêtes pour activer la pwm et les interruptions...
donc je ne sais pas si j'ai modifié les bons registres...
voici le code:
Je suis aussi à la recherche de cours concernant la programmation des pic (et dspic), les registres... si vous connaissez des liens, je suis preneur!Code:#include "dspicmoteur.h" #define maxpwm 1000 #define PWM_OFF 0 #define dirpc PORTAbits.RA4 #define maximumencodeur #define FOSC 10e6 // 10 Mhz crystal in XTL mode #define PLL 8.0 // 8x PLL #define FCY ((FOSC*PLL)/(4.0)) // Instruction cycle frequency int main(void); void __attribute__((__interrupt__,auto_psv)) _INT0Interrupt(void); void __attribute__((__interrupt__,auto_psv)) _T1Interrupt(void); void setup_TMR1(void); void setup_INT0(void); void setup_PWM(void); void setup_encoder(void); void setpwm(int); float calculPID(struct PID); struct PID pid; // ************************************** // * MAIN * // ************************************** int main(void) { //-------------------------------declaration des variables------------// // à modifier en fonction du moteur pid.pgain= 1.0; pid.igain=0.5; pid.dgain=0.5; //--------------------------------initialisation du dspic---------------// setup_INT0(); setup_TMR1(); setup_PWM(); setup_encoder(); _TRISA4=1; // configure la pin A4 en input (dirpc) _NOSC=3; // configure le premier oscillateur à quartz; pid.command=15; pid.prev_cmd=0; // met les donnée à 0. pid.feedback=0; //-------------------------------------programme----------------------// while(1); // tout se gère par les interruptions.... } // ************************************** //******************************** fonctions initialisation ********************************************************** // ************************************** //-------------------------------------setup TIMER 1------------------// void setup_TMR1(void){ T1CONbits.TON=1; // start 16-bits Timer1 T1CONbits.TSIDL=0; // Continue module operation in Idle mode T1CONbits.TCKPS= 2; // Prescale // 11 = 1:256 // 10 = 1:64 // 01 = 1:8 // 00 = 1:1 TMR1=0; T1CONbits.TCS=0; // on prend l'horloge interne (FCY) T1CONbits.TGATE=1; // Gated time accumulation enabled PR1=255; // timer period _T1IE=1; // enable interrupt _T1IP=0; // set the interrupt priority } //-------------------------------------setup interruptions externes----// void setup_INT0(void){ _NSTDIS = 1; // interrupt nesting disabled _INT0EP = 0; // interrupt sur front montant (flag à 1 lorsque moteur arrêté) _INT0IF = 0; // flag interrupt INT0 à 0 (StopF) _INT0IE = 1; // interrupt INT0 activée } //------------------------------------setup interruptions TIMER 1-----// void setup_PWM(void){ P1TCONbits.PTEN=1; // PWM time base is on P1TCONbits.PTSIDL=1; //1 = PWM time base halts in CPU Idle mode //0 = PWM time base runs in CPU Idle mode P1TCONbits.PTOPS= 15; //1111= 1/16 postscale //... //0001=1:2 postscale //0000=1:1 postscale P1TCONbits.PTCKPS=3; // prescaler PWM 1 00-> 1:1 // 01-> 1:8 // 10-> 1:64 // 11-> 1:256 P1TPERbits.PTPER=maxpwm; //jusque où compte le timer PWM1CON1bits.PMOD2=1; // met les pwm en independant PWM1CON1bits.PEN1H=1; // met les sorties pwm1H1 et pwm1H2 en pwm. P1OVDCONbits.POVD1H=1; // Output on PWMx I/O pin is controlled by the PWM generator P2TCONbits.PTEN=1; // PWM time base is on P2TCONbits.PTSIDL=1; //1 = PWM time base halts in CPU Idle mode //0 = PWM time base runs in CPU Idle mode P2TCONbits.PTOPS= 15; //1111= 1/16 postscale //... //0001=1:2 postscale //0000=1:1 postscale P2TCONbits.PTCKPS=3; // prescaler PWM 1 00-> 1:1 // 01-> 1:8 // 10-> 1:64 // 11-> 1:256 P2TPERbits.PTPER=maxpwm; //jusque où compte le timer PWM2CON1bits.PMOD1=1; // met les pwm en independant PWM2CON1bits.PEN1H=1; // met les sorties pwm1H1 et pwm1H2 en pwm. P2OVDCONbits.POVD1H=1; // Output on PWMx I/O pin is controlled by the PWM generator P1DC1=200; } void setup_encoder(void){ _QEIM=7; // encode en 4x (detecte les front montant et decendant des 2 entrée) // et le compteur ne se réinitialise que quand maximumencoder est atteind (qui ne doit pas arriver) _QEA1R=0; // ramap la pin RP0 vers QEA (une entrée du codeur) _QEB1R=1; // remap la pin RP1 vers QEB (l'autre entrée du codeur) } // ************************************** //******************************** interruptions ********************************************************** // ************************************** //------------------------------------- interruptions externes---------// void __attribute__((__interrupt__)) _INT0Interrupt(void) { if (dirpc==1) pid.command++; // incremente ou decremente en fonction de la direction reçue. else pid.command--; _INT0IF = 0; return; } //--------------------------------------interruptions TIMER 1---------// void __attribute__((__interrupt__)) _T1Interrupt(void) { // tout les 0.1 ms pid.feedback=POSCNT; // recupère la position de l'encodeur optique calculPID(pid); // calcul le PID setpwm(pid.output); // regule le moteur en conséquence _T1IF=0; return; // quitter interrupt } // ************************************** //******************************** fonctions calcul ********************************************************** // ************************************** //-------------------------------modifier le duty de la pwm----------// void setpwm(int value){ if (value>0){ P1DC2=0; if (value<maxpwm) P1DC1=value; else P1DC1=maxpwm; } if (value==0){ P1DC1=0; P2DC1=0; } if (value<0){ P1DC1=0; value=-value; if (value<maxpwm) P2DC1=value; else P2DC1=maxpwm; } } //---------------------calcul du PID avec pid déclaré en globale---// float calculPID(struct PID pid){ pid.error =(float)(pid.command - pid.feedback); //calcul de l'erreur de position pid.error_i=pid.error_i+(float)pid.error; //calcul terme integral pid.error_d=pid.error-pid.prev_error; //calcul terme derivé pid.prev_error=pid.error; pid.output=pid.pgain*pid.error+pid.igain*pid.error_i+pid.dgain*pid.error_d; return pid.output; }
Merci d'avance!
Olivier
-----