Encoder not working on Pico 2W #17082
Replies: 13 comments 6 replies
-
|
There is a problem with RP2350 pins when used as inputs - see this issue. I'm not sure if this is relevant to the basic encoder script, but it will almost certainly affect the RP2 version which uses the PIO. In my view the |
Beta Was this translation helpful? Give feedback.
-
|
Re PIO solutions you might like to try the workround here. As written it fixes GPIO numbers 0 and 1, but check the RP2350 manual for the means of adapting to other pins. In my testing PIO input was utterly broken without that code. There is another possible issue in that the signals from mechanical encoders aren't particularly clean logic signals. I use 1KΩ pullups to try to get reasonably fast transitions. It is possible that the revised hardware/firmware is particularly intolerant of these signals. To put this into context, the portable driver has been used on a wide range of platforms (STM32, ESP32, ESP8266, RP2040, and probably others) without problems. As a general point, given that you're using |
Beta Was this translation helpful? Give feedback.
-
|
Assume a mechanical encoder linked to 0v, with 1KΩ pullups to 3V3: if the voltage swing isn't 0-3.3V, something is electrically very wrong. |
Beta Was this translation helpful? Give feedback.
-
|
I have now tested from machine import Pin
from encoder_portable import Encoder
from time import sleep
px = Pin(0, Pin.IN)
py = Pin(1, Pin.IN)
e = Encoder(px, py)
while True:
print(e.position())
sleep(1)I haven't yet tested the PIO version, but I would expect it to be problematic without the fix I identified above. |
Beta Was this translation helpful? Give feedback.
-
|
@tgnorman A few points.
|
Beta Was this translation helpful? Give feedback.
-
|
My advice is to use There is no need to use the
Or even damage. |
Beta Was this translation helpful? Give feedback.
-
|
Hi Peter, hope you are well. I sorted my issues with encoders… but am now between a rock and a hard place with Pushbutton.py.
I have been happily using your classes on a Pico 2 W… running a prototype of a major project, with a 5-way navigation switch mounted on a breadboard, wired to my Pico 2. Works a treat… including long and double-press logic. So… I finally got to make a PCB, mounted a second Pico 2 W on it… and Pushbutton would ONLY recognise long presses. Hmm… Initially I suspected some weird grounding issues on my PCB, but… no.
I have scoped the voltage on the GPIO pin… a very nice, clean transition from 3.3V to 0V, so electrically it should be fine.
I have now changed the switch, the connecting cable, the Pico 2 , and MicroPython release version. Even a different USB power cable. I added code to record the delay between falling and rising edges… around 100-160 ms. So, well above the 40 ms debounce time, well below the 400 ms double-click time… and yet, it never registers a single click.
I am of course using Pin.PULL_UP… My current dog’s breakfast of wires in my prototype WORKS… every other setup fails !! And I really want to migrate to a PCB… but am quite stuck. Many hours on ChatGPT has produced no joy… I am now desperate, and hope you don’t mind me reaching out to you directly.
I have attached my modified version of your test script… and pasted below also in case a mail agent has a spit over the attachment! Also, some typical output: Which shows long_func being triggered… but never press_func.
Hoping you can shed some illumination on this frustrating failure mode!
Many thanks in advance… your asyncio repo is a goldmine…
From my VS terminal:
MicroPython v1.25.0 on 2025-04-15; Raspberry Pi Pico 2 W with RP2350 # same result using v1.27.0…
Test script:
from machine import Pin
import asyncio
from Pushbutton import Pushbutton
from utime import ticks_ms
btn = Pin(14, Pin.IN, Pin.PULL_UP) # Adapt for your hardware
t1 = t2 = 0
def irq_test(pin):
global t1, t2
v = pin.value()
# t1 = 0
if v == 0:
t1 = ticks_ms()
print("Falling EDGE", v)
else:
t2 = ticks_ms()
delay = t2 - t1 #type: ignore
print(f'Rising EDGE {v} {delay=}ms')
btn.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=irq_test)
async def main():
pb = Pushbutton(btn, suppress=True)
pb.press_func(print, ("PRESS",)) #type: ignore
pb.release_func(print, ("RELEASE",)) #type: ignore
pb.double_func(print, ("DOUBLE",)) #type: ignore
pb.long_func(print, ("LONG",)) #type: ignore
await asyncio.sleep(60) # Run for one minute
asyncio.run(main())
And here’s my result…
Falling EDGE 0
Rising EDGE 1 delay=110ms
Falling EDGE 0
Rising EDGE 1 delay=131ms
Falling EDGE 0
Rising EDGE 1 delay=142ms
Falling EDGE 0
Rising EDGE 1 delay=107ms
Rising EDGE 1 delay=108ms
Rising EDGE 1 delay=108ms
Falling EDGE 0
LONG
Rising EDGE 1 delay=1723ms
Falling EDGE 0
Rising EDGE 1 delay=110ms
Falling EDGE 0
LONG
Rising EDGE 1 delay=2038ms
From: Peter Hinch ***@***.***>
Sent: Friday, 11 April 2025 2:27 AM
To: micropython/micropython ***@***.***>
Cc: tgnorman ***@***.***>; Mention ***@***.***>
Subject: Re: [micropython/micropython] Encoder not working on Pico 2W (Discussion #17082)
My advice is to use encoder_portable with a simple mechanical encoder and (preferably) 1KΩ pullups. Connect the common of the encoder to gnd and the pullups to 3.3V. This will work on any RP2. Then you needn't worry about Pin/PIO problems or chip steppings.
There is no need to use the encoder_rp2 version for a switch - it is intended for use with fast optical or magnetic encoders.
—
Reply to this email directly, view it on GitHub <#17082 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/AL5KWZKKYXH5R5ODELS7WPL2Y2PD5AVCNFSM6AAAAAB2RAIGEOVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTENZZGQZTONI> .
You are receiving this because you were mentioned. <https://github.com/notifications/beacon/AL5KWZKC4B4IRFMLRRBKN532Y2PD5A5CNFSM6AAAAAB2RAIGEOWGG33NNVSW45C7OR4XAZNRIRUXGY3VONZWS33OINXW23LFNZ2KUY3PNVWWK3TUL5UWJTQAYM5AO.gif> Message ID: ***@***.*** ***@***.***> >
|
Beta Was this translation helpful? Give feedback.
-
|
Your code works fine here on a Pico 2W after correcting the capitalisation: from pushbutton import Pushbutton # File is pushbutton.pyI can't think of a reason why only long presses are detected. The only reason why adding a second RP2 should cause it to fail is some kind of electrical issue. |
Beta Was this translation helpful? Give feedback.
-
|
Peter, I had forgotten some details that now appear relevant… my apology.
When I first started using your repo, I could not see launch.py. ChatGPT provided me something that seemed to work… but, digging deeper into what is now failing, it is clear it is the launch method. I’ve looked again on your repo… but cannot see launch.py.
What am I missing?
I have cut&paste the launch I’ve been using for the last year (with a couple print statements thrown in). I still have no idea why this always works on one Pico and only sometimes on another (running the same MP build). Very odd behaviour!
# Note: slightly modified version of Peter Hinch's version... works on Pico
import uasyncio as asyncio
def launch(func, args=()):
print(f'launch {func}')
if hasattr(func, '__call__'):
print(f'launch calling {func}')
res = func(*args)
if hasattr(res, '__await__'): # It's a coroutine
asyncio.create_task(res)
The other confession… I was using a bespoke version of delay_ms. Can’t recall why, as this IS in your repo, which I’ve now tried… but this revels something else is amiss. On my old breadboard system… the press_func is called – but then, I get the same error as on my other platform… Note that I modified the “from . import launch” to vanilla “import launch, as my Pico doesn’t like relative imports. I’m assuming this is innocuous… but in the spirit of full disclosure…
Output is this:
Falling EDGE 0
PRESS # woohoo… this gets printed! That’s progress… (It also prints on my other Pico system…at least it is now consistent)
Rising EDGE 1 delay=151ms
RELEASE
Task exception wasn't retrieved
future: <Task> coro= <generator object '_timer' at 200143b0>
Traceback (most recent call last):
File "asyncio/core.py", line 1, in run_until_complete
File "delay_ms.py", line 49, in _timer
TypeError: 'module' object isn't callable
My head is spinning… it seems something is badly broken, I really don’t get why this started happening. The only thing I’ve done recently is updated my version of VS Code… again, I’d have thought this could not impact things.
Sorry for the lengthy emails – but I don’t know where else to seek advice. I feel I should at least buy you a beer or something!
Cheers,
T.
From: Peter Hinch ***@***.***>
Sent: Sunday, 22 March 2026 10:38 PM
To: micropython/micropython ***@***.***>
Cc: tgnorman ***@***.***>; Mention ***@***.***>
Subject: Re: [micropython/micropython] Encoder not working on Pico 2W (Discussion #17082)
Your code works fine here on a Pico 2W after correcting the capitalisation:
from pushbutton import Pushbutton # File is pushbutton.py
I can't think of a reason why only long presses are detected. The only reason why adding a second RP2 should cause it to fail is some kind of electrical issue.
—
Reply to this email directly, view it on GitHub <#17082?email_source=notifications&email_token=AL5KWZIIJTROK2XF3KOYKZ34R7JSNA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCNRSGU3DGMBSUZZGKYLTN5XKO3LFNZ2GS33OUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#discussioncomment-16256302> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/AL5KWZOCLBDPNWRHQUXSKWT4R7JSNAVCNFSM6AAAAACW2B6A42VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTMMRVGYZTAMQ> .
You are receiving this because you were mentioned. <https://github.com/notifications/beacon/AL5KWZNDAMLTFEI3VMOYJ3D4R7JSNBFCNFSM6AAAAACW2B6A42WGG33NNVSW45C7OR4XAZNRIRUXGY3VONZWS33OINXW23LFNZ2KUY3PNVWWK3TUL5UWJTQA7AGS5JTSMVQXG33OU5WWK3TUNFXW4.gif> Message ID: ***@***.*** ***@***.***> >
|
Beta Was this translation helpful? Give feedback.
-
There is no problem with relative imports on the Pico. The primitives directory relies on them, with |
Beta Was this translation helpful? Give feedback.
-
|
Thanks Peter… I’ll check that out.
Meanwhile… I have found the root cause of my mysterious behaviour. I do not know when/how/why… but the second Pico I was using in my tests had a different (old?) version of launch.py…
It’s about 1AM where I am (South Australia), so I’m not going to try to figure that out tonight… I feel pretty stupid having put so many debug prints all over the place… and did not twig to this difference. I apologise for wasting your time… I should have been more thorough in my debugging…
And you have answered my query about the location of launch.py… which I just looked at – and that is different code again. I confess I never did do the full install of your repo… when I started using a Pico 1, I would not have had sufficient space (my project is quite large, and creates a lot of log data) so… I just installed what I needed. Seems this piecemeal approach has come back to bite me.
Many thanks for helping me out, you are most kind.
Cheers,
T.
From: Peter Hinch ***@***.***>
Sent: Tuesday, 24 March 2026 10:14 PM
To: micropython/micropython ***@***.***>
Cc: tgnorman ***@***.***>; Mention ***@***.***>
Subject: Re: [micropython/micropython] Encoder not working on Pico 2W (Discussion #17082)
my Pico doesn’t like relative imports
There is no problem with relative imports on the Pico. The primitives directory relies on them, with launch residing in __init__.py. I strongly advise you install them as described here <https://github.com/peterhinch/micropython-async/blob/master/v3/docs/TUTORIAL.md#01-installing-asyncio-primitives> and call them as recommended in the tutorial.
—
Reply to this email directly, view it on GitHub <#17082?email_source=notifications&email_token=AL5KWZPOWQ5T7JXJQZQLAD34SJYI5A5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCNRSHEZDGMBTUZZGKYLTN5XKO3LFNZ2GS33OUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#discussioncomment-16292303> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/AL5KWZOQQL4BUAEWKTFN4X34SJYI5AVCNFSM6AAAAACW2B6A42VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTMMRZGIZTAMY> .
You are receiving this because you were mentioned. <https://github.com/notifications/beacon/AL5KWZMXA3HXVZFQT2Y4P6L4SJYI5BFCNFSM6AAAAACW2B6A42WGG33NNVSW45C7OR4XAZNRIRUXGY3VONZWS33OINXW23LFNZ2KUY3PNVWWK3TUL5UWJTQA7CM47JTSMVQXG33OU5WWK3TUNFXW4.gif> Message ID: ***@***.*** ***@***.***> >
|
Beta Was this translation helpful? Give feedback.
-
If your concern is RAM space, if you study |
Beta Was this translation helpful? Give feedback.
-
|
Thankyou Peter. On the Pico2 I have enough RAM… but have ongoing issue with Flash space. I regularly email my log data, but have work to do on improving log rolling and space management.
I will do a FULL install… and then remove what I don’t need.
Cheers,
From: Peter Hinch ***@***.***>
Sent: Wednesday, 25 March 2026 3:12 AM
To: micropython/micropython ***@***.***>
Cc: tgnorman ***@***.***>; Mention ***@***.***>
Subject: Re: [micropython/micropython] Encoder not working on Pico 2W (Discussion #17082)
I never did do the full install of your repo… when I started using a Pico 1, I would not have had sufficient space
If your concern is RAM space, if you study __init__.py you will see it performs lazy imports: modules are only loaded into RAM if they are explicitly imported. If the concern is Flash space you can delete unused modules - but you must leave __init__.py.
—
Reply to this email directly, view it on GitHub <#17082?email_source=notifications&email_token=AL5KWZIIHTJLUPH7EPXRCJD4SK3GJA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCNRSHE3DENBRUZZGKYLTN5XKO3LFNZ2GS33OUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#discussioncomment-16296241> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/AL5KWZNJ6QJMOCRJR62Z3V34SK3GJAVCNFSM6AAAAACW2B6A42VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTMMRZGYZDIMI> .
You are receiving this because you were mentioned. <https://github.com/notifications/beacon/AL5KWZM2U5CHYT4BISFPMUD4SK3GJBFCNFSM6AAAAACW2B6A42WGG33NNVSW45C7OR4XAZNRIRUXGY3VONZWS33OINXW23LFNZ2KUY3PNVWWK3TUL5UWJTQA7CUTDJTSMVQXG33OU5WWK3TUNFXW4.gif> Message ID: ***@***.*** ***@***.***> >
|
Beta Was this translation helpful? Give feedback.



Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi,
I have a rotary encoder that was working just fine on a Pico 1 W, using Peter Hinch's asyncio encoder. I was forced to migrate to Pico 2 as I needed more memory, but the same code does not trigger any interupts on the Pico 2. I am using Micropython v1.25.0-preview.380.g226434055.
Encoder driver form https://github.com/peterhinch/micropython-samples/blob/master/encoders/ENCODERS.md
I am using encoder.py... not encoder_rp2.py, which to be honest, I didn't find until today. encoder_rp2.py generates interupts, but the values generated are"interesting"... encoder.py does not do anything on Pico 2.
Hardware is fine.. works with my simple IRQ that just compares encoder Pin values, but Peter's code is rather more elegant ;-)
However, the reason for reporting the issue here is that there seems to be something broken in v1.25 ... at least, running on a Pico 2.
Beta Was this translation helpful? Give feedback.
All reactions