diff --git a/code/piplayer2.py b/code/piplayer2.py index edcc3f9..06a8cc5 100644 --- a/code/piplayer2.py +++ b/code/piplayer2.py @@ -1,22 +1,21 @@ # piplayer2 # http://www.tilman.de/piplayer2 - import RPi.GPIO as GPIO import logging import time import subprocess -import select # see http://stackoverflow.com/a/10759061/3761783 +import select # for polling zbarcam, see http://stackoverflow.com/a/10759061/3761783 import os # Configuration -MUSIC_BASE_DIRECTORY = "/home/pi/audio/" +MUSIC_BASE_DIRECTORY = "/home/pi/music/" SOUND_SCANNING = "/home/pi/piplayer2/sounds/scanning.mp3" SOUND_OK = "/home/pi/piplayer2/sounds/ok.mp3" SOUND_SCAN_FAIL = "/home/pi/piplayer2/sounds/fail.mp3" -SOUND_PLAYBACK_ERROR = "/home/pi/piplayer2/sounds/no.mp3" +SOUND_PLAYBACK_ERROR = "/home/pi/piplayer2/sounds/error.mp3" QR_SCANNER_TIMEOUT = 3 -BUTTON_PAUSE = 0.4 +BUTTON_PAUSE = 400 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s.%(msecs)d %(levelname)s - %(message)s') @@ -41,8 +40,23 @@ GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP) +def btn1_callback(channel): + logging.debug('mocp --previous') + subprocess.call(["mocp", "--previous"]) -photo_sensor_still_active = False +def btn2_callback(channel): + logging.debug('mocp --toggle-pause') + subprocess.call(["mocp", "--toggle-pause"]) + +def btn3_callback(channel): + logging.debug('mocp --next') + subprocess.call(["mocp", "--next"]) + + + +GPIO.add_event_detect(9, GPIO.FALLING, callback=btn1_callback, bouncetime=BUTTON_PAUSE) +GPIO.add_event_detect(10, GPIO.FALLING, callback=btn2_callback, bouncetime=BUTTON_PAUSE) +GPIO.add_event_detect(11, GPIO.FALLING, callback=btn3_callback, bouncetime=BUTTON_PAUSE) try: logging.info('Start moc server') @@ -51,126 +65,111 @@ try: subprocess.call(["mocp", "-l", SOUND_OK]) while True: - time.sleep(0.05) + logging.debug('Wait for photo sensor') + GPIO.wait_for_edge(17, GPIO.RISING) - if (GPIO.input(9) == False): - logging.debug('mocp --previous') - subprocess.call(["mocp", "--previous"]) - time.sleep(BUTTON_PAUSE) - # TODO wait for ~0.25 s, if button is still pressed, seek instead of skipping - - if (GPIO.input(10) == False): - logging.debug('mocp --toggle-pause') - subprocess.call(["mocp", "--toggle-pause"]) - time.sleep(BUTTON_PAUSE) - - if (GPIO.input(11) == False): - logging.debug('mocp --next') - subprocess.call(["mocp", "--next"]) - time.sleep(BUTTON_PAUSE) - # TODO wait for ~0.25 s, if button is still pressed, seek instead of skipping + logging.debug('Photo sensor active, activating light and camera') + subprocess.call(["mocp", "-l", SOUND_SCANNING]) - # check photo sensor - if ((not photo_sensor_still_active) and (GPIO.input(17) == GPIO.HIGH)): - logging.debug('Photo sensor active, activating light and camera') - subprocess.call(["mocp", "-l", SOUND_SCANNING]) + # turn LED on + GPIO.output(27, GPIO.HIGH) + + # scan QR code + zbarcam = subprocess.Popen(['zbarcam', '--quiet', '--nodisplay', '--raw', '-Sdisable', '-Sqrcode.enable', '--prescale=320x240', '/dev/video0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + poll_obj = select.poll() + poll_obj.register(zbarcam.stdout, select.POLLIN) + + # wait for scan result (or timeout) + start_time = time.time() + poll_result = False + while ((time.time() - start_time) < QR_SCANNER_TIMEOUT and (not poll_result)): + poll_result = poll_obj.poll(100) + + if (poll_result): - # turn LED on - GPIO.output(27, GPIO.HIGH) - - # scan QR code - zbarcam = subprocess.Popen(['zbarcam', '--nodisplay', '--raw', '-Sdisable', '-Sqrcode.enable', '--prescale=320x240', '/dev/video0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - poll_obj = select.poll() - poll_obj.register(zbarcam.stdout, select.POLLIN) - - # wait for scan result (or timeout) - start_time = time.time() - poll_result = False - while ((time.time() - start_time) < QR_SCANNER_TIMEOUT and (not poll_result)): - poll_result = poll_obj.poll(100) - - if (poll_result): + try: + qr_code = zbarcam.stdout.readline().rstrip() + qr_code = qr_code.decode("utf-8") # python3 + logging.debug("QR Code: {}".format(qr_code)) - try: - - qr_code = zbarcam.stdout.readline().rstrip() - qr_code = qr_code.decode("utf-8") # python3 - logging.debug("QR Code: {}".format(qr_code)) + if (not qr_code.startswith("http://")): + # create full path + full_path = MUSIC_BASE_DIRECTORY + qr_code + logging.debug("Full Path {}".format(full_path)) - if (not qr_code.startswith("http://")): - # create full path - full_path = MUSIC_BASE_DIRECTORY + qr_code - logging.debug("Full Path {}".format(full_path)) - - if (not os.path.isfile(full_path)): - logging.debug("not a file, add as directory") - directory = full_path - logging.debug("Directory {}".format(directory)) - else: - logging.debug("it's a file") - directory = os.path.dirname(os.path.realpath(full_path)) - filename = os.path.basename(full_path) - logging.debug("Directory {}".format(directory)) - logging.debug("Filename {}".format(filename)) - - os.chdir(directory) - + if (not os.path.isfile(full_path)): + logging.debug("not a file, add as directory") + directory = full_path + logging.debug("Directory {}".format(directory)) else: - logging.debug("URL, open as stream") - stream_url = qr_code + logging.debug("it's a file") + directory = os.path.dirname(os.path.realpath(full_path)) + filename = os.path.basename(full_path) + logging.debug("Directory {}".format(directory)) + logging.debug("Filename {}".format(filename)) - subprocess.call(["mocp", "--clear"]) - subprocess.call(["mocp", "--stop"]) - - logging.debug("Stopped") + os.chdir(directory) - # play confirmation sound - subprocess.call(["mocp", "-l", SOUND_OK]) - - if ('stream_url' in locals()): - logging.debug("Add stream") - subprocess.check_call(["mocp", "-a", stream_url]) - del stream_url - elif ('filename' in locals()): - logging.debug("Add file {}".format(filename)) - subprocess.check_call(["mocp", "-a", filename]) - del filename - else: - logging.debug("Add directory {}".format(directory)) - subprocess.check_call(["mocp", "-a", "."]) - - # subprocess.check_call(["mocp", "-a", target, "-p"]) - logging.debug("Start playback") - subprocess.check_call(["mocp", "-p"]) - - except subprocess.CalledProcessError as e: - logging.debug("Error starting playback, mocp returned {}".format(e.returncode)) - logging.debug(e.output) - subprocess.call(["mocp", "-l", SOUND_PLAYBACK_ERROR]) - except FileNotFoundError as e: - logging.debug("Could not open directory {}".format(directory)) - subprocess.call(["mocp", "-l", SOUND_PLAYBACK_ERROR]) - else: - logging.debug('Timeout on zbarcam') - subprocess.call(["mocp", "-l", SOUND_SCAN_FAIL]) + else: + logging.debug("URL, open as stream") + stream_url = qr_code + + subprocess.call(["mocp", "--clear"]) + subprocess.call(["mocp", "--stop"]) + + logging.debug("Stopped") - # consider the photo sensor to be blocked - photo_sensor_still_active = True - - zbarcam.terminate() - - # LED off - GPIO.output(27, GPIO.LOW) - - elif (GPIO.input(17) == GPIO.LOW): - # the photo sensor is not blocked (anymore) - photo_sensor_still_active = False - + # play confirmation sound + subprocess.call(["mocp", "-l", SOUND_OK]) + + if ('stream_url' in locals()): + logging.debug("Add stream") + subprocess.check_call(["mocp", "-a", stream_url]) + del stream_url + elif ('filename' in locals()): + logging.debug("Add file {}".format(filename)) + subprocess.check_call(["mocp", "-a", filename]) + del filename + else: + logging.debug("Add directory {}".format(directory)) + subprocess.check_call(["mocp", "-a", "."]) + + logging.debug("Start playback") + subprocess.check_call(["mocp", "-p"]) + + except subprocess.CalledProcessError as e: + logging.debug("Error starting playback, mocp returned {}".format(e.returncode)) + logging.debug(e.output) + subprocess.call(["mocp", "-l", SOUND_PLAYBACK_ERROR]) + except FileNotFoundError as e: + logging.debug("Could not open directory {}".format(directory)) + subprocess.call(["mocp", "-l", SOUND_PLAYBACK_ERROR]) + + else: + logging.debug('Timeout on zbarcam') + subprocess.call(["mocp", "-l", SOUND_SCAN_FAIL]) + zbarcam.terminate() + + # LED off + GPIO.output(27, GPIO.LOW) + + # wait until sensor is not blocked anymore + if (GPIO.input(17) == GPIO.HIGH): + GPIO.wait_for_edge(17, GPIO.FALLING) + time.sleep(1) + + # Exit when Ctrl-C is pressed except KeyboardInterrupt: + logging.info('Shutdown') + +finally: logging.info('Close moc server') subprocess.call(["mocp", "--exit"]) logging.info('Reset GPIO configuration and close') GPIO.cleanup() + + + diff --git a/code/test/interrupts.py b/code/test/interrupts.py index 3a5759b..80fb5b6 100644 --- a/code/test/interrupts.py +++ b/code/test/interrupts.py @@ -8,7 +8,7 @@ GPIO.setup(9, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP) -#sensor on PIN 17 +# Sensor on PIN 17 GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) def btn1_callback(channel): diff --git a/installation.txt b/installation.txt index 6d784a2..226854b 100644 --- a/installation.txt +++ b/installation.txt @@ -39,6 +39,7 @@ sudo nano /boot/config.txt # dtparam=act_led_trigger=none # dtparam=act_led_activelow=off +# configure NTP sudo apt install ntp sudo /etc/init.d/ntp restart sudo nano /etc/ntp.conf @@ -52,10 +53,17 @@ sudo apt install lirc zbar-tools mc moc fswebcam python3 python-rpi.gpio python3 # PHAT DAC (https://learn.pimoroni.com/tutorial/phat/raspberry-pi-phat-dac-install) curl -sS get.pimoroni.com/phatdac | bash +# check for errors +dmesg + # MP3-Test mocp sudo nano /etc/modprobe.d/alsa-base.conf +# Webcam-Auflösung bestimmen (http://askubuntu.com/questions/214977/how-can-i-find-out-the-supported-webcam-resolutions) +lsusb +lsusb -s 001:006 -v | egrep "Width|Height" + # Webcam-Test python3 lighton.py sudo fswebcam -r 320x240 -d /dev/video0 -v ~/test.jpg