{"id":16325316,"url":"https://github.com/ttitanua/micropython_rotary_encoder","last_synced_at":"2025-08-21T09:07:36.621Z","repository":{"id":65781545,"uuid":"599260410","full_name":"TTitanUA/micropython_rotary_encoder","owner":"TTitanUA","description":"This is a micropython raspberry pi pico encoder library.","archived":false,"fork":false,"pushed_at":"2024-04-25T13:06:00.000Z","size":35,"stargazers_count":17,"open_issues_count":3,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-30T08:55:05.650Z","etag":null,"topics":["micropython","raspbery-pi-pico","rotary-encoder"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TTitanUA.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-08T19:26:46.000Z","updated_at":"2025-03-23T16:14:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"e0d5eb0e-e2c4-4131-bcdb-0bc529e25240","html_url":"https://github.com/TTitanUA/micropython_rotary_encoder","commit_stats":{"total_commits":7,"total_committers":3,"mean_commits":"2.3333333333333335","dds":0.2857142857142857,"last_synced_commit":"20e7e9ed7925528e809980317e56a4f75cef0407"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/TTitanUA/micropython_rotary_encoder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TTitanUA%2Fmicropython_rotary_encoder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TTitanUA%2Fmicropython_rotary_encoder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TTitanUA%2Fmicropython_rotary_encoder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TTitanUA%2Fmicropython_rotary_encoder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TTitanUA","download_url":"https://codeload.github.com/TTitanUA/micropython_rotary_encoder/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TTitanUA%2Fmicropython_rotary_encoder/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271455195,"owners_count":24762701,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-21T02:00:08.990Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["micropython","raspbery-pi-pico","rotary-encoder"],"created_at":"2024-10-10T23:04:46.247Z","updated_at":"2025-08-21T09:07:36.603Z","avatar_url":"https://github.com/TTitanUA.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"This is an automatic translation, may be incorrect in some places. See sources and examples!\n# Rotary Encoder\nLibrary for Raspberry Pi Pico microcontroller encoder using MicroPython language.\nLibrary features:\n- Encoder: normal rotation, pressed rotation, fast rotation\n- Button: anti-rattle, hold, click, multiple clicks\n- Encoder button registration is optional\n- Interrupts are used for registering events\n- Events can be handled in several ways:\n    - With asyncio task (recommended)\n    - By interrupt timer\n    - Independent function call\n\nThe following materials were used to develop the library:\n- Library [Rotary Encoder](https://github.com/MikeTeachman/micropython-rotary) by Mike Teachman\n- Library (Arduino) [EncButton](https://github.com/GyverLibs/EncButton), by AlexGyver\n- Material [Rotary Encoder](https://www.coderdojotc.org/micropython/sensors/10-rotary-encoder/), by CoderDojoTC\n\n### Compatibility\n- MicroPython 1.19.1\n- Raspberry Pi Pico\n- Rotary Encoder EC11 (KY-040)\n\nOn the hardware above the library has been tested and works correctly.\nBut with small crutches, it can work on other equipment.\n\n### ATTENTION\nYou use this module at your own risk. \nMy experience in MicroPython programming is the whole 7 days. So there may be nuances that I haven't considered.\nIf you notice a bug or have suggestions for improvement, write to Issues.\n\n## Contents\n- [Install](https://github.com/TTitanUA/micropython_rotary_encoder#install)\n- [Initialization](https://github.com/TTitanUA/micropython_rotary_encoder#init)\n- [Documentation](https://github.com/TTitanUA/micropython_rotary_encoder#doc)\n- [Examples](https://github.com/TTitanUA/micropython_rotary_encoder/tree/main/examples)\n- [Bugs and feedback](https://github.com/TTitanUA/micropython_rotary_encoder#feedback)\n\n\u003ca id=\"install\"\u003e\u003c/a\u003e\n## Installation\n- Install the library via pip (Thonny -\u003e Manage Packages) by name **micropython-rotary-encoder**\n- Or manual installation:\n   - [Download library from github](https://github.com/TTitanUA/micropython_rotary_encoder/)\n   - take the **micropython_rotary_encoder** folder from the archive.\n   - upload to the root of the microcontroller or to the **lib** folder.\n\nIf you want to play around with the logic of the library, then the 2nd installation option is preferable. :)\n\n\u003ca id=\"init\"\u003e\u003c/a\u003e\n## Usage\n### Initialization\n```python\nfrom machine import Pin\nfrom micropython_rotary_encoder import RotaryEncoderRP2, RotaryEncoderEvent\n\n# create pins for encoder and button\nen_pin_clk = Pin(15, Pin.IN, Pin.PULL_UP)\nen_pin_dt = Pin(9, Pin.IN, Pin.PULL_UP)\nen_pin_sw = Pin(8, Pin.IN, Pin.PULL_UP)\n\n# create an encoder object\nencoder = RotaryEncoderRP2(en_pin_clk, en_pin_dt, en_pin_sw)\n```\nAfter initialization, the encoder automatically subscribes to encoder and button pin interrupts.\nBut encoder event processing must be started manually.\n\n#### Using the uasyncio library\nThis is the best option for most projects.\n```python\n# at the beginning of the file add the import of the uasyncio library\nimport uasyncio as asyncio\n\n# ----\n# Encoder initialization code above ^\n# ----\n\nasync def async_some_other_task():\n    print(\"async_some_other_task\")\n    while True:\n        await asyncio.sleep(1)\n\nasync def main():\n    await asyncio.gather(\n        encoder.async_tick(1), # run encoder event handling every 1ms\n        async_some_other_task(),\n    )\n\nasyncio.run(main())\n```\n\n#### With timer interrupts\nYou can read more about timers [here](https://docs.micropython.org/en/latest/library/machine.Timer.html)\nFor Raspberry Pi Pico [here](https://docs.micropython.org/en/latest/rp2/quickref.html#timers)\nBe careful, although this is the easiest option, it is not optimal.\nSince encoder events are handled in a timer interrupt, other interrupts will be delayed.\n```python\n# ----\n# Encoder initialization code above ^\n# ----\n\nencoder.timer_tick(1) # запускаем обработку событий энкодера каждые 1 мс\n```\n\n#### By manual call\nEverything is in your hands, but don't forget to call the `raw_tick()` method every 1 - 5 ms.\n```python\nimport utime\n# ----\n# Encoder initialization code above ^\n# ----\n\nwhile True:\n    encoder.raw_tick() # handle encoder events\n    utime.sleep_ms(1) # delay\n```\n\n\u003ca id=\"doc\"\u003e\u003c/a\u003e\n## Documentation\n### Constructor parameters\n\n| Parameter    | Type | Default | Description                            |\n|--------------|------|---------|----------------------------------------|\n| pin_clk      | pin  | None    | Pin CLK encoder                        |\n| pin_dt       | pin  | None    | Pin DT encoder                         |\n| pin_sw       | pin  | None    | Pin buttons                            |\n| debounce_ms  | int  | 50      | Contact bounce timeout                 |\n| encoder_step | int  | 1       | Encoder step                           |\n| half_step    | bool | False   | Increment every 1/2 gray cycle         |\n| hold_ms      | int  | 1000    | Button hold timeout                    |\n| step_ms      | int  | 200     | Timeout between encoder events         |\n| fast_ms      | int  | 50      | Timeout between encoder events on hold |\n| click_ms     | int  | 400     | Timeout between button presses         |\n\n- `pin_clk`, `pin_dt` - encoder pins, if one of them is not specified, then the library will work only in button mode.\n- `pin_sw` - optional parameter, if not specified, the library will work only in encoder mode.\n- `debounce_ms` - contact bounce timeout, protection against false positives of the button.\n- `encoder_step` - encoder step, this is the number of encoder events before triggering.\nFor example, if the step is 1, then each encoder event will fire a trigger.\nIf the step is 2, then the trigger will fire on every second encoder event.\nUseful for compensating for encoder chatter.\n- `half_step` - increments every half-step. Added to support the KY-040 encoder, which only moves half a cycle (1 CLK + 1 DT transition) every physical detent. Allows intuitive operation when used for UI control. When this is true, the encoder_step units will be half-steps.\n- `hold_ms` - button hold timeout, if the button is held longer than this time, the `HELD` event will fire.\n- `step_ms` - timeout between multiple clicks, if click events occur faster than this time, the `MULTIPLE_CLICK` event will fire.\n- `fast_ms` - timeout between encoder events for fast scrolling `TURN_LEFT_FAST | TURN_RIGHT_FAST`.\n- `click_ms` - timeout between clicking and releasing the button for the `CLICK` event.\n\n### События\nEncoder/button events are passed to callbacks, which can be registered with the `on()` method.\n\n| Event                | Parameters passed to callback | Trigger condition                                                   |\n|----------------------|-------------------------------|---------------------------------------------------------------------|\n| ANY                  | event_id: int, clicks: int    | Duplicate any event                                                 |\n| CLICK                | None                          | The button was pressed and released in `click_ms`                   |\n| MULTIPLE_CLICK       | clicks: int                   | The button was pressed, released and pressed again within `step_ms` |\n| HELD                 | None                          | Button held longer `hold_ms`                                        |\n| RELEASE              | None                          | The button was released after `HELD`                                |\n| TURN_LEFT            | None                          | The encoder has been turned to the left                             |\n| TURN_LEFT_FAST       | None                          | The encoder was turned faster than `fast_ms`                        |\n| TURN_LEFT_HOLD       | None                          | The encoder was turned to the left and with the                     |\n| TURN_LEFT_FAST_HOLD  | None                          | The encoder was turned faster than `fast_ms` and with the           |\n| TURN_RIGHT           | None                          | The encoder has been turned to the right                            |\n| TURN_RIGHT_FAST      | None                          | The encoder was turned faster than `fast_ms`                        |\n| TURN_RIGHT_HOLD      | None                          | The encoder was turned to the right and with the pressed button     |\n| TURN_RIGHT_FAST_HOLD | None                          | The encoder was turned faster than `fast_ms` and with the           |\n\n### Register callbacks\nTo register callbacks, you need to use the `on(event, callback)` method, which takes two parameters.\n- `event` - event, property of the `RotaryEncoderEvent` class.\n- `callback` - a function that will be called when the event fires.\nThe number of arguments to the callback function depends on the event. See table above.\n\n```python\n\n# ----\n# Encoder initialization code above ^\n# ----\n\n# subscribe to encoder events\ndef on_click():\n    print(\"CLICK\")\n    \ndef on_multy_clicks(clicks: int):\n    print(f\"CLICK {clicks} times\")\n\ndef on_any(event_id: int, clicks: int):\n    print(f\"ANY {event_id}, clicks {clicks}\")\n\nencoder.on(RotaryEncoderEvent.CLICK, on_click)\nencoder.on(RotaryEncoderEvent.MULTIPLE_CLICK, on_multy_clicks)\nencoder.on(RotaryEncoderEvent.ANY, on_any)\n```\n\n### Unsubscribing from events\nTo unsubscribe from events, you need to use the `off(event, callback)` method, which takes two parameters.\n- `event` - event, property of the `RotaryEncoderEvent` class.\n- `callback` - a link to a function that was registered earlier.\nFor one method call, only one callback from one event is unsubscribed.\n\n```python\n# ----\n# Callback registration code above ^\n# ----\n\n# unsubscribe from the encoder event\nencoder.off(RotaryEncoderEvent.CLICK, on_click)\n\n# example with multiple subscription\nencoder.on(RotaryEncoderEvent.CLICK, on_click) # subscribe first\nencoder.on(RotaryEncoderEvent.CLICK, on_click) # subscribe second\n\nencoder.off(RotaryEncoderEvent.CLICK, on_click) # unsubscribe first\n```\n\n### Unsubscribe from all events\nTo unsubscribe from all events, you need to use the `off_all()` method, which takes two parameters.\n- `event` - event, property of the `RotaryEncoderEvent` class.\n- `callback` - a reference to a function that was registered earlier, if it is not passed, then all listeners of this event will be unsubscribed.\n\n```python\n# ----\n# Encoder initialization code above ^\n# ----\ndef on_click():\n    print(\"CLICK\")\n\ndef on_click2():\n    print(\"CLICK2\")\n\n\nencoder.on(RotaryEncoderEvent.CLICK, on_click) # subscribe first, with callback on_click\nencoder.on(RotaryEncoderEvent.CLICK, on_click2) # subscribe second, with callback on_click2\nencoder.on(RotaryEncoderEvent.CLICK, on_click) # subscribe third, with callback on_click\n\n# unsubscribe from the RotaryEncoderEvent.CLICK event only listeners with the on_click callback function\nencoder.off_all(RotaryEncoderEvent.CLICK, on_click) # unsubscribe all `on_click` listeners from event RotaryEncoderEvent.CLICK\n\n# unsubscribe from the RotaryEncoderEvent.CLICK event of all listeners\nencoder.off_all(RotaryEncoderEvent.CLICK) # unsubscribe all listeners from event RotaryEncoderEvent.CLICK\n```\n\n## Examples\nExamples of using the encoder can be found in the [examples](https://github.com/TTitanUA/micropython_rotary_encoder/tree/main/examples) folder.\n\n\u003ca id=\"feedback\"\u003e\u003c/a\u003e\n## Bugs and feedback\nIf you find bugs, create [issue](https://github.com/TTitanUA/micropython_rotary_encoder/issues).\nThe library is open for revision and your [pull requests](https://github.com/TTitanUA/micropython_rotary_encoder/pulls).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttitanua%2Fmicropython_rotary_encoder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fttitanua%2Fmicropython_rotary_encoder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttitanua%2Fmicropython_rotary_encoder/lists"}