Здрастє, я Tarasius. Це мій бложик.

Особисті думки, нариси, проекти та коротко про мене

Raspberry Pi: Кнопки

Для того, щоб підключені до Распі кнопки почали щось робити, необхідно написати скрипт-демон, який би реагував на зміни стану GPIO. Розглянемо приклад такого скрипту, написаного на Python, який оброблятиме довгі та короткі натиснення кожної кнопки та їх комбінацій.

Нехай маємо чотири кнопки. Я писав обробку кнопок послідовно, без циклу. Так простіше і я не думаю що в когось буде так багато кнопок, що доведеться писати цикл.

Логіка проста. Ми переводимо вказані піни GPIO в режим зчитування високої напруги. Далі ми входимо в безкінечний цикл з невеликою паузою, в якому запам’ятовуємо теперішні значення пінів та порівнюємо з попередніми. Якщо значення відрізняється – статус кнопки змінився. А додавши ще й таймер, ми можемо зробити тригер довго натиснення кнопки:

якщо кнопка була натиснута, а зараз не натиснута, і з часу натиснення пройшо більше 2 секунд, то реагуємо на довге натиснення кнопки.

Точно так само можна обробляти комбінації кнопок, додавши умову для двох (або й більше) кнопок одночасно. Отже, наступний скрипт обробляє довгі та короткі натиснення на чотири кнопки та одночасне натиснення на першу і другу.

# This Python file uses the following encoding: utf-8
# /leds+buttons/buttondaemon.py
import RPi.GPIO as GPIO
import time
import os
import sys
import logging

logger = logging.getLogger('buttons_daemon')
hdlr = logging.FileHandler('/MyLogs/main.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.WARNING)
suffix = " > /dev/null&"

#adjust for where your switch is connected
button1Pin = 18
button2Pin = 13
button3Pin = 16
button4Pin = 15
prev_input1 = 0
prev_input2 = 0
prev_input3 = 0
prev_input4 = 0
btimer12 = 0
btimer1= 0
btimer2= 0
btimer3= 0
btimer4= 0

GPIO.setmode(GPIO.BOARD)
GPIO.setup(button1Pin,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(button2Pin,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(button3Pin,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(button4Pin,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

while True:
  #assuming the script to call is long enough we can ignore bouncing
  input1 = GPIO.input(button1Pin)
  input2 = GPIO.input(button2Pin)
  input3 = GPIO.input(button3Pin)
  input4 = GPIO.input(button4Pin)

  if (input1):
    btimer1 += 1
  if (input2):
    btimer2 += 1
  if (input3):
    btimer3 += 1
  if (input4):
    btimer4 += 1

  #Some button up
  if ((not input1) and (not input2) and (not input3) and (not input4) and ( (prev_input1) or (prev_input2) or (prev_input3) or (prev_input4) ) ):

    #Button 12
    if ((prev_input1) and (prev_input2) and (not prev_input3) and (not prev_input4) ):
      if ((btimer1>20) and (btimer2>20)):
        logger.warning("Button12 long");
        os.system("/leds+buttons/button12long"+suffix)
      else:
        logger.warning("Button12");
        os.system("/leds+buttons/button12"+suffix)

    #Button 1
    if ((prev_input1) and (not prev_input2) and (not prev_input3) and (not prev_input4) ):
      if (btimer1>20):
        logger.warning("Button1 long");
        os.system("/leds+buttons/button1long"+suffix)
      else:
        logger.warning("Button1");
        os.system("/leds+buttons/button1"+suffix)

    #Button 2
    if ((prev_input2) and (not prev_input1) and (not prev_input3) and (not prev_input4) ):
      if (btimer2>20):
        logger.warning("Button2 long");
        os.system("/leds+buttons/button2long"+suffix)
      else:
        logger.warning("Button2");
        os.system("/leds+buttons/button2"+suffix)

    #Button 3
    if ((prev_input3) and (not prev_input2) and (not prev_input1) and (not prev_input4) ):
      if (btimer3>20):
        logger.warning("Button3 long");
        os.system("/leds+buttons/button3long"+suffix)
      else:
        logger.warning("Button3");
        os.system("/leds+buttons/button3"+suffix)

    #Button 4
    if ((prev_input4) and (not prev_input2) and (not prev_input3) and (not prev_input1) ):
      if (btimer4>20):
        logger.warning("Button4 long");
        os.system("/leds+buttons/button4long"+suffix)
      else:
        logger.warning("Button4");
        os.system("/leds+buttons/button4"+suffix)

    btimer1=0
    btimer2=0
    btimer3=0
    btimer4=0

  prev_input1 = input1
  prev_input2 = input2
  prev_input3 = input3
  prev_input4 = input4
  time.sleep(0.2)

При натисненні певної кнопки чи комбінації буде викликатись відповідний баш-скрипт з папки /leds+buttons. Створимо файли-пустишки з відповідними ім’ями як  в скрипті. Приклад такого файлу ( button1long ):

#!/bin/bash
echo Starting XBMC | wall
/usr/lib/xbmc/xbmc.bin
exit

Тепер з нашого пітонівського скрипту зробимо демон. Створимо файлик в папці /etc/init.d під назвою buttondaemon

#! /bin/sh
# /etc/init.d/buttondaemon

### BEGIN INIT INFO
# Provides: buttondaemon
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Daemon to control button events
# Description: Daemon which starts python script to control GPIO button events.
### END INIT INFO

# If you want a command to always run, put it here

# Carry out specific functions when asked to by the system
case "$1" in
start)
echo "Starting button daemon"
# run application you want to start
sudo python /leds+buttons/buttondaemon.py&
;;
stop)
echo "Stopping button daemon"
# kill application you want to stop
kill -9 $(ps -ef | grep -v "grep" | grep buttondaemon.py | awk '{ print $2 }') &> /dev/null
;;
*)
echo "Usage: /etc/init.d/buttondaemon {start|stop}"
exit 1
;;
esac

exit 0

Команда start запускає наш пітонівський скрипт, а команда stop його зупиняє. Роздамо всім скриптам потрібні права. Тепер можемо випробувати, набрав в консолі

sudo /etc/init.d/buttondaemon start

і пожмакаємо кнопки, дивлячись що буде відображатись на екрані. Вуаля!

 

Сподобалось? Поділися з друзями!

Позначки:, ,

Категорія: Інженерія. Автор: tarasius. Опубліковано 10 лютого 2015р. в 15:06.

Прокоментуй!

Попередній пост:   Наступний пост:



Прокоментуй!


Залишити коментар