Somael is a lightweight PlatformIO library for handling button input, actions, and decision events on Arduino-compatible platforms.
The name Somael is associated with action and decision, reflecting the library’s role as an input-oriented abstraction layer. Somael provides both blocking and event-driven button handling, allowing flexible input management for games, menus, and embedded UIs.
Somael is designed to simplify button handling by providing:
- Unified scanning logic for multiple buttons
- Press and release event detection
- Optional callback-based input handling
- Blocking and non-blocking APIs within a single interface
The library intentionally avoids complex state machines while still offering reliable edge detection.
- Multiple button input handling
- Internal press / release state tracking
- Blocking input helpers (waitPress, waitRelease)
- Non-blocking scanning (scan)
- Event callbacks for press and release
- Pull-up input configuration by default
- Minimal and predictable API
- Arduino-compatible platforms
- Tested primarily with ESP32
No platform-specific peripherals are required.
- Arduino framework
No external libraries are required.
Add the following to your platformio.ini:
lib_deps =
https://github.com/tabah-mly/somael.gitAlternatively, place the library in your project’s lib directory:
lib/
└── somael/
├── include/
│ └── Somael.h
├── src/
│ └── Somael.cpp
#include <Somael.h>
constexpr int btnCount = 4;
int buttons[btnCount] = {17, 18, 4, 16};
Somael input(buttons, btnCount);
void setup() {
input.begin();
}Buttons are automatically configured as INPUT_PULLUP.
Blocks execution until a button is pressed and released.
int index = input.waitPress();Returns the index of the pressed button.
Blocks execution but triggers a callback immediately on press.
input.waitPress([](int i) {
Serial.println(i);
});Blocks execution until the specified button is released.
input.waitRelease(buttons[0]);Non-blocking button scan function.
Should be called repeatedly inside loop().
int active = input.scan();Returns
- Index of the currently active button
-1if no button is pressed
Returns the most recent press event detected during scan().
int p = input.getPress();Returns -1 if no press occurred.
Returns the most recent release event detected during scan().
int r = input.getRelease();Returns -1 if no release occurred.
Registers a callback for press events.
input.onPress([](int i) {
Serial.print("Pressed: ");
Serial.println(i);
});Registers a callback for release events.
input.onRelease([](int i) {
Serial.print("Released: ");
Serial.println(i);
});- Buttons are assumed active-low
- Internal arrays track current and previous states
- Press and release events are edge-triggered
- Only one button is considered active at a time
- Priority is given to the most recently pressed button
- Blocking functions are intentionally simple and predictable
- Non-blocking scanning allows integration into game loops
- Fixed internal buffer size (
16) for button states - No debouncing is performed (can be added externally if required)
Somael is currently in beta. The API is stable for its intended use cases, with future improvements focused on configurability and robustness.
Planned enhancements include:
- Optional software debouncing
- Configurable active-high / active-low logic
- Support for long-press detection
- Multiple simultaneous button handling modes
- Event queue–based input processing
This project is licensed under the MIT License.
GitHub: https://github.com/tabah-mly