Go Down

Topic: rotary encoder (Read 2504 times) previous topic - next topic

mipumat

hi there,

i got a rotary encoder from sparkfun which i have connected to a arduino nano. i am using the following code:

Code: [Select]

int pulses, A_SIG=0, B_SIG=1;

void setup(){
  attachInterrupt(0, A_RISE, RISING);
  attachInterrupt(1, B_RISE, RISING);
  Serial.begin(115200);
}//setup


void loop(){
   
}

void A_RISE(){
detachInterrupt(0);
A_SIG=1;

if(B_SIG==0)
pulses++;//moving forward
if(B_SIG==1)
pulses--;//moving reverse
Serial.println(pulses);
attachInterrupt(0, A_FALL, FALLING);
}

void A_FALL(){
  detachInterrupt(0);
A_SIG=0;

if(B_SIG==1)
pulses++;//moving forward
if(B_SIG==0)
pulses--;//moving reverse
Serial.println(pulses);
attachInterrupt(0, A_RISE, RISING); 
}

void B_RISE(){
detachInterrupt(1);
B_SIG=1;

if(A_SIG==1)
pulses++;//moving forward
if(A_SIG==0)
pulses--;//moving reverse
Serial.println(pulses);
attachInterrupt(1, B_FALL, FALLING);
}

void B_FALL(){
detachInterrupt(1);
B_SIG=0;

if(A_SIG==0)
pulses++;//moving forward
if(A_SIG==1)
pulses--;//moving reverse
Serial.println(pulses);
attachInterrupt(1, B_RISE, RISING);
}


and, as i am a newbee, i am in trouble :)   when i start serial monitor i get some numbers coming in and when i turn the encoder also something is happening but not what i want. also numbers are changing when i touch the cables sometimes. so my guess is that i need some kind of pullup oder pulldown resistors somewhere. would someone be so nice and help me out here?

i connected the middle pin of the encoder to gnd on the arduino and the left and right pins to digital 2 and 3. and i do not know much about electronics.

have a nice day!

florinc

Sparkfun usually has some documentation and/or sample code for their products (links after the product description).
Did you check there?

JoeN

I figured out rotary encoders by experimenting with code on this page:

http://www.arduino.cc/playground/Main/RotaryEncoders

I tried several before I got it to work to my satisfaction.  I think the one that worked best for me is under "Another Interrupt Library THAT REALLY WORKS (the Encoder interrupts the processor and debounces like there is no tomorrow)."

I will say, you never do a PinMode(0, INPUT) and PinMode(1, INPUT) which may be necessary.  
I have only come here seeking knowledge. Things they would not teach me of in college.

mipumat

i tried several sketches but the one that works for me is :

Code: [Select]

/*
(Copy and paste)

Rotary encoder decoding using two interrupt lines.
Most Arduino boards have two external interrupts,
numbers 0 (on digital pin 2) and 1 (on digital pin 3).

Program sketch is for SparkFun Rotary Encoder sku: COM-09117
Connect the middle pin of the three to ground.
The outside two pins of the three are connected to
digital pins 2 and 3
*/


volatile int number = 0;                // Testnumber, print it when it changes value,
                                        // used in loop and both interrupt routines
int oldnumber = number;

volatile boolean halfleft = false;      // Used in both interrupt routines
volatile boolean halfright = false;


void setup(){
  Serial.begin(9600);
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);                // Turn on internal pullup resistor
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);                // Turn on internal pullup resistor
  attachInterrupt(0, isr_2, FALLING);   // Call isr_2 when digital pin 2 goes LOW
  attachInterrupt(1, isr_3, FALLING);   // Call isr_3 when digital pin 3 goes LOW
}

void loop(){
  if(number != oldnumber){              // Change in value ?
    Serial.println(number);             // Yes, print it (or whatever)
    oldnumber = number;
  }
}

void isr_2(){                                              // Pin2 went LOW
  delay(1);                                                // Debounce time
  if(digitalRead(2) == LOW){                               // Pin2 still LOW ?
    if(digitalRead(3) == HIGH && halfright == false){      // -->
      halfright = true;                                    // One half click clockwise
    } 
    if(digitalRead(3) == LOW && halfleft == true){         // <--
      halfleft = false;                                    // One whole click counter-
      number--;                                            // clockwise
    }
  }
}
void isr_3(){                                             // Pin3 went LOW
  delay(1);                                               // Debounce time
  if(digitalRead(3) == LOW){                              // Pin3 still LOW ?
    if(digitalRead(2) == HIGH && halfleft == false){      // <--
      halfleft = true;                                    // One half  click counter-
    }                                                     // clockwise
    if(digitalRead(2) == LOW && halfright == true){       // -->
      halfright = false;                                  // One whole click clockwise
      number++;
    }
  }
}


i found it here : http://home.online.no/~togalaas/rotary_encoder/

just for other ones who have troubles with this. i am solved :)

JoeN

Maybe because that example sets the PinMode to input...   :smiley-yell:
I have only come here seeking knowledge. Things they would not teach me of in college.

dc42

Sure, you can use 2 interrupts to manage a rotary encoder, but it is a bit of a waste of interrupts. I poll rotary encoders every 1 to 2 milliseconds instead, which also allows me to multiplex them (I've just completed a design that uses 3 rotary encoders multiplexed on to 2 input pins). You can find the code I use at http://miscsolutions.wordpress.com/2011/10/16/five-things-i-never-use-in-arduino-projects/.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

JoeN


Sure, you can use 2 interrupts to manage a rotary encoder, but it is a bit of a waste of interrupts. I poll rotary encoders every 1 to 2 milliseconds instead, which also allows me to multiplex them (I've just completed a design that uses 3 rotary encoders multiplexed on to 2 input pins). You can find the code I use at http://miscsolutions.wordpress.com/2011/10/16/five-things-i-never-use-in-arduino-projects/.


I have a circuit that uses a couple of flip-flops and a counter that keeps the rotary encoder count without any processor involvement and you can get back to it once a second or once a minute, whatever works for you, but it takes a bunch of extra chips.  My first project I am going to do with a CPLD when I get that figured out is to put this circuit into my CPLD and hopefully give it multiple channels.
I have only come here seeking knowledge. Things they would not teach me of in college.

kf2qd

US Digital sells a chip that connects to the encoder and has a count up, count down output.

JoeN


US Digital sells a chip that connects to the encoder and has a count up, count down output.


Damn it, they stole my idea!  Or I stole their idea.  One or the other.  That was going to be my first CPLD project, now it will have to be better than their implementation (larger count or more channels at least) or I need a new project.

Link to this chip?
I have only come here seeking knowledge. Things they would not teach me of in college.

JoeN

Found it.  http://usdigital.com/products/interfaces/ics/lfls7083

Quote
The LSI Computer Systems LFLS7083 allow incremental shaft encoders to drive standard up/down counters. Connect the encoder quadrature outputs to the A and B inputs. The LFLS7083 outputs can connect directly to the up and down clock inputs of counters such as 74193 or 40193.

The next generation Encoder to Counter Interface chips are now available and recommended for new applications (DIP package, LFLS7183 / LFLS7184, or SOIC package, LFLS7183-S / LFLS7184-S ).


Well, that is not super impressive.  This is my circuit, without the 74193 counters.  Which means it is replacing two flip-flops and an inverter.  I think I can do better. :)
I have only come here seeking knowledge. Things they would not teach me of in college.

Go Up