{"id":13581329,"url":"https://github.com/mathertel/OneButton","last_synced_at":"2025-04-06T07:31:56.028Z","repository":{"id":12835263,"uuid":"15510723","full_name":"mathertel/OneButton","owner":"mathertel","description":"An Arduino library for using a single button for multiple purpose input.","archived":false,"fork":false,"pushed_at":"2024-08-02T15:36:29.000Z","size":150,"stargazers_count":1025,"open_issues_count":8,"forks_count":236,"subscribers_count":53,"default_branch":"master","last_synced_at":"2025-04-01T07:49:56.644Z","etag":null,"topics":["arduino","arduino-library","button"],"latest_commit_sha":null,"homepage":"http://www.mathertel.de/Arduino/OneButtonLibrary.aspx","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mathertel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2013-12-29T15:49:49.000Z","updated_at":"2025-03-26T08:38:12.000Z","dependencies_parsed_at":"2024-09-24T13:44:52.460Z","dependency_job_id":"960ac280-25bf-4b3e-9e60-f299c4b25faf","html_url":"https://github.com/mathertel/OneButton","commit_stats":{"total_commits":141,"total_committers":25,"mean_commits":5.64,"dds":"0.45390070921985815","last_synced_commit":"0cebe0c726cbb535941e49ccdc156443a8a7aaf1"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathertel%2FOneButton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathertel%2FOneButton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathertel%2FOneButton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathertel%2FOneButton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mathertel","download_url":"https://codeload.github.com/mathertel/OneButton/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247450136,"owners_count":20940861,"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","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":["arduino","arduino-library","button"],"created_at":"2024-08-01T15:02:00.404Z","updated_at":"2025-04-06T07:31:55.707Z","avatar_url":"https://github.com/mathertel.png","language":"C++","readme":"# Arduino OneButton Library\n\nThis Arduino library is improving the usage of a singe button for input.\nIt shows how to use an digital input pin with a single pushbutton attached\nfor detecting some of the typical button press events like single clicks, double clicks and long-time pressing.\nThis enables you to reuse the same button for multiple functions and lowers the hardware investments.\n\nThis is also a sample for implementing simple finite-state machines by using the simple pattern above.\n\nYou can find more details on this library at\n\u003chttp://www.mathertel.de/Arduino/OneButtonLibrary.aspx\u003e\n\nThe change log of this library can be found in [CHANGELOG](CHANGELOG.md).\n\n\n## Getting Started\n\nClone this repository into `Arduino/Libraries` or use the built-in Arduino IDE Library manager to install\na copy of this library. You can find more detail about installing libraries\n[here, on Arduino's website](https://www.arduino.cc/en/guide/libraries).\n\n```CPP\n#include \u003cArduino.h\u003e\n#include \u003cOneButton.h\u003e\n```\n\nEach physical button requires its own `OneButton` instance.\n\n\n### Initialize on Instance creation (old way)\n\nYou can create a global instance and pass the hardware configurtion directly at compile time:\n\n```cpp\n// Declare and initialize\nOneButton btn = OneButton(\n  BUTTON_PIN,  // Input pin for the button\n  true,        // Button is active LOW\n  true         // Enable internal pull-up resistor\n);\n```\n\nThis works for most boards.  However, some boards will initialize the hardware AFTER the initialization of global\ndefined instances and the Input pin will not work at all.\n\n\n### Explicit setup and deferred initialization (new, more compatible option)\n\nBy using an explicit initialization using the `setup(...)` function solves the problem of the initialization order.\nAlso this is also a good option in case you do not know the Hardware configuration at compile time.\n\nDeclare a global instance, un-initialized:\n\n```cpp\nOneButton btn;\n```\n\nIn the main `setup()` function the instance will be initialized by passing the hardware configuration.  Pass the input\nmode as known from pinMode():\n\n```cpp\nbtn.setup(\n  BUTTON_PIN,   // Input pin for the button\n  INPUT_PULLUP, // INPUT and enable the internal pull-up resistor\n  true          // Button is active LOW\n);\n```\n\nIn the SimpleOneButton example shows how to use this sequence.  In the new `setup(...)` function the pinMode can be\ngiven in the second parameter to allow all kind of hardware options.\n\n\n## OneButton Tiny version\n\nThe OneButton Library was extended over time with functionality that was requested for specific\nuse cases. This makes the library growing over time too and therefore was limiting use cases using very small processors like attiny84.\n\nStaring with version 2.5 the OneButton Library starts supporting these processors with limited\nmemory and low cpu frequencies by introducing the `OneButtonTiny` class that offers a subset of\nthe features of the complete `OneButton` class by exposing the following events as callbacks:\n\n* Click event\n* DoubleClick event\n* LongPressStart event\n* Callbacks without parameters\n\nThis saves up to 1k of binary program space that is a huge amount on these processors.\n\nWith Version 2.5 the `OneButtonTiny` class is now in a beta state.\n\n* Any Issues or pull requests fixing problems are welcome.\n* Any new feature request for the `OneButtonTiny` class will be rejected to keep size small.\n* New, reasonable functionality will be added to the OneButton class only.\n\n\n### Initialize a Button to GND\n\n```CPP\n#define BUTTON_PIN 4\n\n/**\n * Initialize a new OneButton instance for a button\n * connected to digital pin 4 and GND, which is active low\n * and uses the internal pull-up resistor.\n */\n\nOneButton btn = OneButton(\n  BUTTON_PIN,  // Input pin for the button\n  true,        // Button is active LOW\n  true         // Enable internal pull-up resistor\n);\n```\n\n\n### Initialize a Button to VCC\n\n```CPP\n#define BUTTON_PIN 4\n\n/**\n * Initialize a new OneButton instance for a button\n * connected to digital pin 4, which is active high.\n * As this does not use any internal resistor\n * an external resistor (4.7k) may be required to create a LOW signal when the button is not pressed.\n */\n\nOneButton btn = OneButton(\n  BUTTON_PIN,  // Input pin for the button\n  false,       // Button is active high\n  false        // Disable internal pull-up resistor\n);\n```\n\n\n### Attach State Events\n\nOnce you have your button initialized, you can handle events by attaching them to the button\ninstance. Events can either be static functions or lambdas (without captured variables).\n\n```CPP\n// Handler function for a single click:\nstatic void handleClick() {\n  Serial.println(\"Clicked!\");\n}\n\n// Single Click event attachment\nbtn.attachClick(handleClick);\n\n// Double Click event attachment with lambda\nbtn.attachDoubleClick([]() {\n  Serial.println(\"Double Pressed!\");\n});\n\n// Handler function for MultiClick the button with self pointer as a parameter\nstatic void handleMultiClick(OneButton *oneButton) {\n  Serial.println(\"MultiClick pin=%d debouncedValue=%d!\", oneButton-\u003epin(), oneButton-\u003edebouncedValue());\n}\n\n// MultiClick button event attachment with self pointer as a parameter\nbtn.attachMultiClick(handleMultiClick, \u0026btn);\n```\n\n### Don't forget to `tick()`\n\nIn order for `OneButton` to work correctly, you must call `tick()` on __each button instance__\nwithin your main `loop()`. If you're not getting any button events, this is probably why.\n\n```CPP\nvoid loop() {\n  btn.tick();\n\n  // Do other things...\n}\n```\n\n\n### Usage with lambdas that capture context\n\nYou __can't pass__ a lambda-__with-context__ to an argument which expects a __function pointer__. To work that around,\nuse `paramtererizedCallbackFunction`. We pass the context (so the pointer to the object we want to access) to the library\nand it will give it back to the lambda.\n\n```CPP\nokBtn.attachClick([](void *ctx){Serial.println(*((BtnHandler*)ctx) -\u003e state);}, this);\n```\n\nSee also discussion in [Issue #112](https://github.com/mathertel/OneButton/issues/112).\n\n\n## State Events\n\nHere's a full list of events handled by this library:\n\n| Attach Function         | Description                                                   |\n| ----------------------- | ------------------------------------------------------------- |\n| `attachPress`           | Fires as soon as a press is detected.                         |\n| `attachClick`           | Fires as soon as a single click press and release is detected.|\n| `attachDoubleClick`     | Fires as soon as a double click is detected.                  |\n| `attachMultiClick`      | Fires as soon as multiple clicks have been detected.          |\n| `attachLongPressStart`  | Fires as soon as the button is held down for 800 milliseconds.|\n| `attachDuringLongPress` | Fires periodically as long as the button is held down.        |\n| `attachLongPressStop`   | Fires when the button is released after a long hold.          |\n\n\n### Event Timing\n\nValid events occur when `tick()` is called after a specified number of milliseconds. You can use\nthe following functions to change the timing.\n\n__Note:__ Attaching a double click will increase the delay for detecting a single click. If a double\nclick event is not attached, the library will assume a valid single click after one click duration,\notherwise it must wait for the double click timeout to pass.\nThis is because a single click callback must not to be triggered in case of a double click event.\n\n| Function                | Default    | Description                                                   |\n| ----------------------- | ---------- | ------------------------------------------------------------- |\n| `setDebounceMs(int)`    | `50 msec`  | Period of time in which to ignore additional level changes.   |\n| `setClickMs(int)`       | `400 msec` | Timeout used to distinguish single clicks from double clicks. |\n| `setPressMs(int)`       | `800 msec` | Duration to hold a button to trigger a long press.            |\n\nYou may change these default values but be aware that when you specify too short times\nit is hard to click twice or you will create a long press instead of a click.\n\nThe former functions `setDebounceTicks`, `setClickTicks` and `setPressTicks` are marked deprecated.\nThe term `Ticks` in these functions where confusing. Replace them with the ...Ms function calls.\nThere is no functional change on them.\n\nSet debounce ms to a negative value to only debounce on release. `setDebounceMs(-25);` will immediately\nupdate to a pressed state, and will debounce for 25ms going into the released state. This will expidite\nthe `attachPress` callback function to run instantly.\n\n\n### Additional Functions\n\n`OneButton` also provides a couple additional functions to use for querying button status:\n\n| Function                | Description                                                                    |\n| ----------------------- | ------------------------------------------------------------------------------ |\n| `bool isLongPressed()`  | Detect whether or not the button is currently inside a long press.             |\n| `int getPressedMs()`    | Get the current number of milliseconds that the button has been held down for. |\n| `int pin()`             | Get the OneButton pin                                                          |\n| `int state()`           | Get the OneButton state                                                        |\n| `int debouncedValue()`  | Get the OneButton debounced value                                              |\n\n\n### `tick()` and `reset()`\n\nYou can specify a logic level when calling `tick(bool)`, which will skip reading the pin and use\nthat level instead. If you wish to reset the internal state of your buttons, call `reset()`.\n\n\n## Troubleshooting\n\nIf your buttons aren't acting they way they should, check these items:\n\n1. Check your wiring and pin numbers.\n2. Did you call `tick()` on each button instance in your loop?\n3. Did you alter your clock timers in any way without adjusting ticks?\n","funding_links":[],"categories":["C++","Libraries"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathertel%2FOneButton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmathertel%2FOneButton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathertel%2FOneButton/lists"}