Raspberry Piで超簡易オーディオプレイヤー 「竹」2020年版
Raspberry Piで超簡易オーディオプレイヤー 「竹」2020年版
「ボタンを押すと、楽曲ファイルが演奏され、もう一度ボタンを押すと演奏が止まる」という、誠に単純な機能を持つ装置
Raspberry Piに液晶キャラクタディスプレイ(LCD)とDACデバイスを接続した超簡易オーディオプレイヤー
2020年版では、iPhoneやiPad, Macの「ミュージック」アプリの音声を出力できるAirPlayにも対応
インストールしたOSイメージ
2020-08-20-raspios-buster-armhf.img
基本的な設定は、(すべてのデバイスで共通)Raspberry Pi OS の基本設定を参照。
本機では、MM5102 というDACデバイスを使っているため、OSでDAC関連の設定が必要
(次の行を追加する)
snd_soc_bcm2708bcm2708_dmaenginesnd_soc_pcm5102asnd_soc_hifiberry_dac(次の行を追加する)
dtoverlay=hifiberry-dac $ aplay -l
これでUSB-DACのcard番号を調べる
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 }iPhoneやiPad, Macの「ミュージック」アプリの音声を出力できるAirPlayに対応させる設定
必要なライブラリおよびgitのインストール
$ sudo apt install git autoconf libdaemon-dev libpopt-dev libconfig-dev libasound2-dev libpulse-dev libavahi-client-dev libssl-dev libsoxr-dev $ 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コマンド 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”; $ sudo systemctl start shairport-sync $ sudo systemctl enable shairport-sync $ pip3 install python-vlc $ pip3 install smbusPython3を使って、実装する。
(ソースコード:ファイル名 lcdsimpleplayer.py)
#!/usr/bin/env python3# coding:utf-8# RapsberryPi Simple Music Player with LCD (AQM0802)import RPi.GPIO as GPIOimport subprocessimport vlcimport pathlibimport randomimport smbusimport timeimport sysimport osclass 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最後に下記のエントリを追加
@pcmanfm -d@/home/pi/simpleplayer/lcdsimpleplayer.py