Go Down

Topic: [SOLVED] Rotary Encoder only increments (Read 3295 times) previous topic - next topic

dougp

i had removed since it did not make a difference.
Since both channels are (presumably) electrically identical, I'd wire them both the same way.
Everything we call real is made of things that cannot be regarded as real.  If quantum mechanics hasn't profoundly shocked you, you haven't understood it yet. - Niels Bohr

No private consultations undertaken!

MarkT

change
Code: [Select]

  pinMode (PinA, INPUT);
  pinMode (PinB, INPUT);

to
Code: [Select]

  pinMode (PinA, INPUT_PULLUP);
  pinMode (PinB, INPUT_PULLUP);

And wire the encoder the standard way:
common to GND,
channels to pinA and pinB, no other connections, no physical resistors.

Then you have the standard setup.

Then check that the pins are being read correctly:
Code: [Select]

void loop ()
{
  Serial.print (digitalRead (pinA)) ; Serial.print (",") ; Serial.println (digitalRead (pinB)) ;
}

You can also use a multimeter to check the voltages on the pins directly as the encoder is turned
slowly.

And if this produces the expected results, then go back to the encoder logic.

Proceed step by step, from the most basic, checking everything at each stage is as expected
before proceeding to the next.  That way you are far less likely to get confused, or assume
something that you haven't actually checked.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

anishkgt

Tire @MarkT suggestion
Code: [Select]
int PinA = 6;
int PinB = 7;
int val;
int Counter = 1;
int PinALastState = LOW;
int pinAState = LOW;

void setup() {
  pinMode (PinA, INPUT_PULLUP);
  pinMode (PinB, INPUT_PULLUP);
  Serial.begin (9600);
}

void loop() {
  pinAState = digitalRead(PinA);
  if ((PinALastState == LOW) && (pinAState == HIGH))
  {
    if (digitalRead(PinA) == LOW) {
      Counter--;
    } else {
      Counter++;
    }
    Serial.print (digitalRead (PinA)) ; Serial.print (",") ; Serial.println (digitalRead (PinB)) ;
    //Serial.println(Counter);
  }
  PinALastState = pinAState;
}


The output is
1,0
1,0
1,1
1,1
1,1
1,1
1,1
1,1
1,1
1,0
1,0
1,0
1,0
1,1

dougp

Sifting through old posts last night I saw a thread - can't remember which topic - where the encoder itself was defective, IIRC it was made in a large country in the Orient. As a final check I suppose you could remove the Arduino connections and test the encoder in isolation. Wire up an LED and associated resistor to the channel B pin and see if there's any change when rotated.
Everything we call real is made of things that cannot be regarded as real.  If quantum mechanics hasn't profoundly shocked you, you haven't understood it yet. - Niels Bohr

No private consultations undertaken!

Jobi-Wan

Code: [Select]
void loop() {
  pinAState = digitalRead(PinA);
  if ((PinALastState == LOW) && (pinAState == HIGH))
  {
    // (... counter stuff ...)
    Serial.print (digitalRead (PinA)) ; Serial.print (",") ; Serial.println (digitalRead (PinB)) ;
    //Serial.println(Counter);
  }

You have put that line inside the "if ((PinALastState == LOW) && (pinAState == HIGH)) {}"
so it is normal that it only logs when pinA goes high. 
But at least you can see that pinB is sometimes low and sometimes high when this happens,
presumably/hopefully depending on the turn direction.

Southpark

Have you got a second or a third spare encoder to try? For comparison?

anishkgt

I had two but one of its lead came off.

So i just checked it with an LED and both seems to light up when connected. One turns off when i turn CW and the other CCW. I guess the encoder seems to be working then. am i correct ?

anishkgt

So one sketch that worked is

Code: [Select]
#define outputA 6
 #define outputB 7

 int counter = 0;
 int aState;
 int aLastState; 

 void setup() {
   pinMode (outputA,INPUT);
   pinMode (outputB,INPUT);
   
   Serial.begin (9600);
   // Reads the initial state of the outputA
   aLastState = digitalRead(outputA);   
 }

 void loop() {
   aState = digitalRead(outputA); // Reads the "current" state of the outputA
   // If the previous and the current state of the outputA are different, that means a Pulse has occured
   if (aState != aLastState){     
     // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
     if (digitalRead(outputB) != aState) {
       counter ++;
     } else {
       counter --;
     }
     Serial.print("Position: ");
     Serial.println(counter);
   }
   aLastState = aState; // Updates the previous state of the outputA with the current state
 }


here the wiring is different. The common is connected to the +5v and the pins A and B are connected in series with a 1k resitor.

Would appreciate if somebody could help with the previous code as in wiring the common to ground way as @MarkT had advised.

Jobi-Wan

Code: [Select]

     if (digitalRead(outputB) != aState) {
Since you compare B to A and not to HIGH or to LOW, I believe this should work regardless of whether you have common to +5 or to GND. (Otherwise you would have to swap the counter++ and counter--, or change != to ==)


Code: [Select]
  // If the previous and the current state of the outputA are different, that means a Pulse has occured
   if (aState != aLastState){    

Also, since you act on every state change of A, not just rising or just falling, this will probably give you 2 counts per click. Most encoders go through 4 changes per click:

Code: [Select]

   AB     AB
1  00 -> 01
2  01 -> 11
3  11 -> 10
4  10 -> 00


Your code will do a count on transitions 2 and 4.

anishkgt

Ok guess am getting somewhere
Code: [Select]
int PinA = 6;
int PinB = 7;
int val;
int Counter = 0;
int PinALastState = LOW;
int pinAState = LOW;

void setup() {
  pinMode (PinA, INPUT_PULLUP);
  pinMode (PinB, INPUT_PULLUP);
  Serial.begin (9600);
}

void loop() {
  pinAState = digitalRead(PinA);
  if (pinAState != PinALastState)
  {
    if (digitalRead(PinB) != pinAState) {
      Counter++;
    } else {
      Counter--;
    }
    Serial.println(Counter);
  }
  PinALastState = pinAState;
}


All works well but increments and decrements by 2 values.

MarkT

All works well but increments and decrements by 2 values.
Then just use (Counter>>1) whenever you want the position.
[ common pitfall: don't use (Counter/2), its not well behaved when the sign changes ]
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

anishkgt

Then just use (Counter>>1) whenever you want the position.
[ common pitfall: don't use (Counter/2), its not well behaved when the sign changes ]
well that did it. Seems to be ok now.

Southpark

#27
Jul 14, 2017, 12:14 am Last Edit: Jul 14, 2017, 12:48 am by Southpark
And now........ for the (optional) sequel ...... consider setting up interrupt pins and interrupt channels to detect a transition (like a high-to-low) transition of one of your encoder signals. And when a transition is detected.....read the values of the two encoder signals. Then get the program to make a decision (or do something) based on those readings.

Eg....when an interrupt occurs (when a falling edge of one signal is detected)..... one signal level maybe be low, while the other is high.... so increment. And, for a different condition....if one signal level is low and the other signal level is low.... decrement.

anishkgt

Well never knew i would really start that Sequel and i already have.

:) :) :)


Go Up