Raspberry Piで超簡易オーディオプレイヤー 「竹」2020年版
小型液晶ディスプレイ搭載
AirPlay対応プレイヤー
「ボタンを押すと、楽曲ファイルが演奏され、もう一度ボタンを押すと演奏が止まる」という、誠に単純な機能を持つ装置
Raspberry Piに液晶キャラクタディスプレイ(LCD)とDACデバイスを接続した超簡易オーディオプレイヤー
2020年版では、iPhoneやiPad, Macの「ミュージック」アプリの音声を出力できるAirPlayにも対応
Raspberry Pi OSのインストール
インストールしたOSイメージ
2020-08-20-raspios-buster-armhf.img
基本的な設定は、(すべてのデバイスで共通)Raspberry Pi OS の基本設定を参照。
回路図
DACデバイスを使う設定
本機では、MM5102 というDACデバイスを使っているため、OSでDAC関連の設定が必要
ファイル:/etc/modules
(次の行を追加する)
snd_soc_bcm2708
bcm2708_dmaengine
snd_soc_pcm5102a
snd_soc_hifiberry_dac
ファイル:/boot/config.txt
(次の行を追加する)
dtoverlay=hifiberry-dac
Sound Cardとdevice numberの確認
$ aplay -l
これでUSB-DACのcard番号を調べる
ファイル:/home/pi/.asoudrc
HDMIディスプレイを接続したときと外したときで、DACサウンドカードの番号が変化するので、設定が異なる。
(変更箇所)HDMIディスプレイを使用する場合
pcm.output {
type hw
card 2
}
ctl.!default {
type hw
card 2
}
(変更箇所)HDMIディスプレイを接続しない場合
pcm.output {
type hw
card 1
}
ctl.!default {
type hw
card 1
}
AirPlay対応の設定
iPhoneやiPad, Macの「ミュージック」アプリの音声を出力できるAirPlayに対応させる設定
Shairport-syncのインストール
必要なライブラリおよびgitのインストール
$ sudo apt install git autoconf libdaemon-dev libpopt-dev libconfig-dev libasound2-dev libpulse-dev libavahi-client-dev libssl-dev libsoxr-dev
shairport-syn のファイル取得とビルド、インストール
$ git clone https://github.com/mikebrady/shairport-sync.git
$ cd shairport-sync
$ autoreconf -i -f
$ ./configure --sysconfdir=/etc --with-alsa --with-pa --with-avahi --with-ssl=openssl \
--with-metadata --with-soxr --with-systemd
$ make && sudo make install
shairport-sync設定ファイルの編集
コマンド aplay -l
で 確認したカード番号をもとにファイル/etc/shairport-sync.confを編集する
$ sudo vi /etc/shairport-sync.conf
(編集する部分)
general =
{
name = "AirPlay%H"; //AirPlayサーバの名前(任意)
}
(USB-DACを出力として使うための変更部分)
(変更前)
alsa = {
output_device = “default”;
( HDMI使用時にUSB-DACを出力として使うための変更部分(DACのcardが 2 の場合))
alsa = {
output_device = “hw:2,0”;
(HDMI使用しないときにUSB-DACを出力として使うための変更部分(DACのcardが 1の場合))
alsa = {
output_device = “hw:1,0”;
Shairport起動
$ sudo systemctl start shairport-sync
OS 起動時にShairportが起動するよう設定する。
$ sudo systemctl enable shairport-sync
音楽再生アプリのための設定
PythonでVLCを制御するためのパッケージのインストール
$ pip3 install python-vlc
I2C用Python moduleのインストール
$ pip3 install smbus
オーディオプレイヤーのソフトウェア
Python3を使って、実装する。
(ソースコード:ファイル名 lcdsimpleplayer.py)
#!/usr/bin/env python3
# coding:utf-8
# RapsberryPi Simple Music Player with LCD (AQM0802)
import RPi.GPIO as GPIO
import subprocess
import vlc
import pathlib
import random
import smbus
import time
import sys
import os
class LcdAqm0802:
#LCD AE-AQM0802 controller class
#参考 https://www.denshi.club/pc/raspi/i2caqmlcdarduinode1-aqm0802.html
# class valiables
i2c = smbus.SMBus(1) # 1 is bus number
addr02=0x3e #LCD のアドレス
_command=0x00
_data=0x40
_clear=0x01
_home=0x02
display_On=0x0f
display_Off=0x08
cursor_Off=0x0c
LCD_2ndline=0x40+0x80
#LCD AQM0802/1602
def __init__ (self):
self.command(0x38) # Function set
self.command(0x39) # Function set
self.command(0x14) # Internal OSC frequency
self.command(0x70) # Contrast set
self.command(0x56) # Power/ICON/Contrast control
self.command(0x6c) # Follower control
self.command(0x38) # Function set
self.command(LcdAqm0802.cursor_Off) # dislay On , cursor off
self.command(LcdAqm0802._clear) # Clear Display
def command( self, code ):
LcdAqm0802.i2c.write_byte_data(LcdAqm0802.addr02, LcdAqm0802._command, code)
time.sleep(0.1)
def write( self, message ):
mojilist=[]
for moji in message:
mojilist.append(ord(moji))
LcdAqm0802.i2c.write_i2c_block_data(LcdAqm0802.addr02, LcdAqm0802._data, mojilist)
time.sleep(0.1)
def moveHome(self):
self.command(LcdAqm0802._home)
def move2ndLine(self):
self.command(LcdAqm0802.LCD_2ndline)
def clear(self):
self.command(LcdAqm0802._clear)
def displayOff(self):
self.command(LcdAqm0802.display_Off)
class SimplePlayer:
def __init__(self, master=None):
self.set_gpio()
self.status = "STOP"
# LCDの生成
self.lcd = LcdAqm0802()
self.lcd.clear()
self.lcd.moveHome()
self.lcd.write("--BOOT--")
#create VLC instance
self.vlcp = vlc.MediaListPlayer() # VLC Media List Player
# VLC Volume 50%
#self.VLC_volume = 50
# VLC Volume 80%
self.VLC_volume = 80
self.vlcp_media_player=self.vlcp.get_media_player() # get media player instance from media list palyer
#self.vlcp_media_player.audio_output_device_set(None, "hw:2,0")#set device DAC (HDMI connected)
#self.vlcp_media_player.audio_output_device_set(None, "hw:1,0")#set device DAC
self.vlcp_media_player.audio_set_volume(self.VLC_volume) # volume set to media player
self.vlcp.set_playback_mode(vlc.PlaybackMode.loop) #vlc playback mode をloop(play listの繰り返しに)
# Play Listの生成
self.vlcp.set_media_list( self.get_media_list() ) #set media list
# 起動メッセージ
self.lcd.clear()
self.lcd.moveHome()
self.lcd.write("miniVLCp")
def on_closing(self):
if self.status == "PLAY" :
self.vlcp.stop() #曲の停止
print("--STOP--")
self.lcd.clear() #LCD 表示を消去
self.lcd.displayOff() #LCD 表示終了
GPIO.cleanup(22) # Cleanup GPIO 22
def get_media_list(self):
#メディアリストを更新し、返す。
print("--LIST--")
p_temp_media_list = vlc.MediaList() # MediaListを生成
#メディアファイルのpathのリストを取得
p_temp = pathlib.Path('/media/pi/64GBSDXC') #USBメモリのパスを設定(Raspbian Desktop)
#p_temp = pathlib.Path('/media/usb') #USBメモリのパスを設定(Raspbian LITE + usbmount)
length_mrl_list = 0 #mrl_listの要素数を初期化
while length_mrl_list <= 0 : #有効な要素数が得られなければ
# デバッグ用メッセージを2行目に出力
self.lcd.move2ndLine()
self.lcd.write("--LIST--")
print ("LISTING")
mrl_list = [] #mrl(楽曲ファイルのPATH)のリストの初期化
extension_mrl_list = list(p_temp.glob('**/*.m[4p][3a]')) # 楽曲拡張子mp3,m4aのファイル名を取得
mrl_list.extend(extension_mrl_list)
length_mrl_list = len(mrl_list) #mrl_listの要素数を取得
# デバッグ用メッセージをクリア
self.lcd.move2ndLine()
self.lcd.write("STANDBY-")
print ("LISTING DONE")
for i in range(length_mrl_list):
mrl = random.choice(mrl_list)
p_temp_media_list.add_media(str(mrl))#リストからランダムに取り出す
#print(mrl) #DEBUG
return p_temp_media_list
def vlc_play(self):
if self.status == "STOP" :
self.status = "PLAY"
print("--PLAY Ready--")
# Music media files in /media/pi directory
self.vlcp.play() # 曲の再生
#再生中にメディアリストを再構築する
self.vlcp.set_media_list( self.get_media_list() ) #set media list
self.lcd.move2ndLine() #LCD 2行目に移動
self.lcd.write("--PLAY--") #LCDにPLAYと表示
print("-- PLAYING --")
else:
self.status = "STOP"
self.vlcp.stop() #曲の停止
print("--STOP--")
self.lcd.move2ndLine() #LCD 2行目に移動
self.lcd.write("--STOP--")
print("-- STOPPED --")
def play_sound_gpio(self):
print("EDGE DETECTED!")
waittimercounter = 0
while True:
time.sleep(0.4) # wait 0.4 seconds
charbar = "********" # シャットダウンまでにLCDに表示する文字列
print("SW: PRESSED")
if GPIO.input(22) == True:
# ボタン(PORT22)が押されていないときは
print("SW: RELEASED")
break# Exit
else:
# ボタン(PORT22)が押されているときは
self.lcd.move2ndLine()
self.lcd.write(charbar[:waittimercounter])
waittimercounter += 1 # ボタンの押された回数のカウンタを1増やす
if waittimercounter >= 7: # ボタンのカウンタが規定数になったら終わり
print('SW: LONG PRESSED')
self.on_closing() #終了時処理
os.system("sudo shutdown -h now") # System Shut down
# VLC palyer control by GPIO
self.vlc_play()
def set_gpio(self):
GPIO.setmode(GPIO.BCM) #GPIO Access by BCM
GPIO.setup(22, GPIO.IN, pull_up_down = GPIO.PUD_UP) #BCM PIN-22 as Input
####################################################
app = SimplePlayer()
while True: # Infinity LOOP
print("Wait for EDGE")
GPIO.wait_for_edge(22, GPIO.FALLING)#ボタンが押されるまで待つ
app.play_sound_gpio() #再生処理
ソースコードの保存
ソースコードを(Python3)をlcdsimpleplayer.py
という名前で保存
場所は/home/pi/simpleplayer/
ソースコードを実行可能に設定する。
$ chmod +x /home/pi/simpleplayer/lcdsimpleplayer.py
OSの起動時に自動的に起動するように設定する。
編集するファイル: /home/pi/.config/lxsession/LXDE-pi/autostart
最後に下記のエントリを追加
@pcmanfm -d
@/home/pi/simpleplayer/lcdsimpleplayer.py