Rotary Encoder Help ?

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
BillPretty
 
Posts: 28
Joined: Sun Mar 07, 2021 2:44 pm

Rotary Encoder Help ?

Post by BillPretty »

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

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)

User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: Rotary Encoder Help ?

Post by adafruit_support_mike »

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.

User avatar
BillPretty
 
Posts: 28
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

Post by BillPretty »

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

User avatar
BillPretty
 
Posts: 28
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

Post by BillPretty »

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

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 209 times

User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: Rotary Encoder Help ?

Post by adafruit_support_mike »

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

Code: Select all

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.

User avatar
BillPretty
 
Posts: 28
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

Post by BillPretty »

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

Code: Select all

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 191 times

User avatar
BillPretty
 
Posts: 28
Joined: Sun Mar 07, 2021 2:44 pm

Re: Rotary Encoder Help ?

Post by BillPretty »

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


# 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


User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: Rotary Encoder Help ?

Post by adafruit_support_mike »

Glad to hear you got things working. Happy hacking!

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”