Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

Code pour Encodeur incremental rotatif
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#11 Message par Jérémy » sam. 24 oct. 2015 11:45

Pour te répondre correctement il faudrait connaitre l'ensemble de ton code et la référence de ton encodeur incrémental.

Je n'ai pas la référence de l'encodeur, seulement celui en #1, rien de marquer dessus .

Pour ma part je n'utilise que les interruptions pour être bien certain de ne pas louper quelque chose, vu la vitesse de réaction de ces petites bêtes.

Je voulais faire ça au début , mais je ne sais pas si c'est possible de déclencher une INT, sur deux événements différents ( si ENC_A ou ENC_B changent) ?.
Car effectivement, quand on tourne l'encodeur , ça va très vite, surtout avec un bouton au bout , qui fait un effet multipliant la vitesse de rotation.

Sans parler de ton programme qui n'est pas forcément au rendez-vous dès que l'évènement se produit.

Oui ca aussi, j'ai donc supprimer la partie qui affiche les leds quand on tourne, je soupçonne les HC595 d’être plus lents.

peut -etre pourrait tu faire une filtre software sur les entrees recevant les signaux encoder.(ENCA_OUT ENCB_OUT)
verifier l'etat 2 fois de suite avec une tempo intermediare de 10mS pour confirmer le nouvel etat .

ce serait une bonne idée, mais je perdrais énormément en réactivité non ?.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Code pour Encodeur incremental rotatif
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#12 Message par Jérémy » sam. 24 oct. 2015 11:49

Désolé j'avais pas vu ton édition

Je souhaite garder le maximum de réactivité

la liaison SPI et les HC595 ne semblent servir qu'à l'affichage des leds ?

Oui . la liaison SPI ne sert qu'a communiqué avec les HC595, pour affiché les leds autour de l'encodeur !.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Code pour Encodeur incremental rotatif
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2597
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#13 Message par paulfjujo » sam. 24 oct. 2015 14:16

ce serait une bonne idée, mais je perdrais énormément en réactivité non ?.


il y a au moins un rapport de 1000 entre la reactivité de l'humain (mS) et celle du MCU (< µS).


J'ai testé un encoder (mecanique) mais avec MPLAB C18et en mode interrupt..et une petite tempo de 5mS.
L'etat de sortie est synchronisé sur etat CLCK correspondant à une sortie prise en reference ..
definition du sens de rotation et évolution exponentielle de 1,2,4..4096 par pas. du comptage resultant..
je ne sais pas si ton encoder fonctionne de la meme maniere ... cela devrait etre le cas géneral.

sur une autre appli avec un encodeur 400 pas par tour, j'ai utilisé aussi le mode interruption sur front RB0
mais test de la sortie apres quelques centaines de microsec pour etre sur d'etre sur un etat stable 0 ou 1.
et j'ai pas mal galéré...
ce n'est pas facile de faire cette detection de sens avec une grande fiabilité !
voir tous les posts (Encoder) traités la dessus dans les autres forums.
Aide toi, le ciel ou FantasPic t'aidera

Code pour Encodeur incremental rotatif
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#14 Message par Jérémy » mar. 27 oct. 2015 18:02

Bonsoir ,

Je pète un câble , avec les encodeurs rotatifs . C'est chaud !!

Mettant en doute la fonctionnalité de rotary click , j'ai fabriquer mon propre encodeur pour l'utiliser avec les interrutpions .

Mais voila , il incrémente de deux a chaque fois . j'en peu plus !! deux jours que je suis dessus . J'essaye une derniére fois et je vous montre ! C'est cette enregistrement de l'ancienne valeur qui me perturbe !
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Code pour Encodeur incremental rotatif
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#15 Message par Jérémy » mar. 27 oct. 2015 22:43

Bon je renonce et demande votre aide, car la je patauge .

Soit ca incremente pas, soit 4 par 4 , soit trop vite soit les valeurs sautent !!!! . j'ai essayé avec des interruptions, sur INT avec front montant sur changement détat , avec front descendant , dans des boucles , avec des if de partout ..... J'y arrive pas .
même les codes trouvés sur le NET, ça ne marche pas bien , ou alors je les adaptes mal, je sais pas .....

Ne me demandez pas un code j'en ai fais des dizaines.


je pense avoir compris la subtilité , mais je n'arrive pas à le mettre en œuvre . les deux broches forment un code suivant le sens de rotation :
00-10-11-01-00 ou 00-01-11-10-00
Oui mais comment déterminer un code a chaque boucle

j'ai fais des chronogramme pour bien me rendre compte pas mieux ....

J'aurais aimé la plus grande réactivité possible ...... Si vous avez un code ou une explication de mon niveau je suis preneur
J'ai fabriquer un encodeur amovible :D je peux le brancher sur n'importe PORT avec n'importe quel Pull UP/DOWN . Le PORTD serait préférable car il n'est pas utilisé , le PORTA-B-C on des broches pour l’écran OLED.

Ici le lien de l'encodeur

Je comprends pas pourquoi . Regardez ce chronogramme ? .Si je déclenche une INT sur front montant sur le signal B . Dans l'INT je regarde l'état de mon signal A . SI A est à "0" cella signifie que je tourne dans un sens , si il est à "1" dans un autre sens . j'incrémente donc ma valeur ou je la décrémente .
Puis je réarme l'int
Puis j'affiche ma valeur .

et bé même ce ça ne fonctionne pas, je sais pas pourquoi !

Image
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Code pour Encodeur incremental rotatif
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#16 Message par Jérémy » mer. 28 oct. 2015 14:33

Avec ceci ça fonctionne pas trop mal .

Mais il y a des ratés de temps en temps, et je ne vois pas trop pourquoi . Le seul probléme que je vois , c'est qu'une interruption se produise pendant une MAJ de l’écran .

J'ai mis les fonctions qui ne font pas partis du probléme à la fin . Ici seul l'INT et le MAIN compte

[spoil]

Code : Tout sélectionner

//#############################       DECLARATION       ############################
#include <Oled_M.h>
#include <chiffre.h>


sbit OLED_RST at LATE1_bit; // Definition de la broche RESET
sbit OLED_CS at LATE0_bit;  // Definition de la broche Chip select
sbit OLED_DC at LATC0_bit;  // Definition de la broche Data/command

unsigned int i,j,;
unsigned char curseur, chiffre=0, seconde=0, D_seconde=0, minute=0, D_minute=0, mem_A, mem_B, U_minute, U_seconde;

sbit ENCA at PORTB.B1;
sbit ENCB at PORTB.B2;
sbit flag at curseur.B0;

//##########################        FONCTION       #############################
void affiche_ecran();
void OLED_M_command (unsigned char temp);
void OLED_M_data(unsigned char temp);
void OLED_M_Init();
void zone_ecran(unsigned char C_min, unsigned char C_max, unsigned char P_min, unsigned char P_max);
void efface_ecran();
void affiche_points();
void   affiche_curseur(unsigned char flag_curseur);
void affichage( unsigned char chiffre, unsigned char position);

//#########################        INTERRUPT       #############################

void interrupt (){

    if (INT1IF_bit == 1){   // verifie notre INT extrene sur RB1
           

           if 
(ENCB == 1){                     // Si au moment de l'INT ENCB est à l'état haut
                minute++ ;                     // Alors on incremente
                if (minute >=100)minute = 0 ;
            }
           if (ENCB == 0){
                minute-- ;                     // Sinon on décremente
                if (minute >=200)minute = 99 ;
            }

           while ((ENCB==1)|(ENCA==1));       // Tant qu'on a pas franchis le point milieu ( les deux à 1)
                                              // On reste la
                      
           INT1IF_bit 
= 0;  // réarme l'INT   // On reset le flag pour pouvoir la rélancée
           flag = 0;        // Faire la MAJ de l'ecran

     }
 }
//##################################################################################
//######################     PROGRAMME PRINCIPAL     ###############################
//##################################################################################
void main(){
     ANSELA = 0;            // PORTA en digital
     ANSELB = 0;            // PORTB en digital
     ANSELC = 0;            // PORTC en digital
     ANSELD = 0;            // PORTD en digital
     ANSELE = 0;            // PORTE en digital
     
     TRISA 
= 0b00001000 ;   // RA3 en entrée pour l'encodeur ENCB
     TRISB = 0b00010110 ;   // RB1 et RB2 en entrée pour l'encodeur  RB4 en entrée pourle Switch
     TRISC = 0b00000010 ;   // RC0 en sortie pour le OLED_DC , RC1 en entre pour l'encodeur ENCA
     TRISD = 0b00000000 ;
     TRISE = 0b00000000 ;   // RE0 en sortie pour le OLED_CS , et RE1 en sortie pour le RESET
     
     SPI1_Init
();           // Initialisation du SPI
     Delay_ms(100);

     OLED_M_Init();         // Initialisation de l'ecran LCD
     Delay_ms(100);

     GIE_bit = 1 ;          // Autorise les INT général
     INTEDG1_bit = 0 ;       // Declenchement de l'INT sur front descendant.
     INT1IE_bit = 1 ;       // Active l'INT externe sur RB1

     efface_ecran();        // On efface l'écran et la RAM
     affiche_points();
     affiche_curseur(0);
     affiche_ecran();
     OLED_M_command(SSD1306_DISPLAYON);//0xAF   Active l'écran OLED
     flag = 0;

//############################     BOUCLE INFINIE     ##############################
 while(1){




      if ((ENCA==0)&(ENCB==0)&(flag == 0)){        // Si l'encodeur est revenu au point mort ( les 2 mis à 0)
                                                   // et qu'il y a eu un changement ( flag mis à 0)
           D_minute = minute / 10 ;                // On autorise la MAJ de l'écran
           U_minute = minute % 10 ;
           Affichage( D_minute, 3) ;
           affichage (U_minute, 23) ;
           flag = 1 ;                              // On met le flag à 1 pourdire qu'on a mit à jour
       }

    
  
}
}


/*
     if((ENCB != mem_B)||(ENCA != mem_A)){

      //#######   2    ########
      if(mem_B|ENCA==1){
        minute = minute++;
        if (minute >=100)minute = 0;
      }

      if(mem_A|ENCB==1){
        minute = minute--;
        if (minute >=200)minute = 99;
      }

      mem_A = ENCA ;
      mem_B = ENCB ;

    }
*/


void OLED_M_command (unsigned char temp){ //Envoi d'une commande
     OLED_CS=0;            // Chip Select , actif à l'état bas
     OLED_DC=0;            // Data/Command selection: 1=Data; 0=Command
     SPI1_Write(temp);     // Envoi de l'info sur le BUS
     OLED_CS=1;            // on arrrete la com en desactivant le chip
  }

void OLED_M_data(unsigned char temp){ //Envoi d'une commande
     OLED_CS=0;            // Chip Select , actif à l'état bas
     OLED_DC=1;            // Data/Command selection: 1=Data; 0=Command
     SPI1_Write(temp);     // Envoi de l'info sur le BUS
     OLED_CS=1;            // on arrrete la com en desactivant le chip
  }

void OLED_M_Init(){ // Initialisation de l'écran

     OLED_RST=0;         // Reset de l'écran
     Delay_ms(100);      // Pause
     OLED_RST=1;         // Arret du Reset
     Delay_ms(100);      // pause

     OLED_M_command(SSD1306_DISPLAYOFF);          //0xAE  Ecran en mode veille (désactivé)
     OLED_M_command(SSD1306_SETDISPLAYCLOCKDIV);  //0xD5  Set Display Clock Divide Ratio/Oscillator Frequency
     OLED_M_command(0x80);
     OLED_M_command(SSD1306_SETMULTIPLEX);        //0xA8  Set Multiplex Ratio
     OLED_M_command(0x27);
     OLED_M_command(SSD1306_SETDISPLAYOFFSET);    //0xD3  Set Display Offset
     OLED_M_command(0x00);
     OLED_M_command(SSD1306_SETSTARTLINE);        //0x40  Set Display Start Line
     OLED_M_command(SSD1306_CHARGEPUMP);          //0x8D  Set Charge Pump
     OLED_M_command(0x14);                        //0x14  Enable Charge Pump
     OLED_M_command(SSD1306_COMSCANDEC);          //0xC8  Set COM Output Scan Direction
     OLED_M_command(SSD1306_SETCOMPINS);          //0xDA  Set COM Pins Hardware Configuration
     OLED_M_command(0x12);
     OLED_M_command(SSD1306_SETCONTRAST);         // 0x81   réglage du contraste
     OLED_M_command(0xAF);                        // Envoi de la valeur du contraste
     OLED_M_command(SSD1306_SETPRECHARGE);        // 0xD9   Set Pre-Charge Period
     OLED_M_command(0x25);
     OLED_M_command(SSD1306_SETVCOMDETECT);       //0xDB   Set VCOMH Deselect Level
     OLED_M_command(0x20);
     OLED_M_command(SSD1306_DISPLAYALLON_RESUME); //0xA4   ??? pas compris - Set Entire Display On/Off
     OLED_M_command(SSD1306_NORMALDISPLAY);       //0xA6   mode normal ou inverse
     OLED_M_command(SSD1306_SETSEGMENTREMAP);     //0xA1   Inverse l'ordre de lecture des colonnes gauche vers droite
     OLED_M_command(SSD1306_MEMORYMODE);          // Selection du mode de defilement
     OLED_M_command(0x00);                        //  Horizontal adressing  mode
  }


void zone_ecran(unsigned char C_min, unsigned char C_max, unsigned char P_min, unsigned char P_max){

     OLED_M_command(SSD1306_COLUMNADDR); // On configre la largeur de l'ecran
     OLED_M_command(C_min);              // Colonne minimum
     OLED_M_command(C_max);              // Colonne MAximum
     OLED_M_command(SSD1306_PAGEADDR);   // On configre la hauteur de l'ecran
     OLED_M_command(P_min);              // Hauteur minimum
     OLED_M_command(P_max);              // Hauteur Maximum
  }

void efface_ecran(){
     zone_ecran(0,127,0,4);    // La zone definie fait toute la RAM

     for (k=0;k<640;k++){      // On efface l'ecran et la ram
         OLED_M_data(0x00);    // On envoie 640 fois "0" pour tout effacer
      }

     zone_ecran(32,127,0,4);   // On definie l'espace de l'écran (moins les 32 colonnes)
  }

void affiche_points(){
     zone_ecran(79,82,2,3);    // La zone est definie pour les points

     for (k=0;k<=7;k++){
         OLED_M_data(points[k]);
      }
  }


void   affiche_curseur(unsigned char flag_curseur){

    zone_ecran(105,111,0,0);    // La zone est definie pour les points
      for (k=0;k<=6;k++){
         if (flag_curseur==1)
            OLED_M_data(fleche_haut[k]);
         else
            OLED_M_data
(0);
       }

     zone_ecran(105,111,4,4);    // La zone est definie pour les points
       for (k=0;k<=6;k++){
         if (flag_curseur==1)
            OLED_M_data(fleche_bas[k]);
          else
            OLED_M_data
(0);
        }

     zone_ecran(50,56,0,0);    // La zone est definie pour les points
       for (k=0;k<=6;k++){
         if (flag_curseur==0)
            OLED_M_data(fleche_haut[k]);
         else
            OLED_M_data
(0);
        }

     zone_ecran(50,56,4,4);    // La zone est definie pour les points
       for (k=0;k<=6;k++){
         if (flag_curseur==0)
            OLED_M_data(fleche_bas[k]);
          else
            OLED_M_data
(0);
        }

  }

void affichage( unsigned char chiffre, unsigned char position){

     OLED_M_command(SSD1306_COLUMNADDR); // On configre la largeur de l'ecran
     OLED_M_command(32+position);        // Colonne minimum
     OLED_M_command(47+position);        // Colonne MAximum;
     OLED_M_command(SSD1306_PAGEADDR);   // On configre la largeur de l'ecran
     OLED_M_command(1);                  // Colonne minimum
     OLED_M_command(3);                  // Colonne MAximum;

     if ( chiffre == 0){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre0[k]);}
        }
     if ( chiffre == 1){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre1[k]);}
        }
     if ( chiffre == 2){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre2[k]);}
        }
     if ( chiffre == 3){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre3[k]);}
        }
     if ( chiffre == 4){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre4[k]);}
        }
     if ( chiffre == 5){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre5[k]);}
        }
     if ( chiffre == 6){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre6[k]);}
        }
     if ( chiffre == 7){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre7[k]);}
        }
     if ( chiffre == 8){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre8[k]);}
        }
     if ( chiffre == 9){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre9[k]);}
        }

  }

  void affiche_ecran(){
   affichage (0, 58);
   affichage (0, 78) ;
   affichage (0, 3) ;
   affichage (0, 23) ;
[/spoil]

Avec ce code ci , ça marche vraiment pas mal. Ici je n'ai pas d'INT, et malheureusement si je force un tout petit peu sur l'axe de l'encodeur sans passer le cran) il réagit aussi . Bon cela reste un détail. Mais ce n'est pas encore la perfection mon truc .
en tout cas ce code la est le plus fluide , rapide fiable que j'ai pus réussir a faire .

[spoil]

Code : Tout sélectionner

//#############################       DECLARATION       ############################
#include <Oled_M.h>
#include <chiffre.h>


sbit OLED_RST at LATE1_bit; // Definition de la broche RESET
sbit OLED_CS at LATE0_bit;  // Definition de la broche Chip select
sbit OLED_DC at LATC0_bit;  // Definition de la broche Data/command

unsigned int i,j,;
unsigned char curseur, chiffre=0, seconde=0, D_seconde=0, minute=0, D_minute=0, mem_A, mem_B, U_minute, U_seconde;

sbit ENCA at PORTB.B1;
sbit ENCB at PORTB.B2;
sbit flag at curseur.B0;

//##########################        FONCTION       #############################
void affiche_ecran();
void OLED_M_command (unsigned char temp);
void OLED_M_data(unsigned char temp);
void OLED_M_Init();
void zone_ecran(unsigned char C_min, unsigned char C_max, unsigned char P_min, unsigned char P_max);
void efface_ecran();
void affiche_points();
void   affiche_curseur(unsigned char flag_curseur);
void affichage( unsigned char chiffre, unsigned char position);
 void test();
 
//##################################################################################
//######################     PROGRAMME PRINCIPAL     ###############################
//##################################################################################
void main(){
     ANSELA = 0;            // PORTA en digital
     ANSELB = 0;            // PORTB en digital
     ANSELC = 0;            // PORTC en digital
     ANSELD = 0;            // PORTD en digital
     ANSELE = 0;            // PORTE en digital
     
     TRISA 
= 0b00001000 ;   // RA3 en entrée pour l'encodeur ENCB
     TRISB = 0b00010110 ;   // RB1 et RB2 en entrée pour l'encodeur  RB4 en entrée pourle Switch
     TRISC = 0b00000010 ;   // RC0 en sortie pour le OLED_DC , RC1 en entre pour l'encodeur ENCA
     TRISD = 0b00000000 ;
     TRISE = 0b00000000 ;   // RE0 en sortie pour le OLED_CS , et RE1 en sortie pour le RESET
     
     SPI1_Init
();           // Initialisation du SPI
     Delay_ms(100);

     OLED_M_Init();         // Initialisation de l'ecran LCD
     Delay_ms(100);

     efface_ecran();        // On efface l'écran et la RAM
     affiche_points();
     affiche_curseur(0);
     affiche_ecran();
     OLED_M_command(SSD1306_DISPLAYON);//0xAF   Active l'écran OLED

//############################     BOUCLE INFINIE     ##############################
 while(1){

     if (ENCA == 1){
         test();
         D_minute = minute / 10 ;
         U_minute = minute % 10 ;
         Affichage( D_minute, 3) ;
         affichage (U_minute, 23) ;
      }
  }
}

 void test(){

      while ( ENCA == 1);
            if (ENCB == 0)
               minute--;
            else
               minute
++;

           if (minute >=200)minute = 99 ;
           if (minute >=100)minute = 0 ;
 }


void OLED_M_command (unsigned char temp){ //Envoi d'une commande
     OLED_CS=0;            // Chip Select , actif à l'état bas
     OLED_DC=0;            // Data/Command selection: 1=Data; 0=Command
     SPI1_Write(temp);     // Envoi de l'info sur le BUS
     OLED_CS=1;            // on arrrete la com en desactivant le chip
  }

void OLED_M_data(unsigned char temp){ //Envoi d'une commande
     OLED_CS=0;            // Chip Select , actif à l'état bas
     OLED_DC=1;            // Data/Command selection: 1=Data; 0=Command
     SPI1_Write(temp);     // Envoi de l'info sur le BUS
     OLED_CS=1;            // on arrrete la com en desactivant le chip
  }

void OLED_M_Init(){ // Initialisation de l'écran

     OLED_RST=0;         // Reset de l'écran
     Delay_ms(100);      // Pause
     OLED_RST=1;         // Arret du Reset
     Delay_ms(100);      // pause

     OLED_M_command(SSD1306_DISPLAYOFF);          //0xAE  Ecran en mode veille (désactivé)
     OLED_M_command(SSD1306_SETDISPLAYCLOCKDIV);  //0xD5  Set Display Clock Divide Ratio/Oscillator Frequency
     OLED_M_command(0x80);
     OLED_M_command(SSD1306_SETMULTIPLEX);        //0xA8  Set Multiplex Ratio
     OLED_M_command(0x27);
     OLED_M_command(SSD1306_SETDISPLAYOFFSET);    //0xD3  Set Display Offset
     OLED_M_command(0x00);
     OLED_M_command(SSD1306_SETSTARTLINE);        //0x40  Set Display Start Line
     OLED_M_command(SSD1306_CHARGEPUMP);          //0x8D  Set Charge Pump
     OLED_M_command(0x14);                        //0x14  Enable Charge Pump
     OLED_M_command(SSD1306_COMSCANDEC);          //0xC8  Set COM Output Scan Direction
     OLED_M_command(SSD1306_SETCOMPINS);          //0xDA  Set COM Pins Hardware Configuration
     OLED_M_command(0x12);
     OLED_M_command(SSD1306_SETCONTRAST);         // 0x81   réglage du contraste
     OLED_M_command(0xAF);                        // Envoi de la valeur du contraste
     OLED_M_command(SSD1306_SETPRECHARGE);        // 0xD9   Set Pre-Charge Period
     OLED_M_command(0x25);
     OLED_M_command(SSD1306_SETVCOMDETECT);       //0xDB   Set VCOMH Deselect Level
     OLED_M_command(0x20);
     OLED_M_command(SSD1306_DISPLAYALLON_RESUME); //0xA4   ??? pas compris - Set Entire Display On/Off
     OLED_M_command(SSD1306_NORMALDISPLAY);       //0xA6   mode normal ou inverse
     OLED_M_command(SSD1306_SETSEGMENTREMAP);     //0xA1   Inverse l'ordre de lecture des colonnes gauche vers droite
     OLED_M_command(SSD1306_MEMORYMODE);          // Selection du mode de defilement
     OLED_M_command(0x00);                        //  Horizontal adressing  mode
  }


void zone_ecran(unsigned char C_min, unsigned char C_max, unsigned char P_min, unsigned char P_max){

     OLED_M_command(SSD1306_COLUMNADDR); // On configre la largeur de l'ecran
     OLED_M_command(C_min);              // Colonne minimum
     OLED_M_command(C_max);              // Colonne MAximum
     OLED_M_command(SSD1306_PAGEADDR);   // On configre la hauteur de l'ecran
     OLED_M_command(P_min);              // Hauteur minimum
     OLED_M_command(P_max);              // Hauteur Maximum
  }

void efface_ecran(){
     zone_ecran(0,127,0,4);    // La zone definie fait toute la RAM

     for (k=0;k<640;k++){      // On efface l'ecran et la ram
         OLED_M_data(0x00);    // On envoie 640 fois "0" pour tout effacer
      }

     zone_ecran(32,127,0,4);   // On definie l'espace de l'écran (moins les 32 colonnes)
  }

void affiche_points(){
     zone_ecran(79,82,2,3);    // La zone est definie pour les points

     for (k=0;k<=7;k++){
         OLED_M_data(points[k]);
      }
  }


void   affiche_curseur(unsigned char flag_curseur){

    zone_ecran(105,111,0,0);    // La zone est definie pour les points
      for (k=0;k<=6;k++){
         if (flag_curseur==1)
            OLED_M_data(fleche_haut[k]);
         else
            OLED_M_data
(0);
       }

     zone_ecran(105,111,4,4);    // La zone est definie pour les points
       for (k=0;k<=6;k++){
         if (flag_curseur==1)
            OLED_M_data(fleche_bas[k]);
          else
            OLED_M_data
(0);
        }

     zone_ecran(50,56,0,0);    // La zone est definie pour les points
       for (k=0;k<=6;k++){
         if (flag_curseur==0)
            OLED_M_data(fleche_haut[k]);
         else
            OLED_M_data
(0);
        }

     zone_ecran(50,56,4,4);    // La zone est definie pour les points
       for (k=0;k<=6;k++){
         if (flag_curseur==0)
            OLED_M_data(fleche_bas[k]);
          else
            OLED_M_data
(0);
        }

  }

void affichage( unsigned char chiffre, unsigned char position){

     OLED_M_command(SSD1306_COLUMNADDR); // On configre la largeur de l'ecran
     OLED_M_command(32+position);        // Colonne minimum
     OLED_M_command(47+position);        // Colonne MAximum;
     OLED_M_command(SSD1306_PAGEADDR);   // On configre la largeur de l'ecran
     OLED_M_command(1);                  // Colonne minimum
     OLED_M_command(3);                  // Colonne MAximum;

     if ( chiffre == 0){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre0[k]);}
        }
     if ( chiffre == 1){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre1[k]);}
        }
     if ( chiffre == 2){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre2[k]);}
        }
     if ( chiffre == 3){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre3[k]);}
        }
     if ( chiffre == 4){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre4[k]);}
        }
     if ( chiffre == 5){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre5[k]);}
        }
     if ( chiffre == 6){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre6[k]);}
        }
     if ( chiffre == 7){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre7[k]);}
        }
     if ( chiffre == 8){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre8[k]);}
        }
     if ( chiffre == 9){
               for(k=0;k<48;k++)
                {OLED_M_data(chiffre9[k]);}
        }

  }

  void affiche_ecran(){
   affichage (0, 58);
   affichage (0, 78) ;
   affichage (0, 3) ;
   affichage (0, 23) ;
}
[/spoil]
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Code pour Encodeur incremental rotatif
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#17 Message par Jérémy » mer. 28 oct. 2015 17:02

Bon allez un dernier et j’arrête mon monologue humour!!

cette histoire de "vibration" m'enquiquinais !! . En effet le moindre petit accoup incrémentais une valeur !!! . Chose corrigée !!! Je crois que je tiens le programme presque parfait , mais qui doit pouvoir soit se raccourcir ou s’améliorer ;

Ici je teste 2 valeurs avant de valider une incrémentation/décrémentation ( ce soir je testerais avec 3 valeurs) . Ainsi l'encodeur doit être franchement tourné pour valider le calcul .
De plus la réactivité est au top niveau . En faisant 5 tours très rapide, j'ai aucune erreur .

Voici mon programme biscornu si jamais ca peut servir a quelqu'un .

En fait je créé une variable qui contient l'état des switch sur ses bit0 et bit1 . Ainsi cette variable peut prendre 4 valeurs ( 0=00,1=01,2=10 et 3=11).

A chaque fois que je lis un code, j'attends le code suivant pour voir le sens ; Si le code est bon alors j'effectue le calcul, sinon je reviens au départ .
Pour vérifier d'un code a l'autre , j'attends a chaque coup que la variable change !.

[spoil]

Code : Tout sélectionner

//#############################       DECLARATION       ############################
#include <Oled_M.h>
#include <chiffre.h>


sbit OLED_RST at LATE1_bit// Definition de la broche RESET
sbit OLED_CS at LATE0_bit;  // Definition de la broche Chip select
sbit OLED_DC at LATC0_bit;  // Definition de la broche Data/command

unsigned int i,j,;
unsigned char curseurchiffre=0seconde=0D_seconde=0minute=0D_minute=0mem_Amem_BU_minuteU_seconde,stock=0;

sbit ENCA at PORTB.B1;
sbit ENCB at PORTB.B2;
sbit flag at curseur.B0;

sbit stockA at stock.B0;
sbit stockB at stock.B1;

//##########################        FONCTION       #############################
void affiche_ecran();
void OLED_M_command (unsigned char temp);
void OLED_M_data(unsigned char temp);
void OLED_M_Init();
void zone_ecran(unsigned char C_minunsigned char C_maxunsigned char P_minunsigned char P_max);
void efface_ecran();
void affiche_points();
void   affiche_curseur(unsigned char flag_curseur);
void affichageunsigned char chiffreunsigned char position);

 
//#########################        INTERRUPT       #############################

//##################################################################################
//######################     PROGRAMME PRINCIPAL     ###############################
//##################################################################################
void main(){
     
ANSELA 0;            // PORTA en digital
     
ANSELB 0;            // PORTB en digital
     
ANSELC 0;            // PORTC en digital
     
ANSELD 0;            // PORTD en digital
     
ANSELE 0;            // PORTE en digital
     
     
TRISA 0b00001000 ;   // RA3 en entrée pour l'encodeur ENCB
     
TRISB 0b00010110 ;   // RB1 et RB2 en entrée pour l'encodeur  RB4 en entrée pourle Switch
     
TRISC 0b00000010 ;   // RC0 en sortie pour le OLED_DC , RC1 en entre pour l'encodeur ENCA
     
TRISD 0b00000000 ;
     
TRISE 0b00000000 ;   // RE0 en sortie pour le OLED_CS , et RE1 en sortie pour le RESET
     
     
SPI1_Init();           // Initialisation du SPI
     
Delay_ms(100);

     
OLED_M_Init();         // Initialisation de l'ecran LCD
     
Delay_ms(100);

     
efface_ecran();        // On efface l'écran et la RAM
     
affiche_points();
     
affiche_curseur(0);
     
affiche_ecran();
     
OLED_M_command(SSD1306_DISPLAYON);//0xAF   Active l'écran OLED

//############################     BOUCLE INFINIE     ##############################
 
while(1){

     
stockA ENCA ;
     
stockB ENCB ;

     if ( 
stock == 2){
          
stockA ENCA ;
          
stockB ENCB ;
                 while ( (
ENCA==stockA) & (ENCB==stockB));
                     
stockA ENCA ;
                     
stockB ENCB ;
                            if ( 
stock == 3minute--;
                            if (
minute >=200)minute 99 ;
                            while ( (
ENCA==1) | (ENCB == 1));

     }
     
      if ( 
stock == 1){
          
stockA ENCA ;
          
stockB ENCB ;
                 while ( (
ENCA==stockA) & (ENCB==stockB));
                     
stockA ENCA ;
                     
stockB ENCB ;
                            if ( 
stock == 3minute++;
                            if (
minute >=100)minute ;
                            while ( (
ENCA==1) | (ENCB == 1));

     }
         
D_minute minute 10 ;
         
U_minute minute 10 ;
         
AffichageD_minute3) ;
         
affichage (U_minute23) ;
     
  }
}


void OLED_M_command (unsigned char temp){ //Envoi d'une commande
     
OLED_CS=0;            // Chip Select , actif à l'état bas
     
OLED_DC=0;            // Data/Command selection: 1=Data; 0=Command
     
SPI1_Write(temp);     // Envoi de l'info sur le BUS
     
OLED_CS=1;            // on arrrete la com en desactivant le chip
  
}

void OLED_M_data(unsigned char temp){ //Envoi d'une commande
     
OLED_CS=0;            // Chip Select , actif à l'état bas
     
OLED_DC=1;            // Data/Command selection: 1=Data; 0=Command
     
SPI1_Write(temp);     // Envoi de l'info sur le BUS
     
OLED_CS=1;            // on arrrete la com en desactivant le chip
  
}

void OLED_M_Init(){ // Initialisation de l'écran

     
OLED_RST=0;         // Reset de l'écran
     
Delay_ms(100);      // Pause
     
OLED_RST=1;         // Arret du Reset
     
Delay_ms(100);      // pause

     
OLED_M_command(SSD1306_DISPLAYOFF);          //0xAE  Ecran en mode veille (désactivé)
     
OLED_M_command(SSD1306_SETDISPLAYCLOCKDIV);  //0xD5  Set Display Clock Divide Ratio/Oscillator Frequency
     
OLED_M_command(0x80);
     
OLED_M_command(SSD1306_SETMULTIPLEX);        //0xA8  Set Multiplex Ratio
     
OLED_M_command(0x27);
     
OLED_M_command(SSD1306_SETDISPLAYOFFSET);    //0xD3  Set Display Offset
     
OLED_M_command(0x00);
     
OLED_M_command(SSD1306_SETSTARTLINE);        //0x40  Set Display Start Line
     
OLED_M_command(SSD1306_CHARGEPUMP);          //0x8D  Set Charge Pump
     
OLED_M_command(0x14);                        //0x14  Enable Charge Pump
     
OLED_M_command(SSD1306_COMSCANDEC);          //0xC8  Set COM Output Scan Direction
     
OLED_M_command(SSD1306_SETCOMPINS);          //0xDA  Set COM Pins Hardware Configuration
     
OLED_M_command(0x12);
     
OLED_M_command(SSD1306_SETCONTRAST);         // 0x81   réglage du contraste
     
OLED_M_command(0xAF);                        // Envoi de la valeur du contraste
     
OLED_M_command(SSD1306_SETPRECHARGE);        // 0xD9   Set Pre-Charge Period
     
OLED_M_command(0x25);
     
OLED_M_command(SSD1306_SETVCOMDETECT);       //0xDB   Set VCOMH Deselect Level
     
OLED_M_command(0x20);
     
OLED_M_command(SSD1306_DISPLAYALLON_RESUME); //0xA4   ??? pas compris - Set Entire Display On/Off
     
OLED_M_command(SSD1306_NORMALDISPLAY);       //0xA6   mode normal ou inverse
     
OLED_M_command(SSD1306_SETSEGMENTREMAP);     //0xA1   Inverse l'ordre de lecture des colonnes gauche vers droite
     
OLED_M_command(SSD1306_MEMORYMODE);          // Selection du mode de defilement
     
OLED_M_command(0x00);                        //  Horizontal adressing  mode
  
}


void zone_ecran(unsigned char C_minunsigned char C_maxunsigned char P_minunsigned char P_max){

     
OLED_M_command(SSD1306_COLUMNADDR); // On configre la largeur de l'ecran
     
OLED_M_command(C_min);              // Colonne minimum
     
OLED_M_command(C_max);              // Colonne MAximum
     
OLED_M_command(SSD1306_PAGEADDR);   // On configre la hauteur de l'ecran
     
OLED_M_command(P_min);              // Hauteur minimum
     
OLED_M_command(P_max);              // Hauteur Maximum
  
}

void efface_ecran(){
     
zone_ecran(0,127,0,4);    // La zone definie fait toute la RAM

     
for (k=0;k<640;k++){      // On efface l'ecran et la ram
         
OLED_M_data(0x00);    // On envoie 640 fois "0" pour tout effacer
      
}

     
zone_ecran(32,127,0,4);   // On definie l'espace de l'écran (moins les 32 colonnes)
  
}

void affiche_points(){
     
zone_ecran(79,82,2,3);    // La zone est definie pour les points

     
for (k=0;k<=7;k++){
         
OLED_M_data(points[k]);
      }
  }


void   affiche_curseur(unsigned char flag_curseur){

    
zone_ecran(105,111,0,0);    // La zone est definie pour les points
      
for (k=0;k<=6;k++){
         if (
flag_curseur==1)
            
OLED_M_data(fleche_haut[k]);
         else
            
OLED_M_data(0);
       }

     
zone_ecran(105,111,4,4);    // La zone est definie pour les points
       
for (k=0;k<=6;k++){
         if (
flag_curseur==1)
            
OLED_M_data(fleche_bas[k]);
          else
            
OLED_M_data(0);
        }

     
zone_ecran(50,56,0,0);    // La zone est definie pour les points
       
for (k=0;k<=6;k++){
         if (
flag_curseur==0)
            
OLED_M_data(fleche_haut[k]);
         else
            
OLED_M_data(0);
        }

     
zone_ecran(50,56,4,4);    // La zone est definie pour les points
       
for (k=0;k<=6;k++){
         if (
flag_curseur==0)
            
OLED_M_data(fleche_bas[k]);
          else
            
OLED_M_data(0);
        }

  }

void affichageunsigned char chiffreunsigned char position){

     
OLED_M_command(SSD1306_COLUMNADDR); // On configre la largeur de l'ecran
     
OLED_M_command(32+position);        // Colonne minimum
     
OLED_M_command(47+position);        // Colonne MAximum;
     
OLED_M_command(SSD1306_PAGEADDR);   // On configre la largeur de l'ecran
     
OLED_M_command(1);                  // Colonne minimum
     
OLED_M_command(3);                  // Colonne MAximum;

     
if ( chiffre == 0){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre0[k]);}
        }
     if ( 
chiffre == 1){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre1[k]);}
        }
     if ( 
chiffre == 2){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre2[k]);}
        }
     if ( 
chiffre == 3){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre3[k]);}
        }
     if ( 
chiffre == 4){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre4[k]);}
        }
     if ( 
chiffre == 5){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre5[k]);}
        }
     if ( 
chiffre == 6){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre6[k]);}
        }
     if ( 
chiffre == 7){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre7[k]);}
        }
     if ( 
chiffre == 8){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre8[k]);}
        }
     if ( 
chiffre == 9){
               for(
k=0;k<48;k++)
                {
OLED_M_data(chiffre9[k]);}
        }

  }

  
void affiche_ecran(){
   
affichage (058);
   
affichage (078) ;
   
affichage (03) ;
   
affichage (023) ;
[/spoil]
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Code pour Encodeur incremental rotatif
Gérard
Avatar de l’utilisateur
Expert
Expert
Messages : 1644
Âge : 65
Enregistré en : septembre 2015
Localisation : Alsace - Haut-Rhin

#18 Message par Gérard » mer. 28 oct. 2015 17:56

Je ne peux pas t'aider, je suis nul et C et ne connais pas les encodeurs.
Tu devrais peut-être laisser refroidir le sujet (et ton cerveau) et reprendre à tête reposée la semaine prochaine.

Non, je ne suis pas Freud... :mrgreen:
Le 18/04/19 je suis devenu papy de jumeaux, le 01/09/23 une petite cousine des jumeaux est née.

Code pour Encodeur incremental rotatif
HULK28
Avatar de l’utilisateur
Amateur
Amateur
Messages : 106
Enregistré en : août 2015
Localisation : IdF

#19 Message par HULK28 » sam. 7 nov. 2015 14:23

Bonjour,

je n'ai pas regardé en détail tout ton code mais juste une remarque de C:

il vaut mieux utiliser 'else if' plutôt qu'une succession de 'if'.
La différence est que dès qu'un 'else if' est validé tu sors immédiatement, alors qu'avec des if le programme va tester tous les cas un par un, même après avoir trouvé le bon en tout premier par exemple.
Le temps de traitement sera bien meilleur.
C'est aussi très pratique dans le cas où tu changes une variable qui se trouve dans ton test avec tes if, si par exemple tu as:

Code : Tout sélectionner

...
if(condition == 1)
  {
  condition++;
  }
if(condition == 2)
  {
  moteur = 1;
  }
....


Dans ce cas après le premier if tu accèderas directement au deuxième, ce qui n'est pas toujours souhaitable!
Avec des else if tu n'y accèderas qu'au deuxième passage.
Plutôt que des successions de if, tu peux aussi utiliser des 'switch-case', c'est encore plus propre.
@+
"Pour la carotte, le lapin est la parfaite incarnation du mal" -Robert Shecley-

Code pour Encodeur incremental rotatif
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#20 Message par Jérémy » sam. 7 nov. 2015 14:57

Hello HULK28,

Merci pour ces remarques pertinentes , et effectivement je n'ai pas "optimisé" mon code .

Au tout départ j'avais utilisé un switch , mais comme ça ne fonctionnais pas, je l'ai supprimé pour quelque chose de plus pratique pour un novice comme moi, quitte à perdre un peu de réactivité !
C'est en faisant des erreurs, que l'on apprend le mieux !!!


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 44 invités