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 ---
- 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 ---
Modérateur : Jérémy
Code pour Encodeur incremental rotatif
-
Jérémy
Administrateur du site- Messages : 2723
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
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 ?.
Code pour Encodeur incremental rotatif
-
Jérémy
Administrateur du site- Messages : 2723
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
Désolé j'avais pas vu ton édition
Je souhaite garder le maximum de réactivité
Oui . la liaison SPI ne sert qu'a communiqué avec les HC595, pour affiché les leds autour de l'encodeur !.
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 !.
Code pour Encodeur incremental rotatif
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
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.
Code pour Encodeur incremental rotatif
-
Jérémy
Administrateur du site- Messages : 2723
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
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 !
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 !
Code pour Encodeur incremental rotatif
-
Jérémy
Administrateur du site- Messages : 2723
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
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 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 !
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 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 !
Code pour Encodeur incremental rotatif
-
Jérémy
Administrateur du site- Messages : 2723
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
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][/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][/spoil]
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,k ;
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) ;
}
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,k ;
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) ;
}
Code pour Encodeur incremental rotatif
-
Jérémy
Administrateur du site- Messages : 2723
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
Bon allez un dernier et j’arrête mon monologue
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][/spoil]
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,k ;
unsigned char curseur, chiffre=0, seconde=0, D_seconde=0, minute=0, D_minute=0, mem_A, mem_B, U_minute, U_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_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 #############################
//##################################################################################
//###################### 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 == 3) minute--;
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 == 3) minute++;
if (minute >=100)minute = 0 ;
while ( (ENCA==1) | (ENCB == 1));
}
D_minute = minute / 10 ;
U_minute = minute % 10 ;
Affichage( D_minute, 3) ;
affichage (U_minute, 23) ;
}
}
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) ;
}
Code pour Encodeur incremental rotatif
- Gérard
Expert- Messages : 1644
- Âge : 65
- Enregistré en : septembre 2015
- Localisation : Alsace - Haut-Rhin
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...
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...
Code pour Encodeur incremental rotatif
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:
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.
@+
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.
@+
Code pour Encodeur incremental rotatif
-
Jérémy
Administrateur du site- Messages : 2723
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
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é !
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é !
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 100 invités