Выбрать главу

4.7. Подключаем кнопки

Раз уж мы подключили дисплей, остался последний шаг для создания автономного устройства на базе Raspberry Pi - добавить поддержку кнопок. Тем более, что для тех кто читал главу 3.2 про порты ввода-вывода на ESP32, все будет просто - принцип остается тот же.

Напомним общую идею, которая обсуждалась еще в первой части про Arduino - специальный резистор “подтягивает” напряжение до шины питания, а кнопка при необходимости замыкает его на землю:

На Raspberry Pi все то же самое, только резистор уже встроенный, и ставить его отдельно не надо. Ну и напряжение не 5В, а 3.3В, но для пользователя это ни на что не влияет. В итоге, схема получается проще некуда: просто подключаем кнопку, которая соединяет вывод с “землей”:

А вот код, в отличие от Arduino, будет немного отличаться.

Точнее говоря, есть два способа.

Способ-1. Код в стиле Arduino.

import RPi.GPIO as GPIO

import time

btn_pin = 24 # Button to GPIO24

# Setup

GPIO.setmode(GPIO.BCM)

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

try:

# Loop

while True:

button_state = GPIO.input(btn_pin)

if button_state == False:

print 'Button Pressed...'

time.sleep(0.2)

except:

GPIO.cleanup()

Как можно видеть, здесь состояние кнопок читается в бесконечном цикле while True, и если значение кнопки равно логическому нулю, мы делаем какое-то действие.

Чем плох этот код? Он нормально работает на Arduino, т.к. там используется простой процессор, умеющий выполнять только одну задачу. Но на Raspberry Pi используется многоядерный процессор и полноценная многозадачная операционная система Linux, и постоянно работающий бесконечный цикл будет лишь зря забирать ресурсы процессора.

Гораздо правильнее “подписаться” на системные уведомления об изменении состояния кнопки, тогда код автоматически вызовется когда нужно.

Способ-2. Код с использованием событий (events).

import RPi.GPIO as GPIO

import time

btn_pin = 24 # Button to GPIO24

# Setup

GPIO.setmode(GPIO.BCM)

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

def btn_callback(channel):

if GPIO.input(btn_pin) != False:

print "Rising edge detected"

else:

print "Falling edge detected"

GPIO.add_event_detect(btn_pin, GPIO.RISING, callback=btn_callback, bouncetime=300)

# Loop

try:

while True:

time.sleep(1.0)

except:

GPIO.cleanup()

Разница значительна - здесь в основном цикле программы не делается ничего, кроме вызова time.sleep, такой код будет гораздо меньше нагружать процессор. Когда кнопка будет нажата, сработает функция btn_callback. Функция здесь только выводит сообщение, в реальном коде может обновляться содержимое дисплея или выполняться какое-то другое действие. Как можно видеть из кода, можно подписаться как на срабатывание кнопки (GPIO.RISING), так и на ее отпускание.

Разумеется, в реальном проекте может быть более одной кнопки, достаточно будет лишь добавить соответствующие вызовы GPIO.setup и GPIO.add_event_detect.

Самостоятельная работа: изучить код вывода текста на дисплей из предыдущей части, и объединив его с чтением состояния 4х кнопок, сделать систему меню. Простор для творчества тут большой, можно например использовать кнопки “вверх”, “вниз”, “OK” и “Cancel”.

4.8. Выходим в Web: запросы к серверу

Мы уже рассматривали получение количества друзей в “Контакте” в главе 3.6. Сделаем тот же самый запрос на языке Python. Здесь мы видим всю красоту и мощность данного языка, позволяющего делать вполне сложные вещи очень коротко и лаконично. Весь код умещается в 6 строк:

import json, urllib2

url = "https://api.vk.com/method/friends.get?user_id=29744451"

try:

data = json.load(urllib2.urlopen(url))

cnt = len(data['response'])

print cnt

except:

pass

Кстати, одна из полезных особенностей Python - его кроссплатформенность. Этот код можно выполнить и на Raspberry Pi, и на Windows, и на OSX, он будет работать одинаково.

Практически, подобные фрагменты удобно вынести в отдельную функцию, это делает код читабельнее и понятнее.

def getFriends(friendID):

url = "https://api.vk.com/method/friends.get?user_id=" + str(friendID)

try:

data = json.load(urllib2.urlopen(url))

cnt = len(data['response'])

return cnt

except:

return -1

Тогда вызвать его можно так:

n = getFriends(29744451)

print “Number of friends:”, n

Аналогично с числом подписчиков канала Youtube, все это можно записать в виде функции:

apiKey = "AIzaSyC26UJw-ubU6NXXXXXXXXXXXXXXXXXX"

def getSubscribersCount(channelID):

url = "https://www.googleapis.com/youtube/v3/channels?id=" + channelID + "&part=statistics&key=" + apiKey