Перейти к основному содержимому

Использование библиотеки libgpiod для управления GPIO

libgpiod — это набор инструментов, специально разработанный для работы с GPIO в системах Linux. Он не только имеет библиотеки низкого уровня для языка C, но также интерфейсы для языков высокого уровня, таких как Python, и поставляется с несколькими инструментами командной строки, что весьма удобно.

GPIO

Настройка BIOS

  • В системах с ядром Linux 6.1 необходимо убедиться, что система загружена в режиме 0 Orange Pi 6 plus (Device Tree).

    Режим GPIO
  • Для систем с ядром Linux 6.6, использующих ACPI, убедитесь с помощью команды dmidecode, что версия BIOS - v1.0_for_opi6plus_linux

    sudo dmidecode -s bios-versio

    Если это не так, то обратитесь к разделу Обновление BIOS на плате Orange Pi 6 plus, чтобы записать нужную версию BIOS

Установка libgpiod

Для установки библиотеки выполните в командной строке следующие команды:

sudo apt update
sudo apt install -y libgpiod-dev libgpiod2 gpiod libgpiod-doc
sudo apt install -y python3-libgpiod

Базовая концепция

GPIO chip: каждый контроллер GPIO рассматривается как чип GPIO, обычно представленный как /dev/gpiochipX (где X — номер в системе). GPIO Line: каждая микросхема GPIO имеет несколько линий (контактов) GPIO, каждая из которых имеет уникальный номер, начиная с 0.

Для Linux 6.1 cоответствие чипов, линий, GPIO и контактов приведено в таблице ниже:

GPIO LineGPIO chipGPIOКонтактКонтактGPIOGPIO chipGPIO Line
3.3 В125 В
13gpiochip3GPIO 056345 В
12gpiochip3GPIO 05556GND
22gpiochip4GPIO 09778GPIO 105gpiochip430
GND910GPIO 106gpiochip431
0gpiochip1GPIO 0151112GPIO 017gpiochip12
1gpiochip1GPIO 0161314GND
24gpiochip4GPIO 0991516GPIO 100gpiochip425
3.3 В1718GPIO 018gpiochip13
17gpiochip0GPIO 0281920GND
14gpiochip0GPIO 0252122GPIO 019gpiochip14
18gpiochip0GPIO 0292324GPIO 026gpiochip015
GND2526GPIO 027gpiochip016
5gpiochip3GPIO 0482728GPIO 047gpiochip34
5gpiochip1GPIO 0202930GND
8gpiochip1GPIO 0233132GPIO 021gpiochip16
9gpiochip1GPIO 0243334GND
14gpiochip3GPIO 0573536GPIO 022gpiochip17
17gpiochip3GPIO 0603738GPIO 061gpiochip318
GND3940GPIO 062gpiochip319

Таблица соответствия для Linux 6.6

GPIO LineGPIO chipGPIOКонтактКонтактGPIOGPIO chipGPIO Line
3.3 В125 В
13gpiochip0GPIO 056345 В
12gpiochip0GPIO 05556GND
22gpiochip1GPIO 09778GPIO 105gpiochip130
GND910GPIO 106gpiochip131
0gpiochip6GPIO 0151112GPIO 017gpiochip62
1gpiochip6GPIO 0161314GND
24gpiochip1GPIO 0991516GPIO 100gpiochip125
3.3 В1718GPIO 018gpiochip63
17gpiochip4GPIO 0281920GND
14gpiochip4GPIO 0252122GPIO 019gpiochip64
18gpiochip4GPIO 0292324GPIO 026gpiochip415
GND2526GPIO 027gpiochip416
5gpiochip0GPIO 0482728GPIO 047gpiochip04
5gpiochip6GPIO 0202930GND
8gpiochip6GPIO 0233132GPIO 021gpiochip66
9gpiochip6GPIO 0243334GND
14gpiochip0GPIO 0573536GPIO 022gpiochip67
17gpiochip0GPIO 0603738GPIO 061gpiochip018
GND3940GPIO 062gpiochip019

Инструменты командной строки

  1. Команда gpiodetect может вывести список всех GPIO контроллеров (chip).
sudo gpiodetect
  1. Команда gpioinfo выводит подробную информацию обо всех контроллерах GPIO.
sudo gpioinfo
  1. Команда gpioset может перевести контакты GPIO в режим вывода и одновременно установить высокий уровень или низкий уровень.

Пример

Задача: Установить высокий уровень на 3 контакте разъёма GPIO в системе с ядром Linux 6.6.

Решение: Взяв данные из соответствующей таблицы, получается, что 3 контакту разъёма соответсвуют gpiochip0 и линия GPIO - 13. Для установки можно использовать следующую команду: вывод GPIO на выход + высокий уровень.

sudo gpioset gpiochip0 13=1

После настройки проверьте при помощи мультиметра напряжение на контакте 3, и вы увидите, что напряжение составляет 3,3 В.

Для установки низкого уровня на контакте используйте следующую команду:

sudo gpioset gpiochip0 13=0
  1. Команда gpioget переводит контакты GPIO в режим ввода и считывает статус уровня контакта.
sudo gpioget gpiochip0 13

Возвращаемое значение 0 или 1

  1. Команда gpiomon используется для мониторинга событий изменения уровня (прерывания) контактов GPIO, таких как нажатие/отпускание кнопок, срабатывание датчиков и т. д. Она основана на механизме событий устройств GPIO ядра Linux, который более эффективен и надежен, чем опрос, и поддерживает такую ​​информацию, как временные метки и типы границ.
sudo gpiomon gpiochip1 1

Пример

Задача Получать данные об уровне на контакте 3 в Linux 6.6

Решение

Возмите данные из таблицы и введите в командной строке следующую команду:

sudo gpiomon gpiochip0 13

Соедините 3 контакт на разъёме с контактом GND. На консоли должно появится сообщение:

Режим GPIO

Разомкните контакты и увидите следующее сообщение:

Режим GPIO

Использование языка C для работы с GPIO

Обратите внимание !!!

Код написан для Linux 6.6. Если используется ядро Linux6.1, то gpiochip0 необходимо изменить в коде на gpiochip3.

Запустите редактирование файла gpio_set.c:

vim gpio_set.c

Добавьте следующий код:

#include <gpiod.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define CHIPNAME "gpiochip0"
#define GPIO_OFFSET 13 // Соответствует контакту 3 в 40-контактном разъеме.

int main(int argc, char *argv[])
{
struct gpiod_chip *chip;
struct gpiod_line *line;
int value, ret;

// Проверка параметров командной строки
if (argc != 2) {
fprintf(stderr, "Ошибка параметра команды: %s. Используйте 0 или 1\n", argv[0]);
return 1;
}

value = atoi(argv[1]);

if (value != 0 && value != 1) {
fprintf(stderr, "Ошибка: значение уровня должно быть 0 или 1\n");
return 1;
}

//Открываем чип GPIO
chip = gpiod_chip_open_by_name(CHIPNAME);
if (!chip) {
perror("Невозможно открыть чип GPIO");
return 1;
}

// Получаем инструкции
line = gpiod_chip_get_line(chip, GPIO_OFFSET);
if (!line) {
perror("Не удалось получить линию GPIO");
gpiod_chip_close(chip);
return 1;
}

// Запрос — режим вывода (имя потребителя — «gpio_set»)
ret = gpiod_line_request_output(line, «gpio_set», 0); // Первоначально установлено низкое значение

if (ret < 0) {
perror("Невозможно запросить режим вывода (может быть занято или нет разрешения)");
gpiod_chip_close(chip);
return 1;
}

// Установка уровня
ret = gpiod_line_set_value(line, value);

if (ret < 0) {
perror("Не удалось установить значение GPIO");
} else {
printf("Контакт %d GPIO %s установлен на %s\n", CHIPNAME, GPIO_OFFSET, value ? "Высокий уровень" : "Низкий уровень");
}

// Освободить ресурсы (необязятельно, ресурсы освободятся автоматически после закрытия программы)
gpiod_line_release(line);
gpiod_chip_close(chip);
return 0;
}

Команда для компиляции кода выглядит следующим образом:

gcc -o gpio_set gpio_set.c -lgpiod

Проверить, что программа скомпилирована можно следующей командой:

ls gpio_set

Следующая команда устанавливает высокий уровень на контакте 3 40-контактного разъёма

sudo ./gpio_set 1

Та же команда с параметром 0 установит низкий уровень

sudo ./gpio_set 0

Использование Python для управления GPIO

Откройте файл gpio_set.py для редактирования:

vim gpio_set.py

Добавьте следующий код:

#!/usr/bin/env python3
import sys
import gpiod

CHIPNAME = "gpiochip0"
GPIO_OFFSET = 13 # Соответствует 3 контакту 3 в 40-контактном разъёме.
def main():
if len(sys.argv) != 2:
print(f"Используйте: {sys.argv[0]} <0|1>", file=sys.stderr)
sys.exit(1)

try:
value = int(sys.argv[1])
assert value in (0, 1)
except (ValueError, AssertionError):
print("错误: 电平值必须是 0 或 1", file=sys.stderr)
sys.exit(1)

# Открываем чип
with gpiod.Chip(CHIPNAME) as chip:

# Получить номер линии
line = chip.get_line(GPIO_OFFSET)

# Запрос на переход в режим вывода
line.request(consumer="gpio_set_py", type=gpiod.LINE_REQ_DIR_OUT)

# Установить уровень
line.set_value(value)

print(f"GPIO {CHIPNAME} контакт {GPIO_OFFSET} установлен {'высокий' if value else 'низкий'} уровень")

if __name__ == "__main__":
main()

Следующая команда устанавливает высокий уровень на контакте 3.

 sudo python3 gpio_set.py 1

Для низкого уровня используйте команду:

sudo python3 gpio_set.py 0

Больше информации по библиотеке libgpiod

Официальная документаци по библиотеке находится по адресу https://libgpiod.readthedocs.io/en/latest/index.html