Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Rotaryio] filtered rotary encoder always has a position of 0 when connected to a RP2350b #10037

Open
timothyBoye opened this issue Feb 7, 2025 · 6 comments

Comments

@timothyBoye
Copy link

CircuitPython version and board name

Adafruit CircuitPython 9.2.4-7-g1c0b37e504 on 2025-02-04; Pimoroni Pico Plus 2 W with rp2350b

Code/REPL

import board
import rotaryio
import time

encoder = rotaryio.IncrementalEncoder(board.GP15, board.GP14)

while True:
    time.sleep(0.1)
    print(encoder.position)


# Code to test output of encoder using digitalio
#
# import board
# import digitalio
# import time

# encoderpin1 = digitalio.DigitalInOut(board.GP14)
# encoderpin2 = digitalio.DigitalInOut(board.GP15)
# encoderpin1.direction = digitalio.Direction.INPUT
# encoderpin2.direction = digitalio.Direction.INPUT

# while True:
#     time.sleep(0.1)
#     print(encoderpin1.value, " - ", encoderpin2.value)

Behavior

Rotaryio position of a rotary encoder attached to an external filter circuit then to GPIO pins 14 and 15 on a Pimoroni Pico Plus 2W (RP2350b) does not change when turned.

Description

I have an EC12E type rotary encoder connected to a Pimoroni Pico Plus 2 W (GPIO14 and 15). The encoder uses the recommended external filter circuit from the datasheet (see image) rather than connect directly to the board.
Image

If I try to use rotaryio the position never updates, it's constantly stuck on a position value of 0. However, if I read the encoder pins as digitalio inputs I can see both pins read True by default and when I spin the encoder I can see it flipping between True and False as you would expect.

This seems to be the same behaviour as #9695 but this was reported fixed in PR #9682, a further RP bug was reported #10024 which references these but this was also reported fixed by PR #10025.

Additional information

I attempted to use the same board with a spare encoder and no filtering circuit and that did seem to work with rotaryio and so I thought that the circuit might be at fault.

I have a handheld multimetre which has some basic oscilloscope functionality. So I hooked it up to the GPIO and when using rotaryio I can see the state as high but the low signal does not seem to be returning to GND it hovers at what looks like around halfway between the high signal and GND (if my multimetre has a way to see the actual voltage number on the oscilloscope graph I don't know how). I thought there might be a slight short so I checked the pins and cleaned the board, no change.

I then thought to check those same pins connected to the same filtered encoder circuit but using digitalio instead of rotaryio, using the oscilloscope to measure that, the circuit is going to GND properly as the encoder is turned. This implies to me that the circuit does not have a short or anything like that and that is has to be something about how rotaryio is implemented that is different to just reading the pins using digitalio.

I can only deduce that either the way this circuit is designed is incompatible with rotaryio or something about how roraryio works has a bug for RP2350b when using an external filtering circuit like this.

@timothyBoye timothyBoye added the bug label Feb 7, 2025
@todbot
Copy link

todbot commented Feb 7, 2025

I just verified this on Pico 2 RP2350. The issue is with the series resistors. Having the external pull-up resistors and the filtering caps are fine. Add the series resistors and rotaryio stops registering pulses. Use 1k resistors instead of 10k and it works. (Seems almost like this is somehow related to the RP2350 E9 errata)

On Pico RP2040, rotaryio works in all cases. Adding the series resistors or any of the other external components in that filter circuit does not affect functionality.

@timothyBoye, as a workaround, omit the series resistors or use 1k. Or omit the entire filter circuit: most designs do not use them; see, I think, any Adafruit product that use a rotary encoder. (e.g. 1, 2)

@timothyBoye
Copy link
Author

@todbot thanks Tod! Your work around should be easy to do on the PCB just need to desolder those resistors and replace with a wire. Will try tomorrow.

@tannewt tannewt added the rp235x label Feb 7, 2025
@tannewt tannewt added this to the Support milestone Feb 7, 2025
@timothyBoye
Copy link
Author

I removed those resistors and bridged the connection where they were, but kept the the caps and pull up resistors. Testing the rotaryio code again all looks good, it is registering the encoder turns now and updating the position in both directions correctly. Thanks again @todbot for the support.

Should I close this issue as there is a workaround, or leave it open for a CircuitPython fix?

@dhalbert
Copy link
Collaborator

dhalbert commented Feb 8, 2025

Should I close this issue as there is a workaround, or leave it open for a CircuitPython fix?

I think, yes, this is probably an E9 problem. There's no fix except to document not to use a >8.2k resistor to ground.

Just to be clear, are you still using 5V pullups? 3.3v would be fine and safer for the RP2350B, depite the "5v tolerant" verbiage. See https://forums.raspberrypi.com/viewtopic.php?t=375118 for background.

@dhalbert dhalbert modified the milestones: Support, 9.x.x Feb 8, 2025
@todbot
Copy link

todbot commented Feb 8, 2025

Yes upon further reflection, this is another variation of RP2350 E9 problem. The series resistor turns into a pull-down when the encoder pulse happens.

@timothyBoye
Copy link
Author

timothyBoye commented Feb 9, 2025

The 5v I did without thinking as I was just blindly following the data sheet forgetting the rp2350 is a 3.3V device primarily. In my attempt to debug the encoder not working I thought that the 5V might have been the problem so I cut the 5V line before the pull-ups and instead tied it to the 3.3V line (this was before I posted this issue). So it was originally 5V -> 10k ohm -> encoder pin -> 10k ohm -> 0.1uf cap -> pico gpio, but i changed it before i posted the issue to 3.3V -> 10k ohm -> encoder pin -> 10k ohm -> 0.1uf cap -> pico gpio to see if that would fix it and neither had worked.

As you suggested I removed the series resistors but left the pullup resistors which worked. So it's now 3.3V -> 10k ohm -> encoder pin -> 0.1uf cap -> pico gpio. Hopefully that makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants