Répondre à la discussion
Affichage des résultats 1 à 4 sur 4

[Terminé] Stroboscope/Variateur à PIC pour Led



  1. #1
    HULK28

    [Terminé] Stroboscope/Variateur à PIC pour Led

    Salut,

    un petit cadeau pour ceux qui jouent avec les leds, se programme écrit en C vous permettra de réaliser un stroboscope ainsi qu'un variateur.
    Le programme tourne sur un PIC16F872 avec un quartz de 4MHz, mais il peut être porté sur un PIC plus petit, j'avais celui-là sous la main.
    Le code occupe 26% de ROM et 23% de RAM donc il reste de quoi faire.
    Le mode stroboscope permet de faire flasher une led dans une plage de 10Hz à 500Hz et le mode variateur est une mise en oeuvre du principe de PWM souvent évoqué sur le forum.
    J'ai conçu ce programme dans un but didactique comme à mon habitude, pour que les débutants puissent se rendre compte de la manière dont doit être construit un programme propre, je l'ai donc commenté avec précision et structuré pour qu'il puisse être porté sur différents compilateurs sans soucis de compatibilité.
    Habituellement je travaille avec le compilo de chez Hitech mais comme il est plutôt cher pour les amateurs j'ai testé le compilateur C de chez Mikroelektronika pour voir.

    Je n'utilise pas de macros fonctions ou de librairies spécifiques non publiques souvent opaques qui éludent la manière dont sont traités certaines fonctionalités propres au PIC, mais je dois reconnaitre que j'ai été agréablement surpris par cet outil plutôt convivial et facile à prendre en main.

    Tous les détails sont expliqués dans le programme.
    Il y a 4 boutons poussoirs: "+", "-", "Stroboscope", "Dimmer".
    Par défaut à la mise sous tension le système est en mode stroboscope, un appui relâché sur "Dimmer" permet de changer de mode et un appui permanent ou intermittent sur "+" ou "-" permet la variation PWM ou fréquentielle (selon le mode dans lequel on se trouve).
    Si vous souhaitez des évolutions de ce programme n'hésitez pas à faire des propositions.
    Je joins aussi le fichier Hex pour ceux qui veulent faire joujou tout de suite.
    @+

    Code:
    #include "Strob_dimmer_config.h"
    
    /********************** Déclaration des variables *****************************/
    
    volatile unsigned int tps_index, X;  // variable liées aux interruptions
                                         // déclarées en volatile
    unsigned char mode_strob, mode_dimmer, retour;
    unsigned int duty;
    
    /********************** Déclaration des prototypes de fonctions ***************/
    
    void detection_BP(void);
    void int_stop(void);
    void int_go(void);
    void init_pic();
    void config_dimmer();
    void config_strob();
    void config_rapport_cyclique(int duty);
    void init_compare(void);
    
    /************************ Initialisation du PIC *******************************/
    
    void init_pic()
    {
     TRISA = 0x09;        // PortA positionné en mode digital
     PORTA = 0;           // Sorties du PortA fixées à 0
     TRISB = 0b00001111;  // <RB0:RB3> dirigés en entrées, le reste en sorties
     PORTB = 0b11000000;  // <RB0:RB5> positionnés à 0
     TRISC = 0;           // PORTC dirigé en sortie
     Cde_Led = 0;             // RC2 positionné à 0
    }
    
    /*********************** Initialisation des variables *************************/
    
    void init_var()
    {
     retour = 0;  // on fixe le mode Stroboscopique par défaut
     duty = 1000;
     X = 15536;
     tps_index = X;
    }
    
    /********************** Programme principal ***********************************/
    
    void main()
    {
     init_pic();        // mise en situation du PIC
     init_var();        // initialisation des variables
     config_strob();    // configuration en mode stroboscopique par défaut
    
       while(1)         // le programme tourne dans cette boucle infinie
       {
       detection_BP();  // gestion des appuis sur les B.P.
       GIE=0;           // on désactive les interruptions
       TMR1IE=0;        // pour raffraichir les contenus des registres
       tps_index = X;   // par le nouveau contenu de tps_index
       GIE=1;           // on réactive les interruptions
       TMR1IE=1;        // pour un nouveau cycle
       }
    }
    
    /************************ Fonction de détection des B.P ***********************/
    
    void detection_BP(void)
    {
      if((Strob == 0) || (retour == 0))  // si mode stroboscopique demandé
        {
        while(Strob == 0);  // on attend le relâchement de la touche
        if(Up == 0)         // appui sur "+" détecté on augmente la fréquence
                            // des flashs
          {
          while(Up == 0);   // on attend le relâchement de la touche "+"
          if(X <= Xmax)     // si X inférieur à la valeur de butée max fréquence
            {
            X+=400;         // on incrémente X de 400 (pour un pas d'environ 1Hz)
            delay_ms(100);  // petite tempo
            }
          }
    
        if(Down == 0)       // appui sur "-" on diminue la fréquence des flashs
          {
          while(Down == 0)  // on attend le relâchement de la touche "-"
          if(X > 1000)
            {
            X-=400;         // on décrémente X de 400
            delay_ms(100);
            }
          }
          
        if(Dimmer == 0)         // mode variateur requis
          {
          while(Dimmer == 0);   // on attend le relâchement de la touche "-"
          config_dimmer();      // on reconfigure le mode variateur avant de quitter
                                // la boucle strob
          retour = 1;           // on positionne la variable de retour dans la
                                // boucle variateur
          }
        }
          
          
      if((Dimmer == 0) || (retour == 1))  // mode dimmer
          {
          while(Dimmer == 0);      // on attend le relâchement de la touche "dimmer"
          delay_ms(200);
          config_dimmer();         // on configure le mode variateur
        
          while(mode_dimmer == 1)  // tant que le mode variateur est actif on tourne
                                   // dans cette boucle
               {
               if((Up == 0) && (duty < 1900))   // si appui sur le B.P "+" et
                                                //duty max non atteint
                 {
                 while(Up == 0);                // on attend le relachement du B.P
                 delay_ms(200);
                 duty=duty+100;                 // on incrémente duty de 100
                 config_rapport_cyclique(duty); // on appelle la fonction permettant
                                                // de charger les registres CCPR1x
                 }
               
               if((Down == 0) && (duty > 100))  // si appui sur le B.P "-"
                 {
                 delay_ms(200);
                 duty=duty-100;                 // on décrémente duty de 100
                 config_rapport_cyclique(duty); // on appelle la fonction permettant
                                                // de charger les registres CCPR1x
                 }
                 
               if(Strob == 0)                   // mode stroboscopique demandé
                 {
                 while(Up == 0);                // on attend le relachement du B.P
    
                 config_strob();     // on reconfigure le mode stroboscopique
                                     // avant de retourner dans la boucle
                 retour = 0;           // on positionne la variable de retour dans la
                                     // boucle strob
                 }
               }
          }
      delay_ms(100);
    
    }
    
    /************* Fonction permettant d'initialiser le variateur *****************/
    
    void config_dimmer()
    {
     mode_strob = 0;    // mode strob interdit
     mode_dimmer = 1;   // mode variateur autorisé
     GIE = 1;           // autorisation des interruptions
     PEIE = 1;
     Cde_Led = 0;
     CCP1IE = 1;
     TMR1IE = 1;
     init_compare();    // variateur initialisé sur 50% de rapport cyclique
     TMR1ON = 1;        // Timer activé
    }
    
    /*********** Fonction permettant d'initialiser le stroboscope *****************/
    
    void config_strob()
    {
     mode_dimmer = 0;     // mode dimmer interdit
     mode_strob = 1;      // mode stroboscopique autorisé
     X = 15536;           // on  fixe la variable X pour avoir Fmin (10Hz)
     tps_index = X;       // on charge la variable X dans tps_index
     Cde_Led = 0;             // Sortie n°2 du PORTC positionné à 0
     GIE = 1;             // activation globale des interruptions
     PEIE = 1;            // activation des interruptions liées aux périphériques
     CCP1IE = 0;          // activation de l'interruption liée au module CCP1
     TMR1IE = 1;          // activation de l'interruption liée au Timer1
     TMR1ON = 1;          // Timer1 activé
    }
    
    /********** Fonction permettant d'initialiser la période de comptage **********/
    /*                  et de fixer le rapport cyclique initial                   */
    /*  Principe: Le timer1 est un timer 16 bits, en mode timer il compte de      */
    /*  0 à 65535 (si le prédiviseur est fixé à O), puis repasse à 0 ce qui       */
    /*  déclenche une interruption (TMR1IF).                                      */
    /*  On charge dans <TMR1H:TMR1L> la valeur requise pour débuter le comptage   */
    /*  Ex: On souhaite générer un signal de 500Hz (Fosc=4MHz) avec 50% de R.C.   */
    /*  Période = 2ms => <TMR1H:TMR1L> = 65535 - [4/4.10^(-6)*2] = 63535 = 0xF82F */
    /*  On charge dans <CCPR1H:CCPR1L> la valeur permettant de fixer le R.C.      */
    /*  On positionne les bits adéquat dans CCP1CON pour fixer le mode COMPARE    */
    /******************************************************************************/
    
    void init_compare()
    {
    TMR1H = 0xF8; TMR1L = 0x2F; // On charge les 2 registres de timer1
                                // pour une période de comptage de 2ms
    CCPR1H = 0xFC;
    CCPR1L = 0x17;
    CCP1CON = 0b00001010;       // Mode COMPARE "special event"
    T1CON = 0;
    }
    
    /*********** Fonction permettant de fixer un rapport cyclique *****************/
    /*  Principe: on charge dans <CCPR1L:CCPR1H> le temps pour lequel on désire   */
    /*  un état haut sur RC2, lorsque cette valeur est atteinte, le mode spécial  */
    /*  de COMPARE va lever le drapeau (CCP1IF) et RC2 est remis à 0 dans la      */
    /*  routine d'interruption.                                                   */
    /*  La variable "duty" permet d'agir sur le duty cycle, elle est indéxée à la */
    /*  valeur d'offset du timer1 (valeur de début de comptage de Timer1).        */
    /******************************************************************************/
    
    void config_rapport_cyclique(int duty)
    {
    CCPR1L = 63535+duty;       // les 8 bits bas sont stockés dans CCPR1L
    CCPR1H = (63535+duty)>>8;  // les 8 bits hauts sont stockés dans CCPR1H
    }
    
    /******************************************************************************/
    /*******************  Gestion des interruptions  ******************************/
    /******************************************************************************/
    
    void interrupt()
    {
     if(TMR1IF == 1)                        // si interruption du Timer1 est détectée
      {
      if(mode_strob == 1)                // si mode stroboscopique est activé
        {
         Cde_Led = 0;                      // la sortie RC2 est mise à 0 (début du ra
         TMR1H=tps_index>>8;           // on recharge le registre du timer
         TMR1L=tps_index;              // pour une nouvelle période indéxée selon X
        }
    
      if(mode_dimmer == 1)             // si mode variateur activé
        {
        Cde_Led = 1;                         // la sortie RC2 est mise à 1
                                       // (début du rapport cyclique)
        TMR1H = 0xF8; TMR1L = 0x2F;    // on recharge la durée de la période fixe
        }
      TMR1IF=0;                        // on repositionne le flag à 0 pour
                                       // pouvoir détecter la prochaine interruption
      }
    
     if((CCP1IF == 1) && (mode_dimmer == 1))  // on autorise l'interruption si le mode
                                              // variateur est activé
          {
          Cde_Led = 0;                 // RC2 retombe à O
                                       // (fin du rapport cyclique)
          CCP1IF = 0;                  // pouvoir détecter la prochaine interruption
                                       // liée àau module CCP1
          }
    }
    Fichier Strob_dimmer_config.h
    Code:
    /*******************************************************************************
    *                  Librairie de définitions carte led                          *
    *              Ecrit en C sur compilateur MikroC  7.0.0.3                      *
    ********************************************************************************
    
    *   Fichier : Strob_dimmer_config.h                        	                   *
    *   Date: 28/02/2008                                                           *
    *   Version: 1.00                                             	               *
    ********************************************************************************
    *   Fonctions: -MODE STROBOSCOPIQUE: faire flasher une led                     *
    *                de Fmin=10Hz à Fmax=500Hz                                     *
    *                                                                              *
    ********************************************************************************
    *   Historique de révision:                                                    *
    *   V1.00 - Version beta					                                             *
    *******************************************************************************/
    
    /******************************** Port B **************************************/
    
    #define Up                    PORTB.F1  // B.P "+"
    #define Down                  PORTB.F2  // B.P "-"
    #define Strob                 PORTB.F3  // B.P "sroboscope"
    #define Dimmer                PORTB.F4  // B.P "variateur"
    
    /******************************** Port C **************************************/
    #define Cde_Led               PORTC.F2  // Cde du signal PWM -> DC/DC
    /******************************************************************************/
    
    #define      Xmax             64536  // butée haute pour le calcul de tps_index
                                         // => Période min (Fmax=500Hz)
                                       
    /****************** appelation des bits des registres *************************/
    
    #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

    -----

    Fichiers attachés Fichiers attachés
    Dernière modification par HULK28 ; 02/03/2008 à 03h43.

  2. #2
    BastienBastien
    Invité

    Re : [Terminé] Stroboscope/Variateur à PIC pour Led

    Bonjour HULK,

    Merci beaucoup. J'attends avec impatience ma carte de développement EasyPIC5 achetée, sur vos conseils, en dollars !

    Ton programme fait intervenir pas mal de concepts de base. Merci.

  3. #3
    Gérard

    Re : [Terminé] Stroboscope/Variateur à PIC pour Led

    Bonjour à tous,

    Encore une idée de Géant (vert ?) qu'a eu notre ami Hulk !

    Si tu pouvais aussi nous donner un petit schéma ?
    Merci d'avance, tu es un Grand du forum.

    Si quelqu'un est preneur d'une version Basic (Proton+), je veux bien me changer de la traduction C --> Basic. (Le C me parrait toujours aussi compliqué )

    Faudra juste attendre un peu, mercredi je pars en vacances.

  4. #4
    HULK28

    Re : [Terminé] Stroboscope/Variateur à PIC pour Led

    Salut,

    voici le schéma qui va avec ce programme.
    J'ai ajouté dans le programme la mise en action des pull-up interne du PortB pour gagner les 4 résistances de tirage au +5V.
    J'ai repositionné aussi les 4 B.P sur <RB0:RB3> donc modifié le fichier header correspondant.
    Je remet donc le zip en pièce jointe du prog.
    @+
    Fichiers attachés Fichiers attachés

Sur le même thème :

Discussions similaires

  1. montage variateur rvb a led
    Par dédé21 dans le forum Électronique
    Réponses: 14
    Dernier message: 20/04/2009, 10h32
  2. variateur de lumiere à base de led
    Par violaine-è dans le forum Électronique
    Réponses: 36
    Dernier message: 16/01/2008, 19h53
  3. Stroboscope à LED
    Par MysterG dans le forum TPE / TIPE et autres travaux
    Réponses: 4
    Dernier message: 27/03/2007, 16h53
  4. Variateur de couleurs pour led RGB
    Par Hosedna dans le forum Électronique
    Réponses: 44
    Dernier message: 23/07/2006, 13h18
  5. Un variateur de tension automatique pour led
    Par geantvert dans le forum Électronique
    Réponses: 16
    Dernier message: 26/11/2003, 15h00