Gestion d'un Rotary Encoder

Ici on parle code, configuration matériel, bibliothèques Arduino ou comment utiliser les modules e-licktronic...

Gestion d'un Rotary Encoder

Postby Philippe » Mar 5th, '13, 12:18

Ci-dessous le code que j'utilise pour gérer un Rotary Encoder.
Si vous avez d'autres méthodes pour gérer ce type de composants, nous pouvons les partager ici.


/*
PHM FACTORY (c)
Routine de gestion d'un Rotary Encoder SparkFun COM-09117
L'encodeur doit etre connecté sur les PIN 2 & 3 de la carte UNO afin d'utiliser les interruptions 0 & 1.
Sur une carte MEGA il est aussi possible d'utiliser les PINs 21, 20, 19, 18 pour les interruptions 2, 3, 4, 5.
Je ne reventique pas la paternité de l'intégralité du code car je me suis inspiré de divers informations trouvées ça et là sur la toile.
*/

# define A 21 // Avec Arduino UNO, il faut utiliser # define A 3
# define B 20 // Avec Arduino UNO, il faut utiliser # define B 2
int POS = 0;
int OLDPOS = 0;
int COUNT=0;
int CPT = 0; // CPT est la variable utile, incrémentée ou décrémentée par l'encodeur.
int OLDCPT = 0;

void setup()
{
  pinMode(A, INPUT_PULLUP);
  pinMode(B, INPUT_PULLUP);
  attachInterrupt (2, EncoderE1, CHANGE); // Avec Arduino UNO, il faut utiliser attachInterrupt (0, EncoderE1, CHANGE)
  attachInterrupt (3, EncoderE1, CHANGE); // Avec Arduino UNO, il faut utiliser attachInterrupt (1, EncoderE1, CHANGE)
  Serial.begin(115200);
}

void loop()
// Cette fonction ne sert qu'à l'affichage de la valeur de CPT sur le Arduino Serial Monitor
{
  if(CPT != OLDCPT) Serial.println(CPT,DEC);
  OLDCPT = CPT;
}

void EncoderE1()
// Cette fonction est appelée par les interruption déclarées plus haut.
{
      if (digitalRead(A) == 1 && digitalRead(B) == 1 ) POS = 0;
      if (digitalRead(A) == 0 && digitalRead(B) == 1 ) POS = 1;
      if (digitalRead(A) == 0 && digitalRead(B) == 0 ) POS = 2;
      if (digitalRead(A) == 1 && digitalRead(B) == 0 ) POS = 3;
      if (POS-OLDPOS == -1 || POS-OLDPOS == 3) COUNT--;
      if (POS-OLDPOS == 1 || POS-OLDPOS == -3) COUNT++;
      if (POS == 0 && COUNT > 0) CPT--;
      if (POS == 0 && COUNT < 0) CPT++;
      if (POS == 0) COUNT=0;
      OLDPOS = POS;
}

Last edited by Philippe on Mar 7th, '13, 17:40, edited 2 times in total.
Ground control to Major Tom
User avatar
Philippe
 
Posts: 20
Joined: Feb 27th, '13, 20:08
Location: Yvelines (78) France

Re: Gestion d'un Rotary Encoder

Postby e-licktronic » Mar 5th, '13, 13:25

Bonjour Philippe,

Voici un code qui m'a l'air plus simple et très efficace car il utilise directement les PORT de l'Arduino.
Si il ya des parties du code que tu ne comprends pas je peux donner plus de description si tu en as besoin.
/*
          Rotary_Encoder_Example         
*/

//These are the rotary encoder pins A, B, and switch
#define ENC_A    8
#define ENC_B    9
#define ENC_SW   10
#define ENC_PORT PINB  //The port that the rotary encoder is on (see http://www.arduino.cc/en/Reference/PortManipulation)

void setup()
{
  //Set encoder pins to input, turn internal pull-ups on
  pinMode(ENC_A, INPUT);
  digitalWrite(ENC_A, HIGH);
  pinMode(ENC_B, INPUT);
  digitalWrite(ENC_B, HIGH);
  pinMode(ENC_SW, INPUT);
  digitalWrite(ENC_SW, HIGH);
  //Set serial rate, prompt for desired sequence
  Serial.begin(115200);
}

void loop()

  //Local Variables
  static uint8_t counter = 0; //this variable will be changed by encoder input
  int8_t tmpdata;
  
    
  //Call read_encoder() function
  tmpdata = read_encoder();
  
  //if the encoder has moved
  if(tmpdata)
    {
      //Print out the counter value
      Serial.print("Counter value: ");
      Serial.println(counter, DEC);
      //Set the new counter value of the encoder
      counter += tmpdata;      
    }
  
  //If the encoder switch is pushed, do something
  if (!digitalRead(ENC_SW))
  {
    //do something
  }
}
/*************************************************************************
*    read_encoder() function as provided by Oleg:                        *
*    http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino *
*                                                                        *
*    Returns change in encoder state (-1,0,1)                            *
************************************************************************ */
int8_t read_encoder()
{
  int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_AB = 0;
  /**/
  old_AB <<= 2;                   //remember previous state
  old_AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_AB & 0x0f )]);
}

Best regards,
e-licktronic
User avatar
e-licktronic
Site Admin
 
Posts: 578
Joined: Feb 16th, '11, 13:36

Re: Gestion d'un Rotary Encoder

Postby Philippe » Mar 7th, '13, 17:37

J'ai optimisé mon code.
Voici une version qui n'utilise pas d'interruption.

/*
PHM FACTORY (c)
Routine de gestion d'un Rotary Encoder SparkFun COM-09117 sans interruptions
Dans cet exemple, l'encoder est connecté sur les pins 20 & 21 d'une Arduino MEGA 2560
*/
int POS = 0;
int OLDPOS = 0;
int COUNT=0;
int CPT = 0;
int OLDCPT = 2;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
EncoderE1();
  if(CPT != OLDCPT)
  {
    Serial.println(CPT, DEC);
    OLDCPT = CPT;
  }
}

void EncoderE1()
{
      if ((PIND & 0x03) == 3 ) POS = 0;
      if ((PIND & 0x03) == 2 ) POS = 1;
      if ((PIND & 0x03) == 0 ) POS = 2;
      if ((PIND & 0x03) == 1 ) POS = 3;
      if (POS-OLDPOS == -1 || POS-OLDPOS == 3) COUNT--;
      if (POS-OLDPOS == 1 || POS-OLDPOS == -3) COUNT++;
      if (POS == 0 && COUNT > 0) CPT--;
      if (POS == 0 && COUNT < 0) CPT++;
      if (POS == 0) COUNT=0;
      OLDPOS = POS;
}

Ground control to Major Tom
User avatar
Philippe
 
Posts: 20
Joined: Feb 27th, '13, 20:08
Location: Yvelines (78) France

Re: Gestion d'un Rotary Encoder

Postby e-licktronic » Mar 8th, '13, 15:34

Bonjour Philippe,

As tu essayé d'utiliser ton code avec la bibliothèque SRIO?
Je voulais savoir si la lecture de l'encoder restait correct malgré le scan des boutons des platines Dilicktal.

Cordialement,

e-licktronic
Best regards,
e-licktronic
User avatar
e-licktronic
Site Admin
 
Posts: 578
Joined: Feb 16th, '11, 13:36

Re: Gestion d'un Rotary Encoder

Postby Philippe » Mar 8th, '13, 16:42

Bonjour,

Oui, j'utilise mon code avec en plus la gestion d'une carte Lickogik, deux cartes Dilicktal, un LCD et des envois de CC sur le midi out.
Pour le moment cela fonctionne bien mais pour être certain de ne jamais avoir de drop sur la lecture de l'encoder, j'utilise les interruptions.
J'ai fait un test sans interruption, ça fonctionne correctement mais pour le moment, mon programme est tout petit

Cordialement.
Ground control to Major Tom
User avatar
Philippe
 
Posts: 20
Joined: Feb 27th, '13, 20:08
Location: Yvelines (78) France


Return to E-licktronic rencontre Arduino

Who is online

Users browsing this forum: No registered users and 2 guests