Arduino Forum

Using Arduino => General Electronics => Topic started by: anishkgt on Jul 12, 2017, 10:02 pm

Title: [SOLVED] Rotary Encoder only increments
Post by: anishkgt on Jul 12, 2017, 10:02 pm
Hi All,

Learning the rotary encoder and i've managed to get this far
Code: [Select]
int PinA = 6;
int PinB = 7;
int Counter = 10;
int PinALastState = LOW;
int pinAState = LOW;

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

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


for some reason the decrements do not seem to working it just increments no matter how i turn the knob.
Title: Re: Rotary Encoder only increments
Post by: vinceherman on Jul 12, 2017, 10:45 pm
Just guessing, but does the digital read of PinB ever go LOW?
I would write a test sketch to read both pins and print the values.
Then you should see something like this:

00
01
11
10

with possible repetitions. 
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 12, 2017, 10:55 pm
No Vince, Just increments like below
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 12, 2017, 10:59 pm
here is my wiring just one 10K resistor between pin A and GND(http://forum.arduino.cc/index.php?action=dlattach;topic=488987.0;attach=218680)
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 12, 2017, 11:19 pm
half through it comes like this
169
170
169
170
171
172
173
172
171
170
169
170
171
172
173
172
173
174
175
176
177
176
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 12, 2017, 11:25 pm
and after a reset
2
1
0
-1
-2
-3
-4
-5
-6
-5
-6
-5
-4
-5
-6
-5
-4
-5
-4
-3
-2
-1
0
1
2
3
4
3
2
1
2
1
2
Title: Re: Rotary Encoder only increments
Post by: dougp on Jul 12, 2017, 11:40 pm
here is my wiring just one 10K resistor between pin A and GND
Per the photo it doesn't look like the ground side of the resistor is connected to ground, maybe I'm not seeing well. Should you not also have a resistor to ground for channel B? What happens if you swap the blu/orn wires on the Arduino header?
Title: Re: Rotary Encoder only increments
Post by: Southpark on Jul 12, 2017, 11:47 pm
for some reason the decrements do not seem to working it just increments no matter how i turn the knob.
Check to see if you need to set the pinmode to "INPUT_PULLUP" or not.

Also.....  one end of your resistor doesn't even seem to be connected to anything. The leg is just connected to a rail, but nothing else is connected to it. If that resistor is needed..... then the problem here is..... you need to review the basics of bread-boards. The rows of little hole sockets in different sections of the bread-board are not always electrically-connected in the same direction.
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 12, 2017, 11:59 pm
Check to see if you need to set the pinmode to "INPUT_PULLUP" or not.

Also.....  one end of your resistor doesn't even seem to be connected to anything. The leg is just connected to a rail, but nothing else is connected to it. If that resistor is needed..... then the problem here is..... you need to re-learn/learn some things about breadboards.
changed the code to just INPUT and no visible change on the serial monitor.

The wiring is correct and the resistor is connected to GND and the other to pin A.
Title: Re: Rotary Encoder only increments
Post by: Southpark on Jul 13, 2017, 12:03 am
The wiring is correct and the resistor is connected to GND and the other to pin A.
The wiring is not correct in this photo you provided. If you go back to the bread-board manual, and look at the internal wiring of the bread-board along that rail.... you will find that your resistor leg is connected to nothing.

Take a look at the red coloured arrow.

Also, if you intend that resistor leg to be connected to ground, then probably need to make sure that it really needs to be connected to ground (ie.......the purpose of that resistor).

(http://forum.arduino.cc/index.php?action=dlattach;topic=488987.0;attach=218685)
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 13, 2017, 12:03 am
Per the photo it doesn't look like the ground side of the resistor is connected to ground, maybe I'm not seeing well. Should you not also have a resistor to ground for channel B? What happens if you swap the blu/orn wires on the Arduino header?
Added to resistor to pin B as well, no change. Swaped the wires in the arduino PINs A and B, no change there either.
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 13, 2017, 12:09 am
The wiring is not correct in this photo you provided. If you go back to the bread-board manual, and look at the internal wiring of the bread-board along that rail.... you will find that your resistor leg is connected to nothing.

Take a look at the red coloured arrow.
checked and for some reason i missed that. but i've correct it now, not thing noticeable change tho.

(http://forum.arduino.cc/index.php?action=dlattach;topic=488987.0;attach=218687)
Title: Re: Rotary Encoder only increments
Post by: dougp on Jul 13, 2017, 12:19 am
re: photo in post #11 - where is the resistor for channel B?
Title: Re: Rotary Encoder only increments
Post by: Delta_G on Jul 13, 2017, 12:20 am
Can you try what @vinceherman described in reply #1 and create a sketch that outputs the pin states instead of counting.  
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 13, 2017, 12:25 am
i had removed since it did not make a difference.

Tried the test what vinceherman mentioned and all seems to go high only.
Code: [Select]
int PinA = 6;
int PinB = 7;
int val;
int Counter = 1;
int PinALastState = LOW;
int pinAState = LOW;

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

void loop() {
  pinAState = digitalRead(PinA);
  if ((PinALastState == LOW) && (pinAState == HIGH))
  {
    if (digitalRead(PinA) == LOW) {
      Serial.println(0);
    } else {
      Serial.println(1);
    }
    //Serial.println(Counter);
  }
  PinALastState = pinAState;
}
Title: Re: Rotary Encoder only increments
Post by: dougp on Jul 13, 2017, 12:33 am
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.
Title: Re: Rotary Encoder only increments
Post by: MarkT on Jul 13, 2017, 02:19 am
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.
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 13, 2017, 01:55 pm
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
Title: Re: Rotary Encoder only increments
Post by: dougp on Jul 13, 2017, 03:15 pm
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.
Title: Re: Rotary Encoder only increments
Post by: Jobi-Wan on Jul 13, 2017, 03:43 pm
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.
Title: Re: Rotary Encoder only increments
Post by: Southpark on Jul 13, 2017, 05:17 pm
Have you got a second or a third spare encoder to try? For comparison?
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 13, 2017, 05:29 pm
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 ?
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 13, 2017, 05:38 pm
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.
Title: Re: Rotary Encoder only increments
Post by: Jobi-Wan on Jul 13, 2017, 06:03 pm
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.
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 13, 2017, 06:08 pm
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.
Title: Re: Rotary Encoder only increments
Post by: MarkT on Jul 13, 2017, 06:17 pm
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 ]
Title: Re: Rotary Encoder only increments
Post by: anishkgt on Jul 13, 2017, 06:57 pm
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.
Title: Re: [SOLVED] Rotary Encoder only increments
Post by: Southpark on Jul 14, 2017, 12:14 am
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.
Title: Re: [SOLVED] Rotary Encoder only increments
Post by: anishkgt on Jul 15, 2017, 03:16 pm
Well never knew i would really start that Sequel and i already have.

:) :) :)