0

Rotary Encoder Help ?
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Rotary Encoder Help ?

by BillPretty on Sat Jul 17, 2021 4:43 pm

Does anyone have experience with rotary (quadrature) encoders ?
I appear to get two events for every click of rotation.

I am using python to debounce the switch:

Code: Select all | TOGGLE FULL SIZE
from gpiozero import Button
import time

input_A = Button( 18, bounce_time = .1)
input_B = Button( 23, bounce_time = .1)

old_a = True
old_b = True

def get_encoder_turn():
    # return -1, 0, or +1
    global old_a, old_b
    result = 0
    new_a = input_A.is_pressed
    new_b = input_B.is_pressed
    if new_a != old_a or new_b != old_b :
        if old_a == 0 and new_a == 1 :
            result = (old_b * 2 - 1)
        elif old_b == 0 and new_b == 1 :
            result = -(old_a * 2 - 1)
    old_a, old_b = new_a, new_b
    time.sleep(0.001)
    return result

x = 0

while True:
    change = get_encoder_turn()
    if change != 0 :
        x = x + change
        print(x)

BillPretty
 
Posts: 26
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

by adafruit_support_mike on Sun Jul 18, 2021 12:33 am

Both signals on the encoder change with each click, they just do it at different times. The code above will respond to both changes.

It looks like your code is similar to the running-sum decoding method, but can be simpler: just return 1 when channel A changes, -1 when channel B changes, and 0 if there's no change.

Then your variable 'x' in the while() loop will alternate between 0 and 1 when A changes first, and between -1 and 0 when B changes first.

Add a conditional to print the value of 'x' when it isn't 0, and you'll get one value that indicates direction per click.

adafruit_support_mike
 
Posts: 63716
Joined: Thu Feb 11, 2010 2:51 pm

Re: Rotary Encoder Help ?

by BillPretty on Sun Jul 18, 2021 7:22 am

Thanks for the help. The code is from a book I am reading, so I will try your method.

BillPretty
 
Posts: 26
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

by BillPretty on Sun Jul 18, 2021 5:01 pm

I tried to implement your idea without success.
While trouble shooting with a DVM (all I have) I noticed that the output of terminal A and B is a pulse
rather than a steady state. I think my function needs more tests, but I'm not sure how to do this.

Code: Select all | TOGGLE FULL SIZE
def get_encoder_turn():
    # return -1, 0, or +1
    global old_a, old_b
    result = 0
    new_a = input_A.is_pressed
    new_b = input_B.is_pressed

    if new_a != old_a :
        if old_a == 0 and new_a == 1 :
            result = 1

    if new_b != old_b :
   if old_b == 0 and new_b == 1:
       result = 1

    old_a, old_b = new_a, new_b
    time.sleep(0.01)
    return result
Attachments
OutputTable.jpg
OutputTable.jpg (9.86 KiB) Viewed 140 times

BillPretty
 
Posts: 26
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

by adafruit_support_mike on Mon Jul 19, 2021 12:48 am

The switch values don't matter.. only whether they've changed since the last time you read them:

Code: Select all | TOGGLE FULL SIZE
prev_a = 0
prev_b = 0

def check( a, b ):
   global prev_a, prev_b

   if ( a != prev_a ):
      prev_a = a
      return( 1 )
   
   if ( b != prev_b ):
      prev_b = b
      return( -1 )
   
   return( 0 )


count = 0

def direction( inc ):
   global count
   
   count += inc
   
   if (( inc != 0 ) and ( count != 0 )):
      print( count )



in_a = [ 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 ]
in_b = [ 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0 ]

for n in range( 0,16 ):
   direction( check( in_a[ n ], in_b[ n ] ) )
   
for n in range( 0,16 ):
   direction( check( in_a[ 15-n ], in_b[ 15-n ] ) )
The code above iterates the same set of switch values in opposite directions. Going forward produces 1, going backward produces -1.

The sequences have duplicate values to approximate reading the switches and seeing no change. The loops only produce output when a switch value changes, and the 'count' value is nonzero.

adafruit_support_mike
 
Posts: 63716
Joined: Thu Feb 11, 2010 2:51 pm

Re: Rotary Encoder Help ?

by BillPretty on Mon Jul 19, 2021 4:58 pm

Thanks to Google, I found a Python module called "Encoder" which I used to implement the following code:

Code: Select all | TOGGLE FULL SIZE
import Encoder
enc = Encoder.Encoder(18,23)
while True:
   x = enc.read()
   print (x)


I get the same results as with my other code (multiple events per click).
I believe I have a hardware problem so I intend to build the circuit shown below;
Attachments
EncoderCircuit 2.jpg
EncoderCircuit 2.jpg (26.92 KiB) Viewed 122 times

BillPretty
 
Posts: 26
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

by BillPretty on Thu Jul 29, 2021 8:42 pm

I have found that the following code works with the schematic shown above.
I used a 0.1uF capacitor and the circuit works reliably.
The 74HC14 works with a Vcc from 2 - 6 volts, so the circuit can also be used with the Arduino Uno.
The software uses a PWM (pin 10) of the Arduino to control the brightness of an LED.
The LED is connected to ground through a 270 ohm resistor.

Code: Select all | TOGGLE FULL SIZE

# This code works with the Schmitt trigger circuit
# It also talks to an Arduino Uno to control the
# brightness of an LED using a PWM pin (10) of the Arduino

import pyfirmata
from gpiozero import Button
import time

board = pyfirmata.Arduino('/dev/ttyACM0')
led_pin = board.get_pin(' d:10:p')

input_A = Button(18)
input_B = Button(23)

# Counter starts at 50 to avoid negative values
# Software needs a test for counter < 0 and > 100
counter=50
change = 0
 
LastState=input_A.is_pressed

while True:
   
   aState=input_A.is_pressed
   if aState > LastState:
      bState=input_B.is_pressed
      if bState != aState:
            counter = counter+1
      else:   
         counter = counter -1
      change = 1      
   if aState !=0 and change==1:
      print (counter)
      led_pin.write( counter / 100.0)
   LastState = aState
   change = 0


BillPretty
 
Posts: 26
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

by adafruit_support_mike on Sun Aug 01, 2021 4:35 am

Glad to hear you got things working. Happy hacking!

adafruit_support_mike
 
Posts: 63716
Joined: Thu Feb 11, 2010 2:51 pm

Please be positive and constructive with your questions and comments.