FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

raspino-org/gpiodWrap: A lightweight C++ wrapper for libgpiod (v2.x) to simplify GPIO usage on Linux/Raspberry Pi. Offers human-friendly functions like configurePin(), setPin(), getPin(), bindInterrupt(), and watchInterrupt() without deep knowledge of the complex libgpiod API Wrapper. · GitHub

Repository navigation

Public

About

A lightweight C++ wrapper for libgpiod (v2.x) to simplify GPIO usage on Linux/Raspberry Pi. Offers human-friendly functions like configurePin(), setPin(), getPin(), bindInterrupt(), and watchInterrupt() without deep knowledge of the complex libgpiod API Wrapper.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation


A lightweight and user-friendly C++ wrapper for libgpiod 2.x, designed to make GPIO access on Linux and Raspberry Pi simple, readable, and intuitive.


✨ Features

✔️ Simple GPIO input/output
✔️ One-line pin configuration
✔️ Pin Event (IS_RISING, IS_FALLING)
✔️ Interrupt support (RISING, FALLING, BOTH)
✔️ Non-blocking debouncing function
✔️ Automatic cleanup & securely reset
✔️ No dynamic memory handling required
✔️ Asynchron and without continuous polling
✔️ Works with libgpiod 2.x


🧩 Provided Functions

Instead of complex gpiod structures, this wrapper provides easy functions like:


Basic configuration Description
gpiodWrap gpio Automatic search chip number.
gpiodWrap gpio(chipnum) Specific chip number.


Basic function Description
openChip(chipnum) Open specifically.
closeChip() Returns outputs to a safe state, releases resources.
configurePin(pin, direction) Configured and registered PIN.
setPin(pin, HIGH/LOW) Sets pin high/low.
getPin(pin, debounce) Reads pin optional debouncing.
getPinEvent(pin, debounce) Reads pin edge events with integrated software debouncing and outputs PinEvent.
resetPin(pin) resets the PIN and releases its resources.


Interrupt methods Description
bindInterrupt(pin, direction, edge, debounce) Registers and configures a GPIO pin for interrupt detection with debouncing.
watchInterrupt(pin, userCallback void/void(int)) Interrupt monitoring; passes events to the specified callback.
unbindInterrupt(pin) Disables interrupt for pin and terminates the associated thread.


Error handling Description
anyGlobalError() Returns a global error
hasGlobalError(enum) Returns a specific global error
getGlobalErrorNum() Returns global error number.
anyPinError(pin) Returns a pin error
hasPinError(pin, enum) Returns a specific pin error.
getPinErrorNum(pin) Returns pin error number.
clearGlobalErrors() Clears all global errors
clearGlobalError(enum) Clears specific global error
clearPinErrors(pin) Clears all specific pin errors
clearPinError(pin, enum) Clears specific pin error


Komfort functions Description
getStrErr() Returns error as text.
getStrErrPin(pin) Returns specific pin errors.
blinkPin(pin, interval, time) e.g., implementing an status LED
softPwm(pin, percent, frequency) Dynamic Software PWM control LEDs, BUZZER...
detachPin(pin, PinValue, PinValue, interval) e.g., status LEDs...

Perfect for hobbyists, students, and projects where you just want GPIO control without becoming a libgpiod expert.


📦 Dependencies

Requirement Version
libgpiod ≥ 2.0
C++ ≥ C++17
CMake optional for building

Install libgpiod build-essential cmake(Debian / Raspberry Pi OS):

sudo apt update
sudo apt install -y libgpiod-dev build-essential cmake

gpioinfo -v

libgpiod-2.x self build e.g. RaspberryOS bullseye/bookworm

sudo apt update
sudo apt install -y build-essential autoconf automake libtool pkg-config autoconf-archive

wget https://mirrors.edge.kernel.org/pub/software/libs/libgpiod/libgpiod-2.3.1.tar.gz
tar -xvf libgpiod-2.3.1.tar.gz
cd libgpiod-2.3.1

./configure --enable-tools
make -j4
sudo make install
sudo ldconfig

No Root Required

//Check the gpio group
  groups 

//if it doesn't show up, keep going (don't forget the 'a').
  sudo usermod -aG gpio username

//Sign up again
  exit


🚀 Basic Example

#include <iostream>
#include <chrono>
#include <thread>

#include "gpiodWrap.hpp"


int main() {
    try {

        using namespace gpiodwrap;

        gpiodWrap gpio;

        gpio.configurePin(17, Output);

        gpio.setPin(17, HIGH);
        std::this_thread::sleep_for(std::chrono::seconds(1));
    
        gpio.setPin(17, LOW);
        std::this_thread::sleep_for(std::chrono::seconds(1));
  
        gpio.resetPin(17);
    }
    catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    // Destructor of gpiodWrap is called automatically
    return 0;
}

⚡ Interrupt Example

#include <iostream>
#include <chrono>

#include "gpiodWrap.hpp"

gpiodWrap gpio;

int main() {

    using namespace gpiodwrap;

    gpio.bindInterrupt(22, PULLUP, FALLING, 60);

    gpio.watchInterrupt(pin, [](int pin) 
         { std::cout << "Falling-Event on Pin: " << pin << std::endl; });

    while (true) {
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

📁 examples/

 ├── blink.cpp       // Make individual LEDs blink
 ├── button.cpp      // Input example
 ├── button_led.cpp  // Input / Output example
 ├── buzzer.cpp      // Alert example
 ├── error.cpp       // Error handling
 ├── fade_led.cpp    // Dynamic PWM control
 ├── interrupt.cpp   // Kernel-Event 
 ├── led.cpp         // Output example
 ├── mockup.cpp      // Event / Debounce stress test
 ├── pin_event.cpp   // Input event falling/rising
 └── pwm.cpp         // Static PWM control



📦 Install build-essential and CMake

sudo apt update
sudo apt upgrade -y
sudo apt install build-essential -y
sudo apt install cmake -y

🔧 Integration Example

CMake-System

cd gpioWarp
mkdir build
cd build
cmake ..
make or make -j4

output bin/...

📦 Project Build Instructions

mkdir myproject
cd myproject
mkdir src include build
mv ../gpioWrap/gpiodWrap.hpp include
nano CMakeLists.txt
cd build
cmake ..
make or make -j4
cd ../bin/myproject
./myproject

🔧 Your build station looks like this:

 myproject
 │
 ├── CMakeLists.txx
 ├── build
 ├── bin
 │     └── myproject
 ├── include
 │     └── gpiodWrap.hpp
 └── src
        └── myproject.cpp

🔧 Your project CMakeLists.txt:

set(SOURCE_NAME myproject)

cmake_minimum_required(VERSION 3.16)
project(${SOURCE_NAME} VERSION 1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include_directories(${PROJECT_SOURCE_DIR}/include)

add_executable(${SOURCE_NAME}
    src/${SOURCE_NAME}.cpp
)

target_link_libraries(${SOURCE_NAME}
    gpiod
)

set_target_properties(${SOURCE_NAME} PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY
    ${PROJECT_SOURCE_DIR}/bin/${SOURCE_NAME}
)

or quickly

(The files to be compiled are located in one directory!)

 g++ myproject.cpp -o myproject -lgpiod

🛠️ Projekt

Here's another nice example from a different project where I'm using gpiodWrap.

#include <chrono>

#include "gpiodWrap.hpp"

gpiodWrap gpio;

constexpr int errorLED = 18;

void delay(unsigned long ms) {
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

unsigned long millis() {
    using namespace std::chrono;
    static const auto start = steady_clock::now();
    return duration_cast<milliseconds>(steady_clock::now() - start).count();
}

void errReport(unsigned long interval = 500) {

    static unsigned long last = 0;
    static bool state = true;
       
    if (millis() - last >= interval) {
        last = millis();   
        state = !state;
        gpiodwrap::gpio.setPin(faultLED, state ? HIGH : LOW);
    }    
}

int main() {

    using namespace gpiodwrap;
    gpio.configurePin(errorLED, Output);
    gpio.setPin(errorLED, LOW);

    bool syserror = true;

    while(true) {

        if (syserror) errReport(300);

        delay(20); 
    }
}

🚨 Hardware Safety & Signal Handling (Safe-by-Default)

Uncontrolled program termination (e.g., via Ctrl + C / SIGINT or SIGTERM) can be hazardous in hardware control applications if outputs connected to motors, relays, or heating elements remain active in an undefined state.

gpiodWrap addresses this by adhering to the Safe-by-Default principle:

  • Automatic Fail-Safe:

    Upon receiving SIGINT or SIGTERM, all active output pins are automatically reverted to a safe, high-impedance input state (INPUT) before the GPIO chip is released.

  • Decoupled Watchdog Thread:

    The POSIX signal handler exclusively modifies atomic flags (100% async-signal-safe). Hardware cleanup is executed asynchronously in a separate watchdog thread—completely free from C library locks or deadlock risks.

  • Optional Compile-Time Disabling:

    If your application logic manages signal handling independently, the built-in signal mechanism can be disabled entirely with zero runtime overhead:

  1. In C++ Source Code:
#define GPIODWRAP_NO_SIGNALS
#include "gpiodWrap.hpp"
  1. Via CMake:
# old school
mkdir -p build && cd build
cmake .. -DGPIODWRAP_DISABLE_SIGNALS=ON
make or make -j4

# Directly in the project directory:
cmake -B build -DGPIODWRAP_DISABLE_SIGNALS=ON
cmake --build build
  1. Direct GCC/Clang Invocation:
g++ -std=c++17 -DGPIODWRAP_NO_SIGNALS main.cpp -o app -lgpiod

📄 License

Copyright (C) 2026 Raspino-Projekt dev@raspino.org
GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
You are free to use, modify, and distribute this project under the terms of the GPLv3.


🤝 Contributions

Pull requests and improvements are welcome.
Feel free to fork, enhance, or suggest features.


⭐ If this wrapper helps your project — consider starring it on GitHub!

About

A lightweight C++ wrapper for libgpiod (v2.x) to simplify GPIO usage on Linux/Raspberry Pi. Offers human-friendly functions like configurePin(), setPin(), getPin(), bindInterrupt(), and watchInterrupt() without deep knowledge of the complex libgpiod API Wrapper.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages


Back | FazBrowse Home | New Git URL