Про то как помигать светодиодом на платах вроде BeagleBone написано очень много. Но есть несколько проблем из-за которых я и решил написать этот пост.
И так, нужно просто управлять цифровым выходом в программе на Python. Для доступа к GPIO из user-space используется sysfs. Можно прямо из консоли (echo 45 > /sys/class/gpio/export), но это не особо удобно поскольку номера выводов придётся считать вручную. Есть библиотека для Python от adafruit которая реализует эту скучную работу и даёт простой API. Её и будем использовать.
Первая проблема: права доступа к /sys.
Вторая проблема: баг в библиотеке от adafruit.
Решение ниже.
Управление выводами из консоли выглядит примерно так:
После этого в /sys/class/gpio должен появиться каталог gpio45/, являющийся симлинком на /sys/devices/virtual/gpio/gpio45/.
Теперь посредством чтения/записи в соответствующие файлы внутри этого каталога имеем доступ непосредственно к лог.уровням на выводе.
Например, настроим его на выход и запишем туда лог.1:
На форумах можно встретить рекомендации изменять права доступа и настраивать GPIO при загрузке системы, из /etc/rc.local например, но мне это тоже не нравится т.к. появляется 2 места для настройки портов: в инитскриптах и собственно в программе, работающей с этими портами.
Правильнее сделать чтобы создаваемые на sysfs файлы уже имели нужные права для нужного пользователя. Это можно сделать с помощью udev. Напишем правило /etc/udev/rules.d/71-gpio.rules с содержанием:
Группу gpio создадим:
Теперь надо получить тот же результат на Python. Используем библиотеку http://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/overview.
Простейший скрипт для дёргания выводом каждые пол-секунды:
Но тут меня ждала подстава. Данный скрипт работает от root, но не работает от обычного пользователя. Хотя все права верные. Более того, скрипт начинает работать если предварительно вручную из консоли включить нужный пин. С этим пошёл на stackoverflow и на github библиотеки. Но самостоятельно решил проблему раньше. Пока авторы не исправили этот баг есть брутальное решение ниже.
По каким-то причинам при работе от простого пользователя файл /sys/class/gpio/gpio# не успевает создаться до того как будет вызвана запись в него. Вызов open() возвращает ошибку, на которую никому нет дела и всё просто тупо не работает.
Берём исходники этой библиотеки:
Утанавливаем:
Вот и всё. Теперь ногодрыгание работает в Python от обычного пользователя.
И так, нужно просто управлять цифровым выходом в программе на Python. Для доступа к GPIO из user-space используется sysfs. Можно прямо из консоли (echo 45 > /sys/class/gpio/export), но это не особо удобно поскольку номера выводов придётся считать вручную. Есть библиотека для Python от adafruit которая реализует эту скучную работу и даёт простой API. Её и будем использовать.
Первая проблема: права доступа к /sys.
Вторая проблема: баг в библиотеке от adafruit.
Решение ниже.
Управление выводами из консоли выглядит примерно так:
echo 45 > /sys/class/gpio/exportВключили GPIO#45. Куда он выведен на плате - курить даташиты, развёрнутый пост про это тут.
После этого в /sys/class/gpio должен появиться каталог gpio45/, являющийся симлинком на /sys/devices/virtual/gpio/gpio45/.
Теперь посредством чтения/записи в соответствующие файлы внутри этого каталога имеем доступ непосредственно к лог.уровням на выводе.
Например, настроим его на выход и запишем туда лог.1:
echo out > /sys/class/gpio/gpio45/directionДо сих пор всё хорошо за исключением того что доступ к /sys имеет только root. От имени простого пользователя записать туда данные нельзя. Это никуда не годится.
echo 1 > /sys/class/gpio/gpio45/value
На форумах можно встретить рекомендации изменять права доступа и настраивать GPIO при загрузке системы, из /etc/rc.local например, но мне это тоже не нравится т.к. появляется 2 места для настройки портов: в инитскриптах и собственно в программе, работающей с этими портами.
Правильнее сделать чтобы создаваемые на sysfs файлы уже имели нужные права для нужного пользователя. Это можно сделать с помощью udev. Напишем правило /etc/udev/rules.d/71-gpio.rules с содержанием:
KERNEL=="gpio*", SUBSYSTEM=="gpio", ACTION=="add", PROGRAM="/bin/sh -c 'chown -R debian:gpio /sys/class/gpio'"Теперь (после перезагрузки т.к. горячая перезагрузка правил udev не сработает для уже загруженного драйвера) при создании файла на sysfs в драйвере gpio будет вызываться смена владельца для 2 каталогов, которые нам и нужны.
KERNEL=="gpio*", SUBSYSTEM=="gpio", ACTION=="add", PROGRAM="/bin/sh -c 'chown -R debian:gpio /sys/devices/virtual/gpio/'"
Группу gpio создадим:
groupadd gpioПользователя debian к ней добавим:
usermod -a -G gpio debianПерелогиниваемся под пользователем debian и проверяем от его имени все вышеприведённые манипуляции с /sys. Должно работать. Можно писать shell-скрипты для мигания светодиодами или аналогичных бесконечно бесполезных задач :)
Теперь надо получить тот же результат на Python. Используем библиотеку http://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/overview.
Простейший скрипт для дёргания выводом каждые пол-секунды:
#!/usr/bin/env pythonСпасибо Adafruit за возможность работать с пинами по их расположению на плате, а не просто по номерам в регистрах процессора. "P8_11" означает 11 пин на гребёнке P8 в BeagleBone Black.
import Adafruit_BBIO.GPIO as GPIO
import time
P = "P8_11"
GPIO.setup(P, GPIO.OUT)
for i in xrange(100):
GPIO.output(P, GPIO.HIGH if i % 2 == 0 else GPIO.LOW)
time.sleep(0.5)
GPIO.cleanup()
Но тут меня ждала подстава. Данный скрипт работает от root, но не работает от обычного пользователя. Хотя все права верные. Более того, скрипт начинает работать если предварительно вручную из консоли включить нужный пин. С этим пошёл на stackoverflow и на github библиотеки. Но самостоятельно решил проблему раньше. Пока авторы не исправили этот баг есть брутальное решение ниже.
По каким-то причинам при работе от простого пользователя файл /sys/class/gpio/gpio# не успевает создаться до того как будет вызвана запись в него. Вызов open() возвращает ошибку, на которую никому нет дела и всё просто тупо не работает.
Берём исходники этой библиотеки:
git clone https://github.com/adafruit/adafruit-beaglebone-io-python.gitИ применяем патч:
--- py_gpio.c 2013-09-17 20:10:08.000000000 +0300Применять патч с помощью patch < name.patch в каталоге adafruit-beaglebone-io-python/source.
+++ py_gpio.c 2013-09-21 02:54:43.000000000 +0300
@@ -105,10 +105,26 @@
if (get_gpio_number(channel, &gpio))
return NULL;
-
- gpio_export(gpio);
- gpio_set_direction(gpio, direction);
- gpio_set_value(gpio, pud);
+
+ unsigned int count = 1000000;
+ int res = -1;
+ do {
+ res = gpio_export(gpio);
+ } while(res != 0 && count-- > 0);
+ if(count == 0)
+ return NULL;
+ count = 1000000;
+ do {
+ res = gpio_set_direction(gpio, direction);
+ } while(res != 0 && count-- > 0);
+ if(count == 0)
+ return NULL;
+ count = 1000000;
+ do {
+ res = gpio_set_value(gpio, pud);
+ } while(res != 0 && count-- > 0);
+ if(count == 0)
+ return NULL;
gpio_direction[gpio] = direction;
Утанавливаем:
python setup.py installВ Debian понадобятся пакеты build-essential python-dev python-setuptools. Если предварительно библиотека была установлена с помощью pip или easy_install, то её следует удалить перед установкой из исходников.
Вот и всё. Теперь ногодрыгание работает в Python от обычного пользователя.
Комментариев нет:
Отправить комментарий