Raspberry PI с кнопками ввода GPIO

У меня есть PI с 4 входными портами GPIO. Цель состоит в том, что если будет нажата одна из 4 кнопок, должен быть воспроизведен файл mp3, то есть button1 = file1.mp3, button2 = file2.mp3 и так далее. Вроде бы все не так сложно, но «дьявол кроется в деталях» :-) Это мой код для двух кнопок на данный момент:

#!/usr/bin/env python
#coding: utf8

import time 
from time import sleep
import os
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(23, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)


def my_callback_1(channel):
  print("Button 23 Pressed")
  os.system('omxplayer -o both /root/1.mp3')
  sleep(10)

def my_callback_2(channel):
  print("Button 24 Pressed")
  os.system('omxplayer -o both /root/2.mp3')
  sleep(10)

GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback_1, bouncetime=200)
GPIO.add_event_detect(24, GPIO.RISING, callback=my_callback_2, bouncetime=200)

try:
  while 1:
          time.sleep(0.5)

except KeyboardInterrupt:
    # exits when you press CTRL+C
    print("  Bye Bye") 

except:
    print("Other error or exception occurred!")

finally:
    GPIO.cleanup() # this ensures a clean exit

Время сна устанавливается на большее время для файла mp3. Он работает, но не так, как я ожидал. Проблема в том, что когда кнопка будет нажата во время воспроизведения файла, PI удерживает нажатой кнопку в буфере и воспроизводит файл после текущего файла в цикле. Представьте, кто-то 5 раз нажмет одну и ту же кнопку, 5 раз один и тот же mp3-файл будет воспроизводиться в цикле.

Поэтому я искал решение вроде этого: пока файл воспроизводится, все кнопки ввода должны быть на это время "отключены". Когда оплата mp3-файла будет завершена, кнопки должны быть «повторно включены», и можно будет нажать другую кнопку.

Как я могу это сделать? Спасибо за вашу помощь.


person wetbike01    schedule 10.12.2015    source источник
comment
Во время воспроизведения файла все кнопки ввода должны быть отключены - это точка зрения пользователя. На уровне программирования вход не должен или не может быть отключен. Программа должна принимать ввод и обрабатывать (или нет) событие в зависимости от текущего состояния игрока. Событие будет отключено или включено вашей программой обработки, игнорирующей или обрабатывающей каждое событие.   -  person sawdust    schedule 10.12.2015


Ответы (2)


Я не вижу простого способа сделать это без добавления потоков. Обратите внимание, что вы неявно уже используете потоки за кулисами с add_event_detect(), который запускает обратные вызовы в отдельных потоках. Если add_event_detect не поддерживает подавление нажатий кнопок (чего я не думаю), то вы можете выполнить его одним из двух способов - с помощью потоков или процессов python или более простым способом с помощью bash.

Чтобы использовать фоновые процессы в bash, удалите свои add_event_detect вызовы, а затем в цикле while сделайте что-то вроде (непроверено):

started_23 = 0
while True:
    if GPIO.input(23) and time.time() - started_23 > 10:
        started_23 = time.time()
        print("Button 23 Pressed")
        os.system('omxplayer -o both /root/1.mp3 &')
    time.sleep(0.200)

Обратите внимание на амперсанд, добавленный к вызову system (), который запустит omxplayer в фоновом режиме. А переменная start_23 отслеживает, когда был запущен звук, чтобы предотвратить его повторное воспроизведение в течение следующих 10 секунд. Вы можете увеличить это, чтобы включить длину файла. Аналогичным образом вы можете добавить код для GPIO 24 в том же цикле.

person Brian    schedule 10.12.2015

Спасибо за помощь, Брайан. Ты направил меня в правильном направлении! Я понял. Теперь он работает, как я описал выше. Вот мой код:

try:

        vtc1 = 8        # Time Audiofile 1
        vtc2 = 11       # Time Audiofile 2
        vtc3 = 0        # Time Audiofile 3
        vtc4 = 0        # Time Audiofile 4

        vtc = 0         # Current AudioFileTime
        started_t = 0   # Started Time


        while True:
                if GPIO.input(23) and time.time() - started_t > vtc:
                        vtc = vtc1
                        started_t = time.time()
                        print("Button 23 Pressed")
                        os.system('omxplayer -o both /root/1.mp3 &')
                time.sleep(0.200)

                if GPIO.input(24) and time.time() - started_t > vtc:
                        vtc = vtc2
                        started_t = time.time()
                        print("Button 24 Pressed")
                        os.system('omxplayer -o both /root/2.mp3 &')
                time.sleep(0.200)

Проблема заключалась в том, что прикомандированный файл был запущен до того, как был закончен первый. Потому что код не знал, какой файл длиннее воспроизводится в данный момент. Поэтому я поместил время аудиофайла в значение "vtc", когда этот файл был запущен. Если вы нажмете другую кнопку, он вычислит время воспроизведения с текущим временем файла «vtc». Вот и все. Спасибо еще раз.

person wetbike01    schedule 11.12.2015