Skip to content

2. Controlling LED with GPIO

This guide explains how to control an LED using the General Purpose Input/Output (GPIO) pins on a Raspberry Pi. We'll use a C++ program that directly interfaces with the Linux GPIO character device interface.

LED

Required Hardware

  • Raspberry Pi (any model)
  • LED (1)
  • Resistor (220Ω to 330Ω)
  • Breadboard
  • Jumper wires

Hardware Setup

This guide uses GPIO pin 24 for the LED connection. Connect the components as follows:

  1. Connect the longer leg (anode) of the LED to GPIO 24
  2. Connect the shorter leg (cathode) of the LED through a resistor to GND (ground)
graph LR
    subgraph RPi["Raspberry Pi"]
        GPIO24["GPIO 24"]
        GND["GND"]
    end

    subgraph LED["LED"]
        Anode["+ Anode"]
        Cathode["- Cathode"]
    end

    GPIO24 --- R["Resistor (220-330Ω)"]
    R --- Anode
    Cathode --- GND

    style LED fill:#ff6b6b

Code Explanation

This program uses the Linux Character Device API to control GPIO pins. This method is efficient as it operates in kernel space.

#include <fcntl.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <chrono>
#include <cstring>
#include <iostream>
#include <thread>

/**
 * Simple LED control program using GPIO
 *
 * This program demonstrates basic GPIO control to blink an LED
 * connected to a specified GPIO pin on a Raspberry Pi or similar device.
 */
int main()
{
    constexpr char kGpioChipDevice[] = "/dev/gpiochip0";
    constexpr int kGpioPin = 24;          // GPIO pin number for the LED
    constexpr int kBlinkIntervalMs = 500; // Blink interval in milliseconds
    constexpr int kNumBlinks = 10;        // Number of times to blink

    // Open GPIO chip
    int chip_fd = open(kGpioChipDevice, O_RDONLY);
    if (chip_fd < 0)
    {
        std::cerr << "Failed to open GPIO chip device" << std::endl;
        return 1;
    }

    // Setup GPIO request
    struct gpiohandle_request req{};
    req.lineoffsets[0] = static_cast<__u32>(kGpioPin);
    req.flags = GPIOHANDLE_REQUEST_OUTPUT;
    req.lines = 1;
    std::strcpy(req.consumer_label, "simple-led");

    // Get line handle
    if (ioctl(chip_fd, GPIO_GET_LINEHANDLE_IOCTL, &req) < 0)
    {
        std::cerr << "Failed to get GPIO line handle" << std::endl;
        close(chip_fd);
        return 1;
    }

    // Blink the LED
    std::cout << "LED blinking started." << std::endl;

    for (int i = 0; i < kNumBlinks; ++i)
    {
        // Turn LED on
        struct gpiohandle_data data{};
        data.values[0] = static_cast<__u8>(1);

        if (ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data) < 0)
        {
            std::cerr << "Failed to set GPIO line value" << std::endl;
            break;
        }

        std::this_thread::sleep_for(
            std::chrono::milliseconds(kBlinkIntervalMs));

        // Turn LED off
        data.values[0] = static_cast<__u8>(0);

        if (ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data) < 0)
        {
            std::cerr << "Failed to set GPIO line value" << std::endl;
            break;
        }

        std::this_thread::sleep_for(
            std::chrono::milliseconds(kBlinkIntervalMs));
    }

    // Clean up resources
    close(req.fd);
    close(chip_fd);
    return 0;
}

Understanding the Code

  1. Header Files:

    • fcntl.h, linux/gpio.h, sys/ioctl.h are required for accessing Linux GPIO devices
    • Standard C++ library headers are also included
  2. Constants:

    • kGpioChipDevice: Path to the GPIO chip device (usually "/dev/gpiochip0")
    • kGpioPin: GPIO pin number connected to the LED (24 in this example)
    • kBlinkIntervalMs: Blinking interval in milliseconds
    • kNumBlinks: Number of times to blink
  3. Opening the GPIO Chip:

    • The open() function is used to open the GPIO device file
  4. Configuring the GPIO Pin:

    • A gpiohandle_request structure is configured, setting the pin to output mode
  5. Getting a Handle:

    • ioctl() is used to get a GPIO line handle
  6. Blinking the LED:

    • Inside a loop, ioctl() is used to toggle the GPIO pin value between 1 (on) and 0 (off)
    • std::this_thread::sleep_for() controls the blinking interval
  7. Releasing Resources:

    • All file descriptors are closed at the end

Compilation and Execution

  1. Save the code as gpio_led.cpp

  2. Compile with GCC/G++:

    g++ -o gpio_led gpio_led.cpp -std=c++14
    
  3. Run with administrator privileges:

    sudo ./gpio_led
    

Troubleshooting

  1. "Failed to open GPIO chip device" Error:

    • Ensure you're running the program with sudo privileges
    • Verify that the GPIO device file (/dev/gpiochip0) exists
  2. "Failed to get GPIO line handle" Error:

    • Check that the pin number is correct
    • Make sure no other process is using the same pin
  3. LED Doesn't Light Up:

    • Check your wiring
    • Verify the LED orientation is correct
    • Ensure the resistor value is appropriate

Additional Resources