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 : 2727
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#1 Message par Jérémy » jeu. 15 oct. 2015 22:23

Bonsoir à tous,

Image

Dans le cadre de mon premier projet, je suis en train de tester le module Rotary click de MikroE sur ma plaque EasyPIC7.

J'ai téléchargé le code exemple et je l'ai travaillé . j'entends par la , j'ai changé des valeurs, modifié le mouvements... etc, pour me faire la main dessus et comprendre le code Grey .

Par contre je ne comprends pas certaines lignes que je me permets de vous soumettre pour une t'chtite explication , si vous avez le temps .

Le code entier :
[spoil]

Code : Tout sélectionner

sbit HC595_cs           at RE0_bit;
sbit ENCA               at RC0_bit;
sbit ENCB               at RA2_bit;
sbit ENC_SW             at RB0_bit;
sbit HC595_cs_direction at TRISE0_bit;
sbit ENCA_direction     at TRISC0_bit;
sbit ENCB_direction     at TRISA2_bit;
sbit ENC_SW_direction   at TRISB0_bit;

unsigned int Led_State = 0x0001;
char ENCA_bit,ENCB_bit;
char ENC_Button_State = 0;

//###################      Interruption sur Appui BP      #####################################
void Interrupt(){

  ENC_Button_State++;               // Incremente la valeur du Bouton
  if (ENC_Button_State == 4)        // Si le bouton arrive à 4
    ENC_Button_State = 0;           // On le passe à 0 .

  if (INT0IF_bit){                  // Verification de l'interruption par le Flag INT0
    INT0IF_bit = 0;                 // Réarmement du flag pour l'interrutpion
    // switch pour selectionner l'etat des leds suivant la valeur du Bouton
    // Cette valeur en Hexa correspond à une valeur en binaire sur 16 bits

    switch (ENC_Button_State){
      case 0 : Led_State = 0x0003;  // 1 led allumée  =  00000000 - 00000001
               break;
      case 1 : Led_State = 0x0101;  // 2 leds allumées = 00000001 - 00000001
               break;
      case 2 : Led_State = 0x1111;  // 4 leds allumées = 00010001 - 00010001
               break;
      case 3 : Led_State = 0x5555;  // 8 leds allumées = 01010101 - 01010101
               break;
      default :         // Secours toujours mettre un defaut avec un switch
               break;
    }
  }
}

void HC595_Write(int value){
  char first_byte, second_byte;
  
  second_byte 
= value; // Enregistrement du premier byte
  value = value>>8;    // On décale de 8 bit pour afficher le second byte
  first_byte = value;  // Enregistrement du second Byte

  SPI1_write(first_byte);  // Envoi du premier byte au HC595
  SPI1_write(second_byte); // Envoi du second Byte
  
  HC595_cs 
= 0;            // HC595
  asm{nop};
  asm{nop};
  asm{nop};
  HC595_cs = 1;
}
//##################################################################################
//##########################  PROGRAMME PRINCIPAL  #################################
//##################################################################################

void main() {
  ANSELA = 0 ;                // Configure PORTA en digital
  ANSELB = 0 ;                // Configure PORTB en digital
  ANSELC = 0 ;                // Configure PORTC en digital

  ENCA_direction     = 1;     // Configure RC0 en entrée
  ENCB_direction     = 1;     // Configure RA2 en entrée
  ENC_SW_direction   = 1;     // Configure RB0 en entrée
  HC595_cs_direction = 0;     // Configure RE0 en sortie
  
  INT0IE_bit 
= 1 ;            // Autorise l'interruption sur RB0
  GIE_bit = 1 ;               // Autorise toutes les interruptions ( Global Int Enable)
  
  SPI1_Init
();                // Initialisation du SPI1
 
// #########################    BOUCLE PRINCIPALE ##################################
  while(1) {

    if((ENCA_bit != RC0_bit)||(ENCB_bit != RA2_bit)){   // SI l'état logique change sur la PinA ou la PinB

      // On compare le dernier état logique de la PinB ET le nouvel état logique de la PinA

      if(ENCB_bit|RC0_bit==1){                    // Si ENCB_old OU ENCA_new est à 1
        Led_State = (Led_State << 1) | (Led_State >> 15);
      }
                    
      if
(ENCA_bit|RA2_bit==1){                    // Si ENCA_old OR ENCB_new est à 1
        Led_State = (Led_State >> 1) | (Led_State <<15);
      }

      ENCA_bit = RC0_bit ;    // On enregistre la nouvelle valeur dans ENCA_bit
      ENCB_bit = RA2_bit ;    // On enregistre la nouvelle valeur dans ENCB_bit
    }
    
  HC595_Write
(Led_State);    // Execute la fonction
  }
[/spoil]
Il s'agit de cette ligne en premier lieu :

Code : Tout sélectionner

if(ENCB_bit|RC0_bit==1){                    // Si ENCB_old OU ENCA_new est à 1
        Led_State = (Led_State << 1) | (Led_State >> 15);
      


J'ai l'impression qu'on ce sert de l'ancien état pour déterminé le sens de mouvement à effectuer! mais je ne comprends pas ce que viens faire le | dans le Led_State = (Led_State << 1) | (Led_State >> 15); ? ou plutôt comment déterminé s'il faut décalé de 1 ou de 15 ?

Et Ici en deuxième :


Code : Tout sélectionner

 HC595_cs = 0;            // HC595
  asm{nop};
  asm{nop};
  asm{nop};
  HC595_cs = 1

Je pense que HC595_cs = 0; active la mise à jour des valeurs mais que viennent faire les asm{nop};

PS : mon premier projet et un compte à rebours pour un jeu de société pour mes enfants ; j'avais fabriquer le premier en BASIC, mais il n'as pas resisté a la brutalité des enfants !
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Code pour Encodeur incremental rotatif
mazertoc
Passionné
Passionné
Messages : 201
Enregistré en : juillet 2015
Localisation : Auvernha

#2 Message par mazertoc » ven. 16 oct. 2015 14:48

Jérémy a écrit :Je pense que HC595_cs = 0; active la mise des jours des valeurs , mais que vienne faire les asm{nop};

Je suppose qu'il s'agit de l'instruction NOP en assembleur.
NOP -> no operation -> ne fait rien sinon laisser passer le temps d'un cycle instruction

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

#3 Message par Gérard » ven. 16 oct. 2015 16:59

Peux-tu dire sur quelles pattes du 595 sont câblés 595_cs et 595_cs_direction?
Ces dénominations n'existent pas sur le 74595.
Les nop sont là pour que le signal dure un certain temps pour prise en compte du 74595.
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
Jérémy
Administrateur du site
Administrateur du site
Messages : 2727
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#4 Message par Jérémy » ven. 16 oct. 2015 18:54

Voici un extrait du document ci-joint,reprenant le schéma global en page 2


Cliquez sur l'image
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 : 2727
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#5 Message par Jérémy » dim. 18 oct. 2015 09:26

Bonjour,

Merci pour vos premiére réponse, concernant leNop, je comprends maintenant grace a vous , ce que cela signifie Merci ! Oui mais cela me fais me posé d'autre questions ? combien de temps dur unnop, et pourquoi ne pas utilisé un delay_us ?

Personne sur ma question sur le conditionnement de cette fonction et surtout sur la réponse au conditionnement .
Quand il est écrit led_state = ca OU ca, comment choisir le décalage de 1 ou de 15 ?

Code : Tout sélectionner

if(ENCB_bit|RC0_bit==1){                    // Si ENCB_old OU ENCA_new est à 1
        Led_State = (Led_State << 1) | (Led_State >> 15);
      }
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 : 1661
Âge : 65
Enregistré en : septembre 2015
Localisation : Alsace - Haut-Rhin

#6 Message par Gérard » dim. 18 oct. 2015 10:44

Le schéma ne permet pas de dire où sont câblés 595_cs et 595_cs_direction
Pourquoi nop et pas delay_µs?
nop est une instruction asm qui fait patienter 1 cycle alors que delay_µs est une fonction qui dépend de la vitesse de l'horloge appliquée au processeur.
Pour led_state, aucune idée.
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
mazertoc
Passionné
Passionné
Messages : 201
Enregistré en : juillet 2015
Localisation : Auvernha

#7 Message par mazertoc » dim. 18 oct. 2015 11:04

Jérémy a écrit :combien de temps dur unnop, et pourquoi ne pas utilisé un delay_us ?

Un NOP dure 1 cycle instruction. Avec un quartz 20 MHz ça fait 200 ns.
Si tu sais faire une attente de 200 ns en C . . .

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

#8 Message par Jérémy » jeu. 22 oct. 2015 21:39

Bonsoir,

J'ai quelques loupés avec l'encodeur incrémental . J'ai l'impression que dans un sens, il n'y as aucun problème, mais que dans l’autre sens , de temps en temps la valeur n'est pas prise en compte !
C'est flagrant même, comme le programme est le même dans un sens et dans l'autre , pensez vous que cela puisse venir de la qualité de l'encodeur incrémental ?

Voici la partie du programme qui gère ceci :

Code : Tout sélectionner

if((ENCA_bit != RC1_bit)||(ENCB_bit != RA3_bit)){   // SI l'état logique change sur la PinA ou la PinB
    // On compare le dernier état logique de la PinB ET le nouvel état logique de la PinA
      
if(ENCB_bit|RC1_bit==1){                    // Si ENCB_old OU ENCA_new est à 1
        
Led_State = (Led_State << 1) | (Led_State >> 15);
        
seconde seconde++;
      }

      if(
ENCA_bit|RA3_bit==1){                    // Si ENCA_old OR ENCB_new est à 1
        
Led_State = (Led_State >> 1) | (Led_State <<15);
        
seconde seconde--;
      }

      
ENCA_bit RC1_bit ;    // On enregistre la nouvelle valeur dans ENCA_bit
      
ENCB_bit RA3_bit ;    // On enregistre la nouvelle valeur dans ENCB_bit

      
HC595_Write(Led_State); // Exécute la fonction pour mettre a jour les leds
    
C'est en faisant des erreurs, que l'on apprend le mieux !!!

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

#9 Message par HULK28 » sam. 24 oct. 2015 11:00

Pour te répondre correctement il faudrait connaitre l'ensemble de ton code et la référence de ton encodeur incrémental.
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.
Ne jamais oublier de prendre en compte le facteur temps quand on code, le µC a sa propre vitesse et ton encodeur également.
Sans parler de ton programme qui n'est pas forcément au rendez-vous dès que l'évènement se produit.
"Pour la carotte, le lapin est la parfaite incarnation du mal" -Robert Shecley-

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

#10 Message par paulfjujo » sam. 24 oct. 2015 11:20

bonjour,


pensez vous que cela puisse venir de la qualité de l'encodeur incrémental ?


A la base ce sont des contacts mecaniques .. doncpeuvent etre sujet à rebonds

sur le schema , les cellules R22- C7 et R23 C8 devraient agir comme filtre passe bas ..
mais R22 et R23 font 0 ohms ?

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 .
L'idée est de tout ralentir, jusqu'à une echelle humaine ..
On est pas dans le cas d'un encoder au cul d'un moteur .


et diminuer la vitesse de scrutation , l'action manuelle étant relativement TRES LENTE par rapport à quelques µsec
la liaison SPI et les HC595 ne semblent servir qu'à l'affichage des leds ?
à confirmer ..

Code : Tout sélectionner

 HC595_cs = 0;            // HC595
   Delay_us(100);
  HC595_cs = 1;
Aide toi, le ciel ou FantasPic t'aidera


Retourner vers « Langage C »

Qui est en ligne

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