Raspberry Pi - GPIO


18.09.2014

В предыдущей статье я затронул тему GPIO. Сегодня я расскажу как управлять выводами GPIO.

Еще раз напомню, что выводы GPIO Raspberry Pi предназначены для работы с напряжением уровня 3.3 В. Raspberry Pi не имеет защиты от перенапряжения, поэтому следует всегда использовать сигналы, не превышающие уровень 3.3 В.

Итак, для тестов приготовим светодиод, и кнопку. Подключим их как показано на схеме.

RaspberryPi2_button_LED

Распиновка Raspberry Pi была приведена в предыдущей статье. Обратите внимание, что для кнопки выполнена "подтяжка" к +3.3 через резистор R1. Т.е. когда на входе 1 - кнопка не была нажата. Когда на входе 0 - это означает, что кнопка нажата. Подтяжку можно делать и программно. Далее это будет описано. При включении подтяжки программно, используются внутренние резисторы. Если вход не имеет подтяжки ("висит в воздухе"), его потенциал может колебаться от 0B до напряжения питания (3.3В). Эта ситуация касается контактных сенсоров, кнопок, герконов и т.п. Если на вход подается сигнал с известным потенциалом, например: сигнал с компаратора или другой микросхемы или датчика, - подтяжку делать не обязательно. Но я рекомендую делать "подтяжку" всегда. Это может предотвратить возможные проблемы в случае физического обрыва связи с источником сигнала.

Существует два различных метода для записи и считывания с периферийных устройств на системах, использующих Linux-подобные системы. Первый из них: создавая доступ через типы файлов к периферии в файловой системе, а второй - запись/чтение базовых адресов памяти, выделенной в GPIO или модуля SoC. Описание участков этой памяти можно найти в данных в BCM2835.

Первый метод управления GPIO (файловая система)

Попробуем поморгать светодиодом. Следующие операции желательно выполнять с полномочиями пользователя root.

Создаем файл доступа GPIO:


echo 11 > /sys/class/gpio/export

Настраиваем как выход (out):


echo out > /sys/class/gpio/gpio11/direction

Записываем значение (0 или 1):


echo 1 > /sys/class/gpio/gpio11/value

Светодиод должен засветиться.


echo 0 > /sys/class/gpio/gpio11/value

Светодиод должен погаснуть.

Следующая команда удаляет создан доступ к GPIO:


echo 11 > /sys/class/gpio/unexport

Вы можете управлять GPIO, используя любой язык программирования (С, Bash, Python).

Скачайте и запустите пример, написанный на Python:


wget https://sites.google.com/site/semilleroadt/raspberry-pi-tutorials/gpio/ADT_blink.py
python ADT_blink.py

Скрипт спросит, к которому вывода GPIO подключен диод и сколько раз он мигнуть. Чтобы убедиться в том, что ничего сложного в управлении GPIO нет, откройте скрипт ADT_blink.py редактором nano:


nano ADT_blink.py

Теперь то же самое сделаем для входа. Кнопка подключена к GPIO17.

Создаем файл доступа GPIO:


echo 17 > /sys/class/gpio/export

Настраиваем как вход (in):


echo in > /sys/class/gpio/gpio17/direction

Считываем значение:


cat /sys/class/gpio/gpio17/value

Как мы видим команда вернула 1 (помним про подтяжку к +3.3В). Нажмем кнопку и повторим команду:


cat /sys/class/gpio/gpio17/value

Команда должна вернуть 0.

Теперь напишем небольшой скрипт на Python (файл test_button.py):


import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17,GPIO.IN)

while True:
  if (GPIO.input(17)==0):
    print("Button Pressed")
    time.sleep(1);

Запустим скрипт:


python test_button.py

Cкрипт должен писать "Button Pressed" когда кнопка нажата.

Мы использовали подтяжку GPIO-входа до логического нуля с помощью внешнего резистора. Но можно сделать это программно с помощью необязательного параметра pull_up_down. например:


GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)

Небольшая памятка как работать GPIO на Python

1) Импортируем библиотеку для работы с GPIO import RPi.GPIO as GPIO

2) Устанавливаем способ нумерации выводов GPIO GPIO.setmode(GPIO.BCM) # GPIO.BCM - будет использоваться нумерация GPIO # GPIO.BOARD - будет использоваться нумерация P1-26

3) Конфигурируем выводы Например, GPIO 11,  конфигурируем как выход, а GPIO 17 - как вход: GPIO.setup(11, GPIO.OUT) # конфигурируем GPIO 11 как выход GPIO.setup(17, GPIO.IN) # конфигурируем GPIO 17 как вход

С помощью необязательного параметра pull_up_down функции setup можно настроить "подтяжку" входа к питанию или к земле: GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP) # подтяжка к питанию 3,3 В GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # подтяжка к земле0 В GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_OFF) # подтяжка выключена

4) Задание выходного сигнала и считывания входного Записываем "1" і "0" в GPIO 11 и считываем сигнал с GPIO 17: GPIO.output(11, True) # записываем в GPIO 11 "1" (3.3 V) GPIO.output(11, False) # записываем в GPIO 11 "0" (0 V) signal = GPIO.input(17) # считываем сигнал GPIO 17 в переменную signal

5) Завершаем работу GPIO.cleanup() # выполнение этой команды переводит GPIO в исходное состояние.

Второй метод (прямой доступ через участки памяти)

Устанавливаем библиотеку bcm2835:


wget http://www.open.com.au/mikem/bcm2835/bcm2835-1.36.tar.gz
tar zxvf bcm2835-1.36.tar.gz
./bcm2835-1.36
make
make check
make install
cd ..

Подробнее о библиотеке можно почитать здесь: http://www.open.com.au/mikem/bcm2835/

Теперь можно использовать эту библиотеку для доступа к GPIO. Скачаем и скомпилируем пример, написанный на С:


wget https://sites.google.com/site/semilleroadt/raspberry-pi-tutorials/gpio/main.c
gcc -o main -l rt main.c -l bcm2835

Запустим скомпилированную программу:


./main

Теперь светодиод, подсоединенный к GPIO 11 должен моргать.

Откройте main.c.  Строка:


#define PIN RPI_GPIO_P1_23

задает номер "ноги" на разъеме. Таблица соответствия двух способов нумерации:

GPIO02 — P1-03 GPIO03 — P1-05 GPIO04 — P1-07 GPIO07 — P1-26 GPIO08 — P1-24 GPIO09 — P1-21 GPIO10 — P1-19 GPIO11 — P1-23 GPIO14 — P1-08 GPIO15 — P1-10 GPIO17 — P1-11 GPIO18 — P1-12 GPIO22 — P1-15 GPIO23 — P1-16 GPIO24 — P1-18 GPIO25 — P1-22 GPIO27 — P1-13 GPIO28 — P5-03 GPIO29 — P5-04 GPIO30 — P5-05 GPIO31 — P5-06

Теперь напишем небольшую программу для считывания. Файл input.c:

#include 
#include 

#define PIN RPI_GPIO_P1_11

int main(int argc, char **argv)
{
  if (!bcm2835_init())
    return 1;
  // Set the pin to be an input
  bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT);
  // with a pullup
  bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP);

  // Reading
  while (1)
  {
    uint8_t value = bcm2835_gpio_lev(PIN);
    printf("Pin 17 = %d", value);

    // wait
    bcm2835_delay(500);
  }
  bcm2835_close();
  return 0;
}

Компілюємо:


gcc -o input -l rt input.c -l bcm2835

Запускаем:


./input

Программа показывает состояние входа GPIO17 (P1-11).

О скорости работы с GPIO различными способами подробно описано здесь: http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/

Успехов!

Смотри также:

Коментарі:

Додати коментар

* - обов'язкові поля

Архіви