Répondre à la discussion
Page 1 sur 2 1 DernièreDernière
Affichage des résultats 1 à 30 sur 36

amelioration code PIC 16F876 moteur pas à pas



  1. #1
    olver62

    amelioration code PIC 16F876 moteur pas à pas


    ------

    Bonjour, je désire réaliser un montage pour contrôler un moteur pas à pas (3.3A par phase) en micro pas.
    j'ai pensé au pic 16F876 pour la logique, donc les 2 sorties pwm , une foi filtrées, m'indiqueraient l'intensité (1v<=>1A) dans chaque bobine.
    j'ai réaliser le code en C grâce au logiciel PICC.
    j'ai ensuite réalisé et simulé le schéma grâce à Proteus.
    le programme fonctionne très bien, mais même cadencé à 20Mhz, je ne peux envoyer des signaux de pas (horloge) qu'à 1,5Khz seulement.
    j'ai essayé d'alléger le code pour qu'il soit plus rapide...



    la lecture du "clock" se fait à chaque parcours du code dans le "while" il faut donc que le "while" soit lu le plus rapidement possible...

    j'aimerais atteindre des fréquences proche de 10 KHz (si c'est possible)
    merci d'avance!

    -----

  2. Publicité
  3. #2
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    #include <16F876a.h>
    #fuses HS, NOPROTECT, NOWDT
    #use delay(clock=20000000)
    #include <math.h>
    #include <stdlib.h>
    #define NUM_LENGTH 8
    // pin RB (0..4) interrupteur rotatif pour choix de la précision
    // pin RC (3..4) connecté au premier L6203
    // pin RC (5..6) connecté au deuxième L6203
    // pin RB (5..6) respectivement le pas, le sens
    //les sorties ppc (1 et 2) sont ensuite filtrées et comparées à la tension "sense" du L6203, pour alimenter l'enable.
    //
    //

    float IB1n,IB2n, IB1m, IB2m, deltaI, lastdeltaI, lastsens, sens, lastclock, clock, ok1, ok2, Iref;
    int Ip1, Ip2, I1, I2;
    void main()
    {
    setup_adc( ADC_CLOCK_INTERNAL );

    lastsens=1;
    lastclock=0;

    setup_ccp1(CCP_PWM);
    setup_ccp2(CCP_PWM);
    setup_timer_2(10000000, 100, 1);
    set_pwm1_duty(0);
    set_pwm2_duty(0);

    if (INPUT(PIN_B0)) //définition du mode (pas entier, demi pas....)
    deltaI = 16;
    if (INPUT(PIN_B1))
    deltaI = 8;
    if (INPUT(PIN_B2))
    deltaI = 4;
    if (INPUT(PIN_B3))
    deltaI = 2;
    if (INPUT(PIN_B4))
    deltaI = 1;


    {IB1n = 0;
    IB2n = 16;
    IB1m = -16;
    IB2m = 0;


    while(1)
    {

    clock= INPUT(PIN_B5);

    if (clock && (clock!=lastclock)) //avance d'un pas
    {
    if (IB1m < IB1n)
    {if ((IB1n + deltaI)<= 16)
    {IB1m = IB1n ; IB1n = (IB1n + deltaI);}
    else { IB1m = IB1n ; IB1n= (IB1n - deltaI);}}

    else {if ((IB1n - deltaI)>= -16)
    {IB1m = IB1n ; IB1n = (IB1n - deltaI);}
    else { IB1m = IB1n ; IB1n= (IB1n + deltaI);}};

    if (IB2m < IB2n)
    {if ((IB2n + deltaI)<= 16)
    {IB2m = IB2n ; IB2n = (IB2n + deltaI);}
    else { IB2m = IB2n ; IB2n = (IB2n - deltaI);};}

    else
    {if ((IB2n - deltaI)>= -16)
    {IB2m = IB2n ; IB2n = (IB2n - deltaI);}
    else { IB2m = IB2n ; IB2n = (IB2n + deltaI);}}; //calcul du pourcentage d'intensité dans chaque bobine (de -16 à 16)
    }
    lastclock=clock;




    sens= INPUT(PIN_B6);
    if (sens!=lastsens)
    {IB1m = (IB1n + (IB1n - IB1m)) ; IB2m = (IB2n + (IB2n - IB2m)) ; lastsens = sens;}; //changement de sens



    if (IB1n > 0)
    {Output_bit(PIN_C4,0); Output_bit(PIN_C3,1);};
    if (IB1n < 0)
    {Output_bit(PIN_C3,0); Output_bit(PIN_C4,1);};
    if (IB1n == 0)
    {Output_bit(PIN_C3,0); Output_bit(PIN_C4,0);};
    if (IB2n > 0)
    {Output_bit(PIN_C5,0); Output_bit(PIN_C5,1);};
    if (IB2n < 0)
    {Output_bit(PIN_C5,0); Output_bit(PIN_C6,1);}; //orientation des courants
    if (IB2n == 0)
    {Output_bit(PIN_C5,0); Output_bit(PIN_C6,0);};


    if(IB1n < 0)
    Ip1=-IB1n; else Ip1=IB1n;

    if(IB2n < 0)
    Ip2=-IB2n; else Ip2=IB2n;

    if (ip1!=I1)
    {set_pwm1_duty(Ip1*6); I1=Ip1;};
    if (Ip2!=I2) //régulation par les "enable"
    {set_pwm2_duty(Ip2*6); I2=Ip2;};

    }
    }
    j'avais oublié le code...

  4. #3
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    pour information, pour calculer l'intensité, je me sert de deux variables Ib1m et ib2m qui sont les intensités précédentes dans les 2 bobines, cela me permet de savoir si je suis dans la "montée" ou dans la "descente" du pseudo signal triangulaire.

    pour le cas où le signal "clock" reste longtemps à l'état haut et pour qu'il ne soit pas perçu comme 2 pulsation, j'ai incorporé une variable "lastclock" qui résous ce problème.

    merci d'avance
    salutations Olivier

  5. #4
    FantomX

    Re : amelioration code PIC 16F876 moteur pas à pas

    Bonsoir,

    Effectivement le code me parait un peu lourd. Tu effectues vachement d'opérations surtout sur du float qui est une donnée 24bits. Pourquoi dois-tu calculer l'intensité dans tes bobines ?

    Est-ce que tu peux fournir le schéma électrique de ton circuit ?

    Quand tu dis que tu ne peux pas envoyer à plus de 1,5kHz, tu veux dire que le PIC ne te sort rien au niveau des PWM ou que ton moteur décroche à cette vitesse ?

    Pour ce qui est de la gestion des PWM, tu as ce site où tu trouveras un code bien commenté (compilateur PICC ) pour l'utiliser avec un 16F876 : http://angeliz.free.fr/langagec/howto_pwm.htm

    @+

    Greg

  6. A voir en vidéo sur Futura
  7. #5
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    Bonjour, merci pour ta reponse et pour le lien concernant les pwm!
    pour les bonnées float, j'avais essayé de les mettre en int signé mais il y avait des erreurs (peut être que je ne l'ai pas fait correctement...)
    toute les variables déclarées comme float prennent des valeurs entieres de -16 à +16 inclus.

    Pour contrôler un moteur pas à pas en micropas, il faut regler le courant dans chaque bobine, pour créer, si possible, une sinusoîde . Dans mon code, je me limite à un signal triangulaire, plus facile à coder à mon gout...

    http://images.google.fr/imgres?imgur...%3Dfr%26sa%3DN

    Au dela de 1.5KHz, j'ai remarqué que le pic ne prennais plus en compte toutes les impultions "clock" tout simplement parce que l'impulsion intervien alors que le code ne lit pas cette pin.
    La "frequence de sortie" est plafonnée. Par exemple, si j'envoie un signal de 100Khz, le pic va se comporter comme avec un signal de 1.5Khz.
    j'ai remarqué cela avec le logiciel proteus, qui contient un oscilloscope.
    Pour le shema electrique, il n'est pas encore fini, mais je vais vous envoyer la partie que doit realiser le pic.

    Salutations
    Olivier

  8. #6
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    voila le shema, il doit contenir pas mal d'erreur. Ce sont les AOP qui permettent de reguler le courant dans les bobines du moteur.
    salutations
    Olivier
    Images attachées Images attachées

  9. Publicité
  10. #7
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    Je vien de m'apercevoir d'un problème, le L6203 (pont en H) est limité à 100Khz, comme il y aurra un signal pulsé qui règlera l'intensité, la commande des pas devra être bien inferieure à 100Khz! (10Khz n'est pas trop?).
    ou sinon, j'ai pensé à utiliser 2 sorties analogiques du pic plutôt que les sorties pwm, mais je ne sais pas si ca ralongera le temps de lecture du code (pour la conversion...).

    pour les "float", je vien de les changer en "signed int", du coup la rom et la ram se sont bien allégées et le code fonctionne toujours.
    merci d'avance!
    Salutations
    Olivier

  11. #8
    FantomX

    Re : amelioration code PIC 16F876 moteur pas à pas

    Salut,

    C'est bien que tu sois passé en entiers signés. Du coup, tu travailles avec des données 16bits ce qui non seulement allège la mémoire mais te permet de travailler plus vite.

    Pour ce qui est de la mesure de courant, tu peux effectivement te servir du CAN du PIC en mesurant la tension aux bornes d'un shunt pour avoir une image tension/courant. Reste à voir le temps de conversion du CAN dans la datasheet du PIC. Pour utiliser le CAN, tu peux jeter un oeil toujours sur le même site : http://angeliz.free.fr/langagec/howto_can.htm.

    Bon courage.

    Greg.

  12. #9
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    re!
    merci pour ta reponse!
    j'ai regardé les documentations et le pic 16F876 ne possède pas de convertisseur N/A, il ne possède qu'un convertisseur A/N. je suis donc obligé d'utiliser les sorties pwm. pour ce qui est de la regulation de courant du L6203, je ne pense pas utiliser le pic, pour ne pas surcharger le code. un aop en comparateur peut-il convenir?.
    existe-il des types de données plus petites que les "signed int"? mes valeurs sont entières et comprises entre -16 et 16, je n'ai pas besoin de 16 bit pour les coder...
    je peux déjas les mêtre en int clasique... mais y-a-t-il plus petit?
    merci d'avance!
    Salutations
    Olivier

  13. #10
    FantomX

    Re : amelioration code PIC 16F876 moteur pas à pas

    Le type signed char ne prend que 8 bits. Que veux-tu faire avec le comparateur ?

  14. #11
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    merci!
    à la pin "sense" du pont en H (L6203) il y a une tension qui est proportionelle à l'intensitée qu'il y a en sortie (avec une resistance de puissance de 0.5 ohm, 1v<=>2A) donc si avec le pic j'arrive fournir une tension de la même échelle (1V<=>2A) et en comparant ces 2 tensions, si V(sense)< V (pwm) alors le comparateur active le L6203 pas l'enable. mais il faut que le comparateur est une frecquence legerement en desous des 100KHz...

    pour le code du pic, je vien de le resimuler, et j'arrive à 10KHZ en entrée horloge. le seul soucis à cette frecquence c'est le signal de sortie, j'au un peu de mal à calibrer le filtre. il faudrais que j'augmente la periode du signal pwm, mais même avec le lien qui tu m'a donnée, j'ai un peu de mal...
    dans le logiciel PICC il y a un exemple de pwm:

    Code:
    /////////////////////////////////////////////////////////////////////////
    ////                           EX_PWM.C                              ////
    ////                                                                 ////
    ////  This program will show how to use the built in PIC PWM.        ////
    ////  The program takes an analog input and uses the digital         ////
    ////  value to set the duty cycle.  The frequency is set by          ////
    ////  the user over the RS-232.                                      ////
    ////                                                                 ////
    ////  Configure the CCS prototype card as follows:                   ////
    ////      Connect a scope to pin 3 (C2)                              ////
    ////      Connect 9 to 15 (pot)                                      ////
    ////      See additional connections below.                          ////
    ////                                                                 ////
    ////  This example will work with the PCM and PCH compilers.  The    ////
    ////  following conditional compilation lines are used to include a  ////
    ////  valid device for each compiler.  Change the device, clock and  ////
    ////  RS232 pins for your hardware if needed.                        ////
    /////////////////////////////////////////////////////////////////////////
    ////        (C) Copyright 1996,2001 Custom Computer Services         ////
    //// This source code may only be used by licensed users of the CCS  ////
    //// C compiler.  This source code may only be distributed to other  ////
    //// licensed users of the CCS C compiler.  No other use,            ////
    //// reproduction or distribution is permitted without written       ////
    //// permission.  Derivative programs created using this software    ////
    //// in object code form are not restricted in any way.              ////
    /////////////////////////////////////////////////////////////////////////
    
    
    #if defined(__PCM__)
    #include <16c74.h>
    #fuses HS,NOWDT,NOPROTECT
    #use delay(clock=10000000)
    #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)  // Jumpers: 8 to 11, 7 to 12
    
    #elif defined(__PCH__)
    #include <18c452.h>
    #fuses HS,NOPROTECT
    #use delay(clock=10000000)
    #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)  // Jumpers: 8 to 11, 7 to 12
    #endif
    
    
    main() {
       char selection;
       byte value;
    
    
       printf("\r\nFrequency:\r\n");
       printf("    1) 19.5 khz\r\n");
       printf("    2) 4.9 khz\r\n");
       printf("    3) 1.2 khz\r\n");
    
       do {
         selection=getc();
       } while((selection<'1')||(selection>'3'));
    
    
       setup_ccp1(CCP_PWM);   // Configure CCP1 as a PWM
    
              //   The cycle time will be (1/clock)*4*t2div*(period+1)
    	       //   In this program clock=10000000 and period=127 (below)
              //   For the three possible selections the cycle time is:
    		    //     (1/10000000)*4*1*128 =  51.2 us or 19.5 khz
    		    //     (1/10000000)*4*4*128 = 204.8 us or 4.9 khz
    		    //     (1/10000000)*4*16*128= 819.2 us or 1.2 khz
    
       switch(selection) {
         case '1' : setup_timer_2(T2_DIV_BY_1, 127, 1);
                    break;
         case '2' : setup_timer_2(T2_DIV_BY_4, 127, 1);
                    break;
         case '3' : setup_timer_2(T2_DIV_BY_16, 127, 1);
                    break;
       }
    
    
    
      setup_port_a(ALL_ANALOG);
      setup_adc(adc_clock_internal);
      set_adc_channel( 0 );
      printf("%c\r\n",selection);
    
      while( TRUE ) {
        value=read_adc();
    
        printf("%2X\r",value);
    
        set_pwm1_duty(value);          // This sets the time the pulse is
                                       // high each cycle.  We use the A/D
                                       // input to make a easy demo.
                                       // the high time will be:
                                       //  if value is LONG INT:
                                       //    value*(1/clock)*t2div
                                       //  if value is INT:
                                       //    value*4*(1/clock)*t2div
                                       // for example a value of 30 and t2div
                                       // of 1 the high time is 12us
                                       // WARNING:  A value to high or low will
                                       //           prevent the output from
                                       //           changing.
      }
    
    }

    je ne voi pas bien ce que represente le "T2_DIV_BY_1"...?
    je suis à 20µs en periode du pwm. soit 50KHz j'aimerrais arriver à 100Khz si possible...

    merci d'avance!
    Dernière modification par gienas ; 16/07/2008 à 14h18. Motif: Ajouté les balises code

  15. #12
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    j'ai oublié de dire que le signal de sorti n'est pas propre lors de basse frecquences d'horloge, cela est due qu signal pwm qui s'est pas régulier, là où il devrais l'être... à quoi cela peut-il être du et comment y remédier?

    merci d'avance!
    Salutations
    Olivier

    Bonjour olver62 et tout le groupe

    Les règles des PJ, déconseillent l'usage du pdf pour les images.

    http://forums.futura-sciences.com/thread163927.html

    Merci de poster à nouveau, avec une extension spécifique aux images.
    Dernière modification par gienas ; 16/07/2008 à 14h17. Motif: Supprimé images en pdf

  16. Publicité
  17. #13
    FantomX

    Re : amelioration code PIC 16F876 moteur pas à pas

    Le T2_DIV correspond au prédiviseur du timer 2 qui est la base de la génération de la fréquence de la PWM. Tu trouveras dans la datasheet du PIC dans la rubrique du timer 2 ou du mode CCP la formule pour calculer la valeur à mettre dans le registre PR2 pour calibrer ta PWM. J'ai le détail chez moi. Je pourrais mieux t'expliquer ça ce soir.

    Effectivement tu peux utiliser un LM311 pour comparer tes tensions. Il faut voir s'il répond assez vite.

  18. #14
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    voila les 2 courbes: les 2 premières sont les signaux de sortie , la 3 ème est l'horloge, la dernière est le signal pwm de la courbe 1.

    merci d'avance
    Salutations
    Olivier
    Images attachées Images attachées

  19. #15
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    bonsoir! je n'ai pas encore réussi à regler le problème de la pwm qui bug par moment. je n'arrive pas nonplus à augmenter sa frequence au dela de 50KHz.

    par contre, le core du pic c'est bien alléger et je peux monter à 10Khz , le code arrive à suivre, mais pas le pwm...

    Salutations
    Olivier

  20. #16
    invite03481543

    Re : amelioration code PIC 16F876 moteur pas à pas

    Bonsoir,

    tu devrais essayer d'utiliser les interruptions pour faire ton PWM, sans quoi tu seras toujours limité par la durée de ta boucle principale.

    Le principe est de fixer une période PR2 et d'utiliser le mode Compare (CCP2) pour caler la durée du rapport cyclique.
    Lorsque CCP2IF est détecté en interruption tu déclenches instantanément l'ordre de mettre à 0 la sortie correspondante en ayant configuré en conséquence les bits <CCP2M3:CCP2M0> dans le registre CCP2CON.

    Tu peux t'inspirer d'un projet que j'avais posté dans le forum "projets" avec des sources en C.
    Tu y trouveras un variateur PWM et un stroboscope qui utilisent ce mode de traitement en interruption.
    Le code source est largement commenté comme d'habitude.
    http://forums.futura-sciences.com/thread206163.html
    @+
    Dernière modification par HULK28 ; 16/07/2008 à 23h29.

  21. #17
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    slt!! merci beaucoup pour ta reponse! je suis en train d'essayer de comprendre le code que tu m'as donné!!
    je regraderrais ca ce midi!! je comprend à peu près comment il faut faire...
    merci @ vous deux! (FantomX et Hulk28!)

    Olivier

  22. #18
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    re! en lisant ton code, je me suis posé des questions et je n'ai pas de réponses à certaines... tu écris dans l'initialisation du pic:
    Cde_Led = 0; // RC2 positionné à 0
    mais comment le pic connait que la cde_Led est la pin RC2? je ne vois pas d'indication avant...
    je ne vois pas non plus où les ports sont definis en pwm...

    je sens que je vais aller voir des cours sur le pwm parce que ca me parrait compliqué...

    Salutations
    Olivier

  23. Publicité
  24. #19
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    dans les cours de Bigonoff, j'ai remarqué qu'il parle d'un "registre
    intermédiaire qui servira de valeur de comparaison, et qui sera chargé au moment du débordement de TMR2." mais je ne voi pas comment modifier ce registre... est-ce que c'est CCPRxL? ("Le nombre entier sera inscrit dans le registre CCPRxL. Les 2 bits fractionnaires qui
    complètent ce nombre sont les bits CCPxX et CCPxY du registre CCPxCON.")
    (je suis avec le pic 16F876 pwm sur 10 bit).
    j'ai aussi trouvé ca dans la datasheet:
    "SET-UP FOR PWM OPERATION
    The following steps should be taken when configuring
    the CCP module for PWM operation:
    1. Set the PWM period by writing to the PR2 register.
    2. Set the PWM duty cycle by writing to the
    CCPR1L register and CCP1CON<5:4> bits.
    3. Make the CCP1 pin an output by clearing the
    TRISC<2> bit.
    4. Set the TMR2 prescale value and enable Timer2
    by writing to T2CON.
    5. Configure the CCP1 module for PWM operation."
    est-ce que l'on peux directement changer la valeur des registres en Language C avec le compilateur PICC? de toute façon je vais essayer...

    merci d'avance
    salutations
    Olivier

  25. #20
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    pour la frequence du pwm c'est réglé!
    mais il y a encore quelques bug... j'arrive pas à les éliminer. de temps en temps le pwm reste à l'état haut pendant 7 µs avant de partir normalement, ce qui crée des pic en sortie. à voir, cela arrive regulièrement, les pulsations ne sont pas périodiques, mais des motifs de pic sont visible.
    HULK28, tu parlais:
    "Le principe est de fixer une période PR2 et d'utiliser le mode Compare (CCP2) pour caler la durée du rapport cyclique.
    Lorsque CCP2IF est détecté en interruption tu déclenches instantanément l'ordre de mettre à 0 la sortie correspondante en ayant configuré en conséquence les bits <CCP2M3:CCP2M0> dans le registre CCP2CON."

    dans la datasheet du pic j'ai trouvé:
    " bit 7-6: Unimplemented: Read as ’0’
    bit 5-4: CCPxX:CCPxY: PWM Least Significant bits
    Capture Mode: Unused
    Compare Mode: Unused
    PWM Mode: These bits are the two LSbs of the PWM duty cycle.The eight MSbs are found in CCPRxL.
    bit 3-0: CCPxM3:CCPxM0: CCPx Mode Select bits
    0000 = Capture/Compare/PWM off (resets CCPx module)
    0100 = Capture mode, every falling edge
    0101 = Capture mode, every rising edge
    0110 = Capture mode, every 4th rising edge
    0111 = Capture mode, every 16th rising edge
    1000 = Compare mode, set output on match (CCPxIF bit is set)
    1001 = Compare mode, clear output on match (CCPxIF bit is set)
    1010 = Compare mode, generate software interrupt on match (CCPxIF bit is set, CCPx pin is unaffected)
    1011 = Compare mode, trigger special event (CCPxIF bit is set, CCPx pin is unaffected); CCP1 resets
    TMR1; CCP2 resets TMR1 and starts an A/D conversion (if A/D module is enabled)
    11xx = PWM mode"

    dans mon code, le CCPxCON est en mode pwm... faut il changer de mode?
    merci de m'éclairer, c'est la premièrefoi que je programme un pic, et je n'ai aucune connaissance en C... votre aide m'est donc très précieuse.

    merci d'avance
    Salutations
    Olivier

  26. #21
    invite03481543

    Re : amelioration code PIC 16F876 moteur pas à pas

    Citation Envoyé par olver62 Voir le message
    dans les cours de Bigonoff, j'ai remarqué qu'il parle d'un "registre
    intermédiaire qui servira de valeur de comparaison, et qui sera chargé au moment du débordement de TMR2." mais je ne voi pas comment modifier ce registre... est-ce que c'est CCPRxL? ("Le nombre entier sera inscrit dans le registre CCPRxL. Les 2 bits fractionnaires qui
    complètent ce nombre sont les bits CCPxX et CCPxY du registre CCPxCON.")
    Oui c'est ça.

    (je suis avec le pic 16F876 pwm sur 10 bit).
    j'ai aussi trouvé ca dans la datasheet:
    "SET-UP FOR PWM OPERATION
    The following steps should be taken when configuring
    the CCP module for PWM operation:
    1. Set the PWM period by writing to the PR2 register.
    2. Set the PWM duty cycle by writing to the
    CCPR1L register and CCP1CON<5:4> bits.
    3. Make the CCP1 pin an output by clearing the
    TRISC<2> bit.
    4. Set the TMR2 prescale value and enable Timer2
    by writing to T2CON.
    5. Configure the CCP1 module for PWM operation."
    est-ce que l'on peux directement changer la valeur des registres en Language C avec le compilateur PICC? de toute façon je vais essayer...
    Bien sur, c'est même plus direct qu'en assembleur:

    CCPR1L=0x3F;

    Il faut faire une distinction entre le mode PWM et le mode Compare.
    Dans le mode PWM, les registres CCPx sont restaurés automatiquement par le µC au débordement du Timer et la sortie commandée ne peut être que RCx.

    En mode Compare, tu as plus de liberté, tu peux affecter la sortie de ton choix et décider du type d'évènement TMRxIF ou CCPxIF.

    Par exemple si tu veux faire varier une fréquence ET son rapport cyclique en même temps, seul le mode Compare le permet.

  27. #22
    invite03481543

    Re : amelioration code PIC 16F876 moteur pas à pas

    Citation Envoyé par olver62 Voir le message
    pour la frequence du pwm c'est réglé!
    mais il y a encore quelques bug... j'arrive pas à les éliminer. de temps en temps le pwm reste à l'état haut pendant 7 µs avant de partir normalement, ce qui crée des pic en sortie. à voir, cela arrive regulièrement, les pulsations ne sont pas périodiques, mais des motifs de pic sont visible.
    Je pense que ton problème est lié à la gestion des interruptions.
    Pour cela il faudrait que je vois ton code.
    Si tu utilises des variables dans l'interruption et dans ton main() il faut veiller à ce qu'elles soient de type "volatile".

    HULK28, tu parlais:
    "Le principe est de fixer une période PR2 et d'utiliser le mode Compare (CCP2) pour caler la durée du rapport cyclique.
    Lorsque CCP2IF est détecté en interruption tu déclenches instantanément l'ordre de mettre à 0 la sortie correspondante en ayant configuré en conséquence les bits <CCP2M3:CCP2M0> dans le registre CCP2CON."

    dans la datasheet du pic j'ai trouvé:
    " bit 7-6: Unimplemented: Read as ’0’
    bit 5-4: CCPxX:CCPxY: PWM Least Significant bits
    Capture Mode: Unused
    Compare Mode: Unused
    PWM Mode: These bits are the two LSbs of the PWM duty cycle.The eight MSbs are found in CCPRxL.
    bit 3-0: CCPxM3:CCPxM0: CCPx Mode Select bits
    0000 = Capture/Compare/PWM off (resets CCPx module)
    0100 = Capture mode, every falling edge
    0101 = Capture mode, every rising edge
    0110 = Capture mode, every 4th rising edge
    0111 = Capture mode, every 16th rising edge
    1000 = Compare mode, set output on match (CCPxIF bit is set)
    1001 = Compare mode, clear output on match (CCPxIF bit is set)
    1010 = Compare mode, generate software interrupt on match (CCPxIF bit is set, CCPx pin is unaffected)
    1011 = Compare mode, trigger special event (CCPxIF bit is set, CCPx pin is unaffected); CCP1 resets
    TMR1; CCP2 resets TMR1 and starts an A/D conversion (if A/D module is enabled)
    11xx = PWM mode"

    dans mon code, le CCPxCON est en mode pwm... faut il changer de mode?
    merci de m'éclairer, c'est la premièrefoi que je programme un pic, et je n'ai aucune connaissance en C... votre aide m'est donc très précieuse.

    merci d'avance
    Salutations
    Olivier
    Si tu utilises le mode PWM donc 11xx dans CCPxCON, tu n'as besoin que de détecter TMRxIF et tu recharges le registre CCPxL et CCPxH avec les nouvelles valeurs du rapport cyclique.
    Regarde comment j'ai fais dans la rubrique "projets", le code y est commenté.
    En mode variateur je modifie le rapport cyclique.
    En mode stroboscope je modifie la période.
    @+

  28. #23
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    bonjour, merci pour ces reponses! ca m'éclaire beaucoup!
    j'ai cependant un problème de code... voici ce que j'ai écrit:

    #include <16F876a.h>
    #fuses HS, NOPROTECT, NOWDT
    #use delay(clock=20000000)
    #include <math.h>
    #include <stdlib.h>
    #define NUM_LENGTH 8
    #define GIE INTCON.F7
    #define PEIE INTCON.F6
    #define CCP1IE PIE1.F2
    #define TMR1IE PIE1.F0
    #define TMR1ON T1CON.F0
    #define TMR1IF PIR1.F0
    #define CCP1IF PIR1.F2
    // pin RB (0..4) interupteur rotatif pour choix de la precision


    /********************** Déclaration des variables *****************************/

    int Ip1, Ip2, I1, I2, duty1, duty2; // variable liées aux interruptions, intensité, déclarées en volatile
    signed int IB1n,IB2n, IB1m, IB2m, deltaI, lastdeltaI, lastsens, sens, lastclock, clock, ok1, ok2, Iref;


    /********************** Déclaration des prototypes de fonctions ***************/
    void detection_clock_sens(void);
    void init_pic();
    void config_rapport_cyclique1(int duty1);
    void config_rapport_cyclique2(int duty2);
    void init_precision(void);
    void absolue(void);
    /************************ Initialisation du PIC ****************************** */

    void init_pic()
    {
    setup_ccp1(CCP_PWM);
    setup_ccp2(CCP_PWM);
    setup_timer_2(T2_DIV_BY_1, 31, 1);
    }

    /*********************** Initialisation des variables *************************/

    void init_var()
    {
    lastsens=1;
    lastclock=0;
    IB1n = 0;
    IB2n = 16;
    IB1m = -16;
    IB2m = 0;
    PEIE = 1;
    TMR2IE = 1;
    GIE = 1; // on réactive les interruptions
    // pour un nouveau cycle
    }
    /********************** initialisation precision********************* **********/

    void init_precision()
    {
    if (INPUT(PIN_B0)) //definition du mode (pas entier, demi pas....)
    deltaI = 16;
    if (INPUT(PIN_B1))
    deltaI = 8;
    if (INPUT(PIN_B2))
    deltaI = 4;
    if (INPUT(PIN_B3))
    deltaI = 2;
    if (INPUT(PIN_B4))
    deltaI = 1;
    }

    /********************** Programme principal ****************************** *****/

    void main()
    {
    init_pic(); // mise en situation du PIC
    init_var(); // initialisation des variables
    init_precision(); // initialisation precision

    while(1) // le programme tourne dans cette boucle infinie
    {
    detection_clock_sens(); // gestion des appuis sur les B.P.
    absolue();

    if (Ip1!=I1)
    { config_rapport_cyclique1(Ip1); I1=Ip1;}
    if (Ip2!=I2)
    { config_rapport_cyclique2(Ip2); I2=Ip2;}


    }
    }

    /************************ Fonction de détection des clock et sens *************/

    void detection_clock_sens()
    {
    clock= INPUT(PIN_B5);

    if (clock && (clock!=lastclock)) //avance d'un pas
    {
    if (IB1m < IB1n)
    {if ((IB1n + deltaI)<= 16)
    {IB1m = IB1n ; IB1n = (IB1n + deltaI);}
    else { IB1m = IB1n ; IB1n= (IB1n - deltaI);}}

    else {if ((IB1n - deltaI)>= -16)
    {IB1m = IB1n ; IB1n = (IB1n - deltaI);}
    else { IB1m = IB1n ; IB1n= (IB1n + deltaI);}};

    if (IB2m < IB2n)
    {if ((IB2n + deltaI)<= 16)
    {IB2m = IB2n ; IB2n = (IB2n + deltaI);}
    else { IB2m = IB2n ; IB2n = (IB2n - deltaI);};}

    else
    {if ((IB2n - deltaI)>= -16)
    {IB2m = IB2n ; IB2n = (IB2n - deltaI);}
    else { IB2m = IB2n ; IB2n = (IB2n + deltaI);}}; //calcul du pourcentage d'intensité dans chacque bobine (de -16 à 16)
    }
    lastclock=clock;

    sens= INPUT(PIN_B6);
    if (sens!=lastsens)
    {IB1m = (IB1n + (IB1n - IB1m)) ; IB2m = (IB2n + (IB2n - IB2m)) ; lastsens = sens;}; //changement de sens

    }

    /************************ prend la valeur absolue des intensités***************/
    void absolue()
    {
    if(IB1n < 0)
    Ip1=-IB1n; else Ip1=IB1n;

    if(IB2n < 0)
    Ip2=-IB2n; else Ip2=IB2n;
    }


    /**************************conf iguration rapport cyclique**********************/


    void config_rapport_cyclique1(duty1 )
    {
    if (TMR1IF == 1)
    {
    GIE=0;
    TMR1IE=0; // on désactive les interruptions pour raffraichir les contenus des registres
    CCP1CON<5:4> = duty1; // les 2 bits "décimaux" sont stockés dans CCp1con
    CCPR1L = (duty1)>>2; // les 8 bits hauts sont stockés dans CCPR1L
    GIE=1; // on réactive les interruptions
    TMR2IE=1; // pour un nouveau cycle
    }
    }
    void config_rapport_cyclique2(duty2 )
    {
    if (TMR2IF == 1)
    {
    GIE=0;
    TMR2IE=0; // on désactive les interruptions pour raffraichir les contenus des registres
    CCP2CON<5:4> = duty2; // les 2 bits "décimaux" sont stockés dans CCC2con
    CCPR2L = (duty2)>>2; // les 8 bits hauts sont stockés dans CCPR1L
    GIE=1; // on réactive les interruptions
    TMR2IE=1; // pour un nouveau cycle
    }
    }


    /****************************** ****************************** ******************/

    mais lorsque je compile, il me dit "expecting a structure/union INTERCON"
    et surligne "PEIE = 1;" dans init_var.
    je ne sais pas ce qu'il y a de mal écrit. si quelqu'un peut m'indiquer ce qui cloche... merci d'avance!

    Salutations
    Olivier

  29. #24
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    j'ai réussi à activer ou desactiver les interuptions! pour le compilateur il fallait que j'écrive:
    "enable_interrupts(INT_COM P);
    enable_interrupts(GLOBAL); "
    et disable...

    pour charger les registres CCPR1L, CCPR2L et les bits décimaux, je n'ai toujours rien trouvé pour remplacer "set_pwm1_duty(duty1);" ou "set_pwm2_duty(duty2);"
    mais au moins, le compilateur arrive à compiler...
    cependant je n'arrive pas à detecter le TMRxIF, pour modifier les registres à ce moment la...
    si quelqu'un sait comment faire, merci!
    je continue de chercher...
    Salutations
    Olivier

  30. Publicité
  31. #25
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    Bonjour, après pas mal de recherche, je n'arrive toujours pas à detecter TMR2IF! voila mon code:

    #include <16F876a.h>
    #fuses HS, NOPROTECT, NOWDT
    #use delay(clock=20000000)
    #include <math.h>
    #include <stdlib.h>
    #define NUM_LENGTH 8
    #define GIE INTCON.F7
    #define PEIE INTCON.F6
    #define CCP1IE PIE1.F2
    #define TMR1IE PIE1.F0
    #define TMR1ON T1CON.F0
    #define TMR2IF PIR1.F1
    #define CCP1IF PIR1.F2
    // pin RB (0..4) interupteur rotatif pour choix de la precision


    /********************** Déclaration des variables *****************************/

    int Ip1, Ip2, I1, I2, duty1, duty2; // variable liées aux interruptions, intensité, déclarées en volatile
    signed int IB1n,IB2n, IB1m, IB2m, deltaI, lastdeltaI, lastsens, sens, lastclock, clock, ok1, ok2, Iref;


    /********************** Déclaration des prototypes de fonctions ***************/
    void detection_clock_sens(void);
    void init_pic();
    void config_rapport_cyclique(int duty1, duty2);
    void init_precision(void);
    void absolue(void);
    void orientation_courants(void);
    /************************ Initialisation du PIC ****************************** */

    void init_pic()
    {
    setup_ccp1(CCP_PWM);
    setup_ccp2(CCP_PWM);
    setup_timer_2(T2_DIV_BY_1, 20, 1);
    }

    /*********************** Initialisation des variables *************************/

    void init_var()
    {
    lastsens=1;
    lastclock=0;
    IB1n = 0;
    IB2n = 16;
    IB1m = -16;
    IB2m = 0;
    enable_interrupts(INT_COMP);
    enable_interrupts(GLOBAL);


    }
    /********************** initialisation precision********************* **********/

    void init_precision()
    {
    if (INPUT(PIN_B0)) //definition du mode (pas entier, demi pas....)
    deltaI = 16;
    if (INPUT(PIN_B1))
    deltaI = 8;
    if (INPUT(PIN_B2))
    deltaI = 4;
    if (INPUT(PIN_B3))
    deltaI = 2;
    if (INPUT(PIN_B4))
    deltaI = 1;
    }

    /********************** Programme principal ****************************** *****/

    void main()
    {
    init_pic(); // mise en situation du PIC
    init_var(); // initialisation des variables
    init_precision(); // initialisation precision

    while(1) // le programme tourne dans cette boucle infinie
    {
    IF (INPUT(pin_B7)==0)
    { init_var(); init_precision();};// reset

    detection_clock_sens(); // gestion des appuis sur les B.P.
    absolue();
    orientation_courants();

    if (Ip1!=I1)
    { config_rapport_cyclique(Ip1, Ip2); I1=Ip1;}



    }
    }

    /************************ Fonction de détection des clock et sens *************/

    void detection_clock_sens()
    {
    clock= INPUT(PIN_B5);

    if (clock && (clock!=lastclock)) //avance d'un pas
    {
    if (IB1m < IB1n)
    {if ((IB1n + deltaI)<= 16)
    {IB1m = IB1n ; IB1n = (IB1n + deltaI);}
    else { IB1m = IB1n ; IB1n= (IB1n - deltaI);}}

    else {if ((IB1n - deltaI)>= -16)
    {IB1m = IB1n ; IB1n = (IB1n - deltaI);}
    else { IB1m = IB1n ; IB1n= (IB1n + deltaI);}};

    if (IB2m < IB2n)
    {if ((IB2n + deltaI)<= 16)
    {IB2m = IB2n ; IB2n = (IB2n + deltaI);}
    else { IB2m = IB2n ; IB2n = (IB2n - deltaI);};}

    else
    {if ((IB2n - deltaI)>= -16)
    {IB2m = IB2n ; IB2n = (IB2n - deltaI);}
    else { IB2m = IB2n ; IB2n = (IB2n + deltaI);}}; //calcul du pourcentage d'intensité dans chacque bobine (de -16 à 16)
    }
    lastclock=clock;

    sens= INPUT(PIN_B6);
    if (sens!=lastsens)
    {IB1m = (IB1n + (IB1n - IB1m)) ; IB2m = (IB2n + (IB2n - IB2m)) ; lastsens = sens;}; //changement de sens

    }
    /************************ orientation courrant********************** ***********/
    void orientation_courants()
    {
    if (IB1n > 0)
    {Output_bit(PIN_C4,0); Output_bit(PIN_C3,1);};
    if (IB1n < 0)
    {Output_bit(PIN_C3,0); Output_bit(PIN_C4,1);};
    if (IB1n == 0)
    {Output_bit(PIN_C3,0); Output_bit(PIN_C4,0);};
    if (IB2n > 0)
    {Output_bit(PIN_C5,0); Output_bit(PIN_C5,1);};
    if (IB2n < 0)
    {Output_bit(PIN_C5,0); Output_bit(PIN_C6,1);}; //orientation des courants
    if (IB2n == 0)
    {Output_bit(PIN_C5,0); Output_bit(PIN_C6,0);};
    }


    /************************ prend la valeur absolue des intensités***************/
    void absolue()
    {
    if(IB1n < 0)
    Ip1=-IB1n; else Ip1=IB1n;

    if(IB2n < 0)
    Ip2=-IB2n; else Ip2=IB2n;
    }


    /**************************conf iguration rapport cyclique**********************/


    void config_rapport_cyclique(duty1, duty2)
    {
    while (TMR2IF==1);

    disable_interrupts(GLOBAL);
    disable_interrupts(INT_COMP);

    // on désactive les interruptions pour raffraichir les contenus des registres
    set_pwm1_duty(duty1);
    set_pwm2_duty(duty2);
    enable_interrupts(INT_COMP);
    enable_interrupts(GLOBAL); // on réactive les interruptions
    // pour un nouveau cycle
    }


    /****************************** ****************************** ******************/
    j'ai déniché dans les fichiers système du logiciel, le fichier 16F876A.h :

    //////// Standard Header file for the PIC16F876A device ////////////////
    #device PIC16F876A
    #nolist
    //////// Program memory: 8192x14 Data RAM: 367 Stack: 8
    //////// I/O: 22 Analog Pins: 5
    //////// Data EEPROM: 256
    //////// C Scratch area: 77 ID Location: 2000
    //////// Fuses: LP,XT,HS,RC,NOWDT,WDT,NOPUT,PU T,PROTECT,PROTECT_5%
    //////// Fuses: PROTECT_50%,NOPROTECT,NOBROWNO UT,BROWNOUT,LVP,NOLVP,CPD
    //////// Fuses: NOCPD,WRT,NOWRT
    ////////
    ////////////////////////////////////////////////////////////////// I/O
    // Discrete I/O Functions: SET_TRIS_x(), OUTPUT_x(), INPUT_x(),
    // PORT_B_PULLUPS(), INPUT(),
    // OUTPUT_LOW(), OUTPUT_HIGH(),
    // OUTPUT_FLOAT(), OUTPUT_BIT()
    // Constants used to identify pins in the above are:

    #define PIN_A0 40
    #define PIN_A1 41
    #define PIN_A2 42
    #define PIN_A3 43
    #define PIN_A4 44
    #define PIN_A5 45

    #define PIN_B0 48
    #define PIN_B1 49
    #define PIN_B2 50
    #define PIN_B3 51
    #define PIN_B4 52
    #define PIN_B5 53
    #define PIN_B6 54
    #define PIN_B7 55

    #define PIN_C0 56
    #define PIN_C1 57
    #define PIN_C2 58
    #define PIN_C3 59
    #define PIN_C4 60
    #define PIN_C5 61
    #define PIN_C6 62
    #define PIN_C7 63

    ////////////////////////////////////////////////////////////////// Useful defines
    #define FALSE 0
    #define TRUE 1

    #define BYTE int
    #define BOOLEAN short int

    #define getc getch
    #define fgetc getch
    #define getchar getch
    #define putc putchar
    #define fputc putchar
    #define fgets gets
    #define fputs puts

    ////////////////////////////////////////////////////////////////// Control
    // Control Functions: RESET_CPU(), SLEEP(), RESTART_CAUSE()
    // Constants returned from RESTART_CAUSE() are:
    #define WDT_FROM_SLEEP 0
    #define WDT_TIMEOUT 8
    #define MCLR_FROM_SLEEP 16
    #define NORMAL_POWER_UP 24


    ////////////////////////////////////////////////////////////////// Timer 0
    // Timer 0 (AKA RTCC)Functions: SETUP_COUNTERS() or SETUP_TIMER0(),
    // SET_TIMER0() or SET_RTCC(),
    // GET_TIMER0() or GET_RTCC()
    // Constants used for SETUP_TIMER0() are:
    #define RTCC_INTERNAL 0
    #define RTCC_EXT_L_TO_H 32
    #define RTCC_EXT_H_TO_L 48

    #define RTCC_DIV_1 8
    #define RTCC_DIV_2 0
    #define RTCC_DIV_4 1
    #define RTCC_DIV_8 2
    #define RTCC_DIV_16 3
    #define RTCC_DIV_32 4
    #define RTCC_DIV_64 5
    #define RTCC_DIV_128 6
    #define RTCC_DIV_256 7


    #define RTCC_8_BIT 0

    // Constants used for SETUP_COUNTERS() are the above
    // constants for the 1st param and the following for
    // the 2nd param:

    ////////////////////////////////////////////////////////////////// WDT
    // Watch Dog Timer Functions: SETUP_WDT() or SETUP_COUNTERS() (see above)
    // RESTART_WDT()
    //
    #define WDT_18MS 8
    #define WDT_36MS 9
    #define WDT_72MS 10
    #define WDT_144MS 11
    #define WDT_288MS 12
    #define WDT_576MS 13
    #define WDT_1152MS 14
    #define WDT_2304MS 15

    ////////////////////////////////////////////////////////////////// Timer 1
    // Timer 1 Functions: SETUP_TIMER_1, GET_TIMER1, SET_TIMER1
    // Constants used for SETUP_TIMER_1() are:
    // (or (via |) together constants from each group)
    #define T1_DISABLED 0
    #define T1_INTERNAL 0x85
    #define T1_EXTERNAL 0x87
    #define T1_EXTERNAL_SYNC 0x83

    #define T1_CLK_OUT 8

    #define T1_DIV_BY_1 0
    #define T1_DIV_BY_2 0x10
    #define T1_DIV_BY_4 0x20
    #define T1_DIV_BY_8 0x30

    ////////////////////////////////////////////////////////////////// Timer 2
    // Timer 2 Functions: SETUP_TIMER_2, GET_TIMER2, SET_TIMER2
    // Constants used for SETUP_TIMER_2() are:
    #define T2_DISABLED 0
    #define T2_DIV_BY_1 4
    #define T2_DIV_BY_4 5
    #define T2_DIV_BY_16 6

    ////////////////////////////////////////////////////////////////// CCP
    // CCP Functions: SETUP_CCPx, SET_PWMx_DUTY
    // CCP Variables: CCP_x, CCP_x_LOW, CCP_x_HIGH
    // Constants used for SETUP_CCPx() are:
    #define CCP_OFF 0
    #define CCP_CAPTURE_FE 4
    #define CCP_CAPTURE_RE 5
    #define CCP_CAPTURE_DIV_4 6
    #define CCP_CAPTURE_DIV_16 7
    #define CCP_COMPARE_SET_ON_MATCH 8
    #define CCP_COMPARE_CLR_ON_MATCH 9
    #define CCP_COMPARE_INT 0xA
    #define CCP_COMPARE_RESET_TIMER 0xB
    #define CCP_PWM 0xC
    #define CCP_PWM_PLUS_1 0x1c
    #define CCP_PWM_PLUS_2 0x2c
    #define CCP_PWM_PLUS_3 0x3c
    long CCP_1;
    #byte CCP_1 = 0x15
    #byte CCP_1_LOW= 0x15
    #byte CCP_1_HIGH= 0x16
    long CCP_2;
    #byte CCP_2 = 0x1B
    #byte CCP_2_LOW= 0x1B
    #byte CCP_2_HIGH= 0x1C
    ////////////////////////////////////////////////////////////////// SPI
    // SPI Functions: SETUP_SPI, SPI_WRITE, SPI_READ, SPI_DATA_IN
    // Constants used in SETUP_SSP() are:
    #define SPI_MASTER 0x20
    #define SPI_SLAVE 0x24
    #define SPI_L_TO_H 0
    #define SPI_H_TO_L 0x10
    #define SPI_CLK_DIV_4 0
    #define SPI_CLK_DIV_16 1
    #define SPI_CLK_DIV_64 2
    #define SPI_CLK_T2 3
    #define SPI_SS_DISABLED 1

    #define SPI_SAMPLE_AT_END 0x8000
    #define SPI_XMIT_L_TO_H 0x4000

    ////////////////////////////////////////////////////////////////// COMP
    // Comparator Variables: C1OUT, C2OUT
    // Constants used in setup_comparators() are:
    #define A0_A3_A1_A3 0xfff04
    #define A0_A3_A1_A2_OUT_ON_A4_A5 0xfcf03
    #define A0_A3_A1_A3_OUT_ON_A4_A5 0xbcf05
    #define NC_NC_NC_NC 0x0ff07
    #define A0_A3_A1_A2 0xfff02
    #define A0_A3_NC_NC_OUT_ON_A4 0x9ef01
    #define A0_VR_A1_VR 0x3ff06
    #define A3_VR_A2_VR 0xcff0e

    #bit C1OUT = 0x9c.6
    #bit C2OUT = 0x9c.7

    ////////////////////////////////////////////////////////////////// ADC
    // ADC Functions: SETUP_ADC(), SETUP_ADC_PORTS() (aka SETUP_PORT_A),
    // SET_ADC_CHANNEL(), READ_ADC()
    // Constants used in SETUP_ADC_PORTS() are:
    #define NO_ANALOGS 0x86 // None
    #define ALL_ANALOG 0x80 // A0 A1 A2 A3 A5 E0 E1 E2 Ref=Vdd
    #define ANALOG_RA3_REF 0x81 // A0 A1 A2 A5 E0 E1 E2 Ref=A3
    #define A_ANALOG 0x82 // A0 A1 A2 A3 A5 Ref=Vdd
    #define A_ANALOG_RA3_REF 0x83 // A0 A1 A2 A5 Ref=A3
    #define RA0_RA1_RA3_ANALOG 0x84 // A0 A1 A3 Ref=Vdd
    #define RA0_RA1_ANALOG_RA3_REF 0x85 // A0 A1 Ref=A3
    #define ANALOG_RA3_RA2_REF 0x88 // A0 A1 A5 E0 E1 E2 Ref=A2,A3
    #define ANALOG_NOT_RE1_RE2 0x89 // A0 A1 A2 A3 A5 E0 Ref=Vdd
    #define ANALOG_NOT_RE1_RE2_REF_RA3 0x8A // A0 A1 A2 A5 E0 Ref=A3
    #define ANALOG_NOT_RE1_RE2_REF_RA3_RA2 0x8B // A0 A1 A5 E0 Ref=A2,A3
    #define A_ANALOG_RA3_RA2_REF 0x8C // A0 A1 A5 Ref=A2,A3
    #define RA0_RA1_ANALOG_RA3_RA2_REF 0x8D // A0 A1 Ref=A2,A3
    #define RA0_ANALOG 0x8E // A0
    #define RA0_ANALOG_RA3_RA2_REF 0x8F // A0 Ref=A2,A3
    // Constants used for SETUP_ADC() are:
    #define ADC_OFF 0 // ADC Off
    #define ADC_CLOCK_DIV_2 1
    #define ADC_CLOCK_DIV_8 0x41
    #define ADC_CLOCK_DIV_32 0x81
    #define ADC_CLOCK_INTERNAL 0xc1 // Internal 2-6us

    // Constants used in READ_ADC() are:
    #define ADC_START_AND_READ 7 // This is the default if nothing is specified
    #define ADC_START_ONLY 1
    #define ADC_READ_ONLY 6

    ////////////////////////////////////////////////////////////////// INT
    // Interrupt Functions: ENABLE_INTERRUPTS(), DISABLE_INTERRUPTS(),
    // EXT_INT_EDGE()
    //
    // Constants used in EXT_INT_EDGE() are:
    #define L_TO_H 0x40
    #define H_TO_L 0
    // Constants used in ENABLE/DISABLE_INTERRUPTS() are:
    #define GLOBAL 0x0BC0
    #define INT_RTCC 0x0B20
    #define INT_RB 0x0B08
    #define INT_EXT 0x0B10
    #define INT_AD 0x8C40
    #define INT_TBE 0x8C10
    #define INT_RDA 0x8C20
    #define INT_TIMER1 0x8C01
    #define INT_TIMER2 0x8C02
    #define INT_CCP1 0x8C04
    #define INT_CCP2 0x8D01
    #define INT_SSP 0x8C08
    #define INT_BUSCOL 0x8D08
    #define INT_EEPROM 0x8D10
    #define INT_TIMER0 0x0B20
    #define INT_COMP 0x8D40

    #list


    j'ai cherché quelque chose la dedans mais j'ai rien trouvé... comme je suis débutant, c'est surement normal... si vous trouvez quelque chose...

    ca blocque toujours au niveau de "TMR2IF==1"

    le code fonctionne sans, mais mon signal de sortie n'est pas top... j'aimerrais avoir quelque chose de plus propre...

    Merci d'avance
    Salutations
    Olivier

  32. #26
    invite03481543

    Re : amelioration code PIC 16F876 moteur pas à pas

    void config_rapport_cyclique(duty1, duty2)
    {
    while (TMR2IF==1);
    disable_interrupts(GLOBAL);
    disable_interrupts(INT_COMP);

    // on désactive les interruptions pour raffraichir les contenus des registres
    set_pwm1_duty(duty1);
    set_pwm2_duty(duty2);
    enable_interrupts(INT_COMP);
    enable_interrupts(GLOBAL); // on réactive les interruptions
    // pour un nouveau cycle
    }

    C'est dans la routine d'interruption, lorsque TMR2IF=1, qu'il faut charger le rapport cyclique qui a été (éventuellement) modifié dans le prog principal.
    Lorsque l'interruption, provoquée par le débordement de Timer2 est détectée, elle est prioritaire sur le programme principal, donc elle charge le dernier duty stocké, puis le programme reprend la main pour un nouveau cycle, etc.

    Il ne faut donc pas détecter la condition TMR2IF=1 dans la fonction qui se charge de mettre à jour le rapport cyclique.

    Dans l'interruption il faut écrire simplement:

    (dans la routine d'interruption)

    Code:
    if(TMRxIF==1)
    {
    CCPRxL= dutyx_L;  // x: 1 ou 2 selon le module CCPx utilisé
    CCPRxH= dutyx_H;
    TMRxIF=0;
    }
    Puis il faut écrire:
    Code:
    void config_rapport_cyclique(int duty1)
    {
    GIE=0;
    duty1_L = duty1;       // les 8 bits bas sont stockés dans la variable duty_L
    duty1_H = duty1>>8;  // les 8 bits hauts sont stockés dans duty_H
    GIE=1;
    }
    
    void config_rapport_cyclique(int duty2)
    {
    GIE=0;
    duty2_L = duty2;       // les 8 bits bas sont stockés dans la variable duty_L
    duty2_H = duty2>>8;  // les 8 bits hauts sont stockés dans duty_H
    GIE=1;
    }
    Dernière modification par HULK28 ; 19/07/2008 à 15h10.

  33. #27
    invite03481543

    Re : amelioration code PIC 16F876 moteur pas à pas

    Il ne faut pas oublier également dans init_pic() de configurer TRISC1 et TRISC2 en sortie:

    TRISC1=0;
    TRISC2=0;

  34. #28
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    merci beaucoup pour ta reponse!!
    le pic 16F876A ayant un pwm de 10 bit, j'ai lu qu'il y avait 8 bits dans CCPRxL et les 2 autres bit "decimaux" dans CCPxX et CCPxY. qui sont les bits 4 et 5 du registre CCPxCON. (dans la datasheet)

    si j'ai bien compris, les registres sont à modifier lorsque TMR2IF==0?
    et ce code:
    if(TMRxIF==1)
    {
    CCPRxL= duty_L;
    CCPRxH= duty_H;
    TMRxIF=0;
    }
    est à introduire dans le main?

    je ne voi pas ce que represente "la routine d'interruption". désolé de mon ignorance...

    si c'est ca, merci beaucoup, ca me resoud un gros problème, mais je ne sais toujours pas comment faire pour que le compilateur prenne en compte le "if(TMR2IF==1)" à moins qu'il faille écrire "if(TMRxIF==1)"? en laissant le x??

    je vais essayer avec le "x"...
    j'espère que le changement de registre "manuel" fonctionnera...

    merci encore pour ton aide!

    Salutations
    Olivier

  35. #29
    olver62

    Re : amelioration code PIC 16F876 moteur pas à pas

    Je vien de tester et le "if(TMRxIF==1)" ne fonctionne pas alors que le "if(TMR2IF==1)", il me met "expecting a structure union PIR1" en surlignant le premier "=".

    j'essaye plusieur truc, mais rien à faire... si ca tombe je vais devoir changer de compilateur...?
    lequel utilises-tu, si c'est pas indiscret?

    Merci d'avance
    Salutations
    Olivier

  36. #30
    invite03481543

    Re : amelioration code PIC 16F876 moteur pas à pas

    Citation Envoyé par olver62 Voir le message
    si j'ai bien compris, les registres sont à modifier lorsque TMR2IF==0?
    et ce code:
    if(TMRxIF==1)
    {
    CCPRxL= duty_L;
    CCPRxH= duty_H;
    TMRxIF=0;
    }
    est à introduire dans le main?
    Pas dans le main(), la routine d'interruption est une fonction particulière.
    Les interruptions sont gérées par cette routine, c'est en quelque sorte un gestionnaire d'interruptions, cette fonction est prioritaire sur le reste du programme principal, selon les compilateurs est s'appelle différemment mais tous possède cette procédure.
    La procédure sauve dans la pile la dernière instruction en cours d'exécution et s'occupe de l'interruption qui vient de se manifester, une fois fait elle récupère la dernière instruction dans la pile et continue le travail avant que l'interruption ne se soit manifestée.
    Toutes les interruptions doivent être traitées dans cette routine spéciale dédiée.

    Par exemple avec HitechC:
    Code:
    /******************************************************************************
    		        Traitement des interruptions
    ******************************************************************************/
    void interrupt traite_int(void)
    {
    	if(TMR1IF)
    	{
    		TMR1IF = 0 ; 	 	
    		.........
    	}
    
    }
    avec CC5X
    Code:
    interrupt int_server(void)
    {
    int_save_registers
    sv_FSR=FSR;
    if (TMR2IF)                             // le timer 2 a généré une interruption
       {
       	TMR2IF=0;                       // RAZ du flag d'interruption
       	..........        
       }
    FSR=sv_FSR;
    int_restore_registers
    }
    si c'est ca, merci beaucoup, ca me resoud un gros problème, mais je ne sais toujours pas comment faire pour que le compilateur prenne en compte le "if(TMR2IF==1)" à moins qu'il faille écrire "if(TMRxIF==1)"? en laissant le x??

    je vais essayer avec le "x"...
    j'espère que le changement de registre "manuel" fonctionnera...
    Non, TMRxIF signifie simplement que x désigne soit 1 soit 2:

    TMR2IF ou TMR1IF, CCP1IF ou CCP2IF, etc... x indique un cas général que tu adaptes selon ce que tu décides de choisir comme Timer ou comme modele CCP.

    Pour finir la routine d'interruption peut s'écrire n'importe où dans le corps du programme, on l'écrit en général soit au début, soit tout à la fin (histoire de la retrouver plus facilement).
    Il n'est pas utile de la déclarer dans les prototypes des fonctions ni de l'appeler dans le reste du programme, puisqu'elle intervient automatiquement dès qu'un flag d'interruption est détecté, il faut juste la faire apparaitre comme une autre fonction quelque part dans le programme (si on a à se servir des interruptions bien sur, dans le cas contraire elle n'apparait pas du tout).
    Dernière modification par HULK28 ; 20/07/2008 à 05h43.

Page 1 sur 2 1 DernièreDernière

Discussions similaires

  1. Réponses: 25
    Dernier message: 02/03/2014, 15h52
  2. liaison PIC <-> moteur pas à pas
    Par elektronik-17 dans le forum Électronique
    Réponses: 2
    Dernier message: 26/03/2008, 11h45
  3. pilotage de moteur pas a pas par port parralelle sans lpt
    Par arno9173 dans le forum Électronique
    Réponses: 3
    Dernier message: 18/03/2008, 22h11
  4. séquence moteur pas à pas controlé par PIC
    Par tiamat dans le forum Électronique
    Réponses: 6
    Dernier message: 20/02/2008, 12h03
  5. Commande moteur pas-à-pas avec pic
    Par Mikaeltrigo dans le forum Électronique
    Réponses: 0
    Dernier message: 20/02/2008, 10h51
Découvrez nos comparatifs produits sur l'informatique et les technologies.