Volumioプラグインを一つにしました [Volumio]
OPAです。
Volumioの曲名とサウンドメーターのプラグインを一つにまとめました。
あと要望としてあった、曲停止時にスクリーンセーバー的なものを入れました。
設定画面でいろいろと設定できます。
https://www.dropbox.com/s/jqwikzb5xg0l4tf/ssd1306I2c_Integration_display_20190429_2.zip?dl=0
I2Cアドレスは、秋月電子様のモジュール以外は試していないので、動作は確認できていません。またGPIO PINによるI2Cアドレスの切り替えは、Raspbery Pi Zero wのGPIO26以外は試していません。
volumioのバグか不明ですが、マルチルームにすると曲名が正しく更新されません。もしかしたら本プラグインの負荷が高く、node.jsのイベント処理がついていけなくなっているのかもしれません。検証できていません。
Raspbery Pi zero w / Raspbery Pi 3B(GPIO PINのIc2アドレス切り替えは試していない)で確認しています。Raspbery Pi以外のプラットフォームは動作しません。node.jsモジュールのonoffモジュールがプラットフォーム依存になっているためです。
いろいろと制限ありますが、公開しますのでお試しください。
2019/4/23 追記
Raspbery Pi zero wだと、Volumioから送られてくる情報が更新されない場合があるようで、もしかしたらmpdから取得するように変更するかもしれません。
2019/4/28 追記
mpdモードを追加しました。volumioのwebsocketによるイベント処理だとうまく更新されてきません。mpdから直接情報を取るようにしてみました。しばらくこれで様子見です。また、mpdモードでは、出力フォーマット(ビットレート、サンプリング周波数)の情報をprocファイルシステムから取得できるようになっています。
2019/4/29更新>
再インストール時に、前のパッケージを削除するようにしました。
Volumioの曲名とサウンドメーターのプラグインを一つにまとめました。
あと要望としてあった、曲停止時にスクリーンセーバー的なものを入れました。
設定画面でいろいろと設定できます。
- ランダムモードを無効・有効に設定します
- サウンドメータのモードを設定します(VU Meter/Peak Meter/Spectrum)
- I2C アドレスを反転させます
- 曲名表示用のIC2アドレスを設定します(0x3C)
- VUメータ表示用I2Cアドレスを設定します(0x3D)
- GPIO PINによるアドレス切り替えを有効にします
- GPIO PINを選択します(2~27)
- スクリーンセーバーを選択します(BLANK/WATCH/LINE)
https://www.dropbox.com/s/jqwikzb5xg0l4tf/ssd1306I2c_Integration_display_20190429_2.zip?dl=0
I2Cアドレスは、秋月電子様のモジュール以外は試していないので、動作は確認できていません。またGPIO PINによるI2Cアドレスの切り替えは、Raspbery Pi Zero wのGPIO26以外は試していません。
volumioのバグか不明ですが、マルチルームにすると曲名が正しく更新されません。もしかしたら本プラグインの負荷が高く、node.jsのイベント処理がついていけなくなっているのかもしれません。検証できていません。
Raspbery Pi zero w / Raspbery Pi 3B(GPIO PINのIc2アドレス切り替えは試していない)で確認しています。Raspbery Pi以外のプラットフォームは動作しません。node.jsモジュールのonoffモジュールがプラットフォーム依存になっているためです。
いろいろと制限ありますが、公開しますのでお試しください。
2019/4/23 追記
Raspbery Pi zero wだと、Volumioから送られてくる情報が更新されない場合があるようで、もしかしたらmpdから取得するように変更するかもしれません。
2019/4/28 追記
mpdモードを追加しました。volumioのwebsocketによるイベント処理だとうまく更新されてきません。mpdから直接情報を取るようにしてみました。しばらくこれで様子見です。また、mpdモードでは、出力フォーマット(ビットレート、サンプリング周波数)の情報をprocファイルシステムから取得できるようになっています。
2019/4/29更新>
再インストール時に、前のパッケージを削除するようにしました。
週末の出来事(別館)開設!! [Volumio]
OPAです。
ファイルウェブのコミュニティに本ブログの別館を開設しました。
http://community.phileweb.com/mypage/entry/5253/20190326/62095/
プラグインを使用している方、感想などありましたらコメントいただければ幸いです。
ファイルウェブのコミュニティに本ブログの別館を開設しました。
http://community.phileweb.com/mypage/entry/5253/20190326/62095/
プラグインを使用している方、感想などありましたらコメントいただければ幸いです。
Volumioプラグインの更新 [Volumio]
OPAです。
曲名を表示するプラグインを更新しました。曲の時間と経過を示すプログレスバーの表示、 再生時に♫マークを出すようにしてみました。
https://www.dropbox.com/s/v53ujubne1a2229/ssd1306I2c_20190321_1.zip?dl=0
※2019/3/21 シャットダウン時に表示がクリアされない問題を直しました。
曲名を表示するプラグインを更新しました。曲の時間と経過を示すプログレスバーの表示、 再生時に♫マークを出すようにしてみました。
https://www.dropbox.com/s/v53ujubne1a2229/ssd1306I2c_20190321_1.zip?dl=0
※2019/3/21 シャットダウン時に表示がクリアされない問題を直しました。
Raspberry Pi Zero WにVolumioをインストールしてみた [Volumio]
OPAです。
以前作成した、PCM5102AのDAC基板と有機ELディスプレイ基板を使って、Raspberry Pi Zero WにVolumioをインストールしてみました。WiFiで接続できるメリットもありますが、不安定なWiFiでもあるので、ネットワークでの音楽共有ファイルを取得するのでなく、USBメモリで音楽ファイルを扱います。
組立前
組立後
メニューのDownloadを選択し、RASPBERRY PIのファイルをダウンロードします。
ダウンロードするタイミングでファイル名は異なります。
Writeボタンを押下してイメージを書き込みします。
https://www.dropbox.com/s/2zlv0r6gqaugadg/ssd1306I2c_20190224_1.zip?dl=0
Dropboxの画面で右上にあるダウンロードボタンを押下してファイルをダウンロードします。
Volumioというアクセスポイントがあるので、選択します。パスワードはvolumio2です。
http://volumio.local/
に接続します。
ここでは、Volumio3と名前を付けます。
I2S DACを有効にして、HiFiBerry DAC(PCM5102A)を選択します。
普段使用しているWiFiのアクセスポイントを選択して接続します。接続が成功すると以下のように画面が表示されます。
ネットワークドライブ(NAS)は使用しないので新規に追加しません。
Doneボタンを押下してセットアップを完了します。
再起動ボタンを押下して再起動します。
http://volumio3.local/
に接続できるか確認します。(しばらく経ってから)
にアクセスします。
SSHのENABLEボタンを押下します。特に画面に結果等は表示されません。
ホスト名にvolumio3.local、ユーザ名にvolumio、パスワードにvolumioを指定して接続します。
プラグインを選択して、ファイルを転送します。
TeraTermでvolumio3.localにアクセスします。
ユーザ名にvolumio、パスワードにvolumioを指定して接続します。
ターミナル上で以下のコマンドを実行してプラグインをインストールします。
インストールが完了すると以下のように表示されます。
インストール済みのプラグインのタブを選択し、SSD1306 I2C Displayプラグインが表示されていることを確認し、アクティブに変更します。
設定ボタンを押下します。
必要に応じて設定します。
プラグインの検索タブを押下し、System Toolsを選択します。
インストールボタンを押下して、GPIO Buttonsプラグインをインストールします。
インストール済みのプラグインのタブを押下し、GPIO Buttonsプラグインをアクティブにします。
設定ボタンを押下します。
以下のように設定します。
Play/Pause GPIO Pin 27
Previous GPIO Pin 22
Next GPIO Pin 17
Shutdown GPIO Pin 13
Saveボタンを押下して保存します。
音楽ライブラリを選択します。
USBのメニューからキューに追加を選択し、USBメモリにある音楽ファイルをキューに追加します。
以上です。参考まで。
以前作成した、PCM5102AのDAC基板と有機ELディスプレイ基板を使って、Raspberry Pi Zero WにVolumioをインストールしてみました。WiFiで接続できるメリットもありますが、不安定なWiFiでもあるので、ネットワークでの音楽共有ファイルを取得するのでなく、USBメモリで音楽ファイルを扱います。
組立前
組立後
Volumio2をダウンロード
https://volumio.org/メニューのDownloadを選択し、RASPBERRY PIのファイルをダウンロードします。
ダウンロードしたファイルを解凍
圧縮されたvolumio-2.555-2019-02-18-pi.img.zipを解凍し、volumio-2.555-2019-02-18-pi.imgイメージファイルを取り出します。ダウンロードするタイミングでファイル名は異なります。
イメージを書き込む
PCにSDカードを入れ、イメージライターを使ってイメージファイルをSDカードに書き込みます。Writeボタンを押下してイメージを書き込みします。
Raspberry Pi Zero WにSDカードを挿入
イメージを書き込んだSDカードをRaspberry Pi Zero Wに挿入します。プラグインをダウンロード
曲名を表示する自作プラグインをダウンロードします。https://www.dropbox.com/s/2zlv0r6gqaugadg/ssd1306I2c_20190224_1.zip?dl=0
Dropboxの画面で右上にあるダウンロードボタンを押下してファイルをダウンロードします。
USBメモリと電源を入れる
曲の入ったUSBメモリと、電源を接続してVolumioを起動します。PCのWiFi接続先を切り替える
私のPCのネットワーク接続は、WiFiを使用しています。Volumioはホットスポットモードで起動しますので接続を切り替えます。Volumioというアクセスポイントがあるので、選択します。パスワードはvolumio2です。
volumioのセットアップ
ブラウザで、http://volumio.local/
に接続します。
言語の選択
デバイス名の設定
ここでは、Volumio3と名前を付けます。
DACの設定
I2S DACを有効にして、HiFiBerry DAC(PCM5102A)を選択します。
WiFiの設定
普段使用しているWiFiのアクセスポイントを選択して接続します。接続が成功すると以下のように画面が表示されます。
ドライブの設定
ネットワークドライブ(NAS)は使用しないので新規に追加しません。
セットアップ完了
Doneボタンを押下してセットアップを完了します。
再起動
再起動ボタンを押下して再起動します。
WiFiを切り替える
普段使用しているWiFiのアクセスポイントに戻します。ブラウザで、http://volumio3.local/
に接続できるか確認します。(しばらく経ってから)
デバッグモードを設定する
http://volumio3.local/DEV/にアクセスします。
SSHのENABLEボタンを押下します。特に画面に結果等は表示されません。
プラグインをインストール
ダウンロードしたプラグインをWinSCPを使用してファイルをアップロードします。ホスト名にvolumio3.local、ユーザ名にvolumio、パスワードにvolumioを指定して接続します。
プラグインを選択して、ファイルを転送します。
TeraTermでvolumio3.localにアクセスします。
ユーザ名にvolumio、パスワードにvolumioを指定して接続します。
ターミナル上で以下のコマンドを実行してプラグインをインストールします。
volumio@volumio3:~$ miniunzip ssd1306I2c_20190224_1.zip volumio@volumio3:~$ cd ssd1306I2c volumio@volumio3:~/ssd1306I2c$ volumio plugin install
インストールが完了すると以下のように表示されます。
曲名を表示するプラグインの設定
ブラウザを開き、設定メニューからプラグインを選択し画面を表示します。インストール済みのプラグインのタブを選択し、SSD1306 I2C Displayプラグインが表示されていることを確認し、アクティブに変更します。
設定ボタンを押下します。
必要に応じて設定します。
GPIO Buttonsプラグインのインストール
作った有機ELディスプレイ基板にはGPIOのボタンがありますので、GPIO Buttonsプラグインをインストールして、ブラウザから操作せずにコントロールできるようにします。プラグインの検索タブを押下し、System Toolsを選択します。
インストールボタンを押下して、GPIO Buttonsプラグインをインストールします。
インストール済みのプラグインのタブを押下し、GPIO Buttonsプラグインをアクティブにします。
設定ボタンを押下します。
以下のように設定します。
Play/Pause GPIO Pin 27
Previous GPIO Pin 22
Next GPIO Pin 17
Shutdown GPIO Pin 13
Saveボタンを押下して保存します。
キューに曲を追加
ブラウザで、一覧表示を選択します。音楽ライブラリを選択します。
USBのメニューからキューに追加を選択し、USBメモリにある音楽ファイルをキューに追加します。
再生
再生ボタンを押下して、曲が再生され有機ELディスプレイに曲名が表示されるか確認します。以上です。参考まで。
有機ELディスプレイを使ったVolumioのプラグインを更新しました [Volumio]
OPAです。
有機ELディスプレイを使ったVolumioのプラグインを更新しました。 機能的には変更はありませんが、新しいバージョンのVolumioだとインストールが できないのが分かったので見直しをしました。
◆曲名を表示するプラグイン
https://www.dropbox.com/s/2zlv0r6gqaugadg/ssd1306I2c_20190224_1.zip?dl=0
◆サウンドメーターを表示するプラグイン
https://www.dropbox.com/s/pr14ej0sghph5fy/soundmeter_20190224_1.zip?dl=0
有機ELディスプレイを使ったVolumioのプラグインを更新しました。 機能的には変更はありませんが、新しいバージョンのVolumioだとインストールが できないのが分かったので見直しをしました。
◆曲名を表示するプラグイン
https://www.dropbox.com/s/2zlv0r6gqaugadg/ssd1306I2c_20190224_1.zip?dl=0
◆サウンドメーターを表示するプラグイン
https://www.dropbox.com/s/pr14ej0sghph5fy/soundmeter_20190224_1.zip?dl=0
IR Remote Controllerプラグインに別のコントローラを追加する [Volumio]
OPAです。
volumioで赤外線リモコン用のプラグインがあるのですが、アップルのリモコンとかしか対応していません。なので、秋月電子様で売っている赤外線リモコン(オプトサプライ赤外線リモコン)用の設定ファイルを作成して動かしてみました。
赤外線リモコン受信モジュールOSRB38C9AAを接続します。出力はGPIO26(PIN37)に接続しました。
プラグインをインストールします。IR Remote ControllerはAccessoriesにあります。
/boot/config.txtファイルに以下を追加します。
以下のディレクトリに「OE13KIR」ディレクトリを作成します。
/data/plugins/system_controller/ir_controller/configurations
OE13KIRディレクトリに2つのファイルを作成します。
lircd.conf
lircrc
このプラグイン、再起動するとデーモンが起動しないので、再起動してもデーモンが起動するように設定します。
sudo systemctl enable lirc
あとは、プラグインの設定画面で、OE13KIRを選択すれば使えるようになります。
volumioで赤外線リモコン用のプラグインがあるのですが、アップルのリモコンとかしか対応していません。なので、秋月電子様で売っている赤外線リモコン(オプトサプライ赤外線リモコン)用の設定ファイルを作成して動かしてみました。
赤外線リモコン受信モジュールOSRB38C9AAを接続します。出力はGPIO26(PIN37)に接続しました。
プラグインをインストールします。IR Remote ControllerはAccessoriesにあります。
/boot/config.txtファイルに以下を追加します。
dtoverlay=lirc-rpi,gpio_in_pin=26,gpio_in_pull=up
以下のディレクトリに「OE13KIR」ディレクトリを作成します。
/data/plugins/system_controller/ir_controller/configurations
OE13KIRディレクトリに2つのファイルを作成します。
lircd.conf
begin remote name /etc/lirc/lircd.conf bits 32 flags SPACE_ENC|CONST_LENGTH eps 30 aeps 100 header 9041 4462 one 595 1648 zero 595 533 ptrail 593 gap 107446 toggle_bit_mask 0x0 begin codes KEY_POWER 0x08F71BE4 KEY_A 0x08F71FE0 KEY_B 0x08F71EE1 KEY_C 0x08F71AE5 KEY_UPPER_LEFT 0x08F78D72 KEY_UPPER 0x08F705FA KEY_UPPER_RIGHT 0x08F7847B KEY_LEFT 0x08F708F7 KEY_CENTER 0x08F704FB KEY_RIGHT 0x08F701FE KEY_LOWER_LEFT 0x08F78877 KEY_LOWER 0x08F700FF KEY_LOWER_RIGHT 0x08F7817E end codes end remote
lircrc
begin prog = irexec button = KEY_POWER config = poweroff end begin prog = irexec button = KEY_CENTER config = /usr/local/bin/volumio toggle end begin prog = irexec button = KEY_UPPER config = /usr/local/bin/volumio volume plus end begin prog = irexec button = KEY_LOWER config = /usr/local/bin/volumio volume minus end begin prog = irexec button = KEY_LEFT config = /usr/local/bin/volumio previous end begin prog = irexec button = KEY_RIGHT config = /usr/local/bin/volumio next end begin prog = irexec button = KEY_A config = /usr/local/bin/volumio repeat end begin prog = irexec button = KEY_B config = /usr/local/bin/volumio random end
このプラグイン、再起動するとデーモンが起動しないので、再起動してもデーモンが起動するように設定します。
sudo systemctl enable lirc
あとは、プラグインの設定画面で、OE13KIRを選択すれば使えるようになります。
有機ELディスプレイ(OLED)を使ったサウンドメーターのvolumioプラグイン公開 [Volumio]
OPAです。秋月電子様の「0.96インチ 128×64ドット有機ELディスプレイ(OLED)」を使ってvolumioのサウンドメータープラグインを作ってみました。この有機ELディスプレイは、I2Cインタフェースで制御しますが、アドレスを2つ切り替えることができ、2つ同時に制御することができます。有機ELディスプレイの裏面にチップ部品がついていて、それを片方に付け替えることでアドレスを切り替えることができます。
以下の写真は、付け替えたものです。
作ったプラグインは、3つのモードが存在し、表示を切り替えられます。
I2Cインタフェースやらpythonやらで、厳密にタイミングよく表示されていないと思いますので、導入する人はあくまでもおもちゃとして使ってください。
このプラグインを導入するために、先に公開した曲名を表示するプラグインも修正していますので、両方使う人は、先のプラグインをアンインストールしてから再度、新しいプラグインを導入してください。
曲名を表示するプラグイン
https://www.dropbox.com/s/6we0921ryzkr34l/ssd1306I2c_20180623_1.zip?dl=0
※プラグインの設定画面で、起動時にランダムモードするかしないかのオプションを追加しました。
サウンドメータープラグイン
https://www.dropbox.com/s/mntiivl8nj6k2m9/soundmeter_20180623_1.zip?dl=0
※プラグインの設定画面で、表示モードを3つ選択できます。
/boot/config.txt ファイルに以下のエントリを追加すると表示が速くなります。
dtparam=i2c_arm_baudrate=400000
本プラグインは、Raspberry Pi2で動作を確認しています。ほかのボードでは試していないのでインストールできないかもしれませんのであしからず。自己責任でお願いします。
前の投稿で、圧縮されたファイルを展開してからvolumioに転送していましたが、miniunzipというコマンドが内蔵されていたため、圧縮したまま転送して、volumio上で展開することができました。
以下の写真は、付け替えたものです。
作ったプラグインは、3つのモードが存在し、表示を切り替えられます。
I2Cインタフェースやらpythonやらで、厳密にタイミングよく表示されていないと思いますので、導入する人はあくまでもおもちゃとして使ってください。
このプラグインを導入するために、先に公開した曲名を表示するプラグインも修正していますので、両方使う人は、先のプラグインをアンインストールしてから再度、新しいプラグインを導入してください。
曲名を表示するプラグイン
https://www.dropbox.com/s/6we0921ryzkr34l/ssd1306I2c_20180623_1.zip?dl=0
※プラグインの設定画面で、起動時にランダムモードするかしないかのオプションを追加しました。
サウンドメータープラグイン
https://www.dropbox.com/s/mntiivl8nj6k2m9/soundmeter_20180623_1.zip?dl=0
※プラグインの設定画面で、表示モードを3つ選択できます。
/boot/config.txt ファイルに以下のエントリを追加すると表示が速くなります。
dtparam=i2c_arm_baudrate=400000
本プラグインは、Raspberry Pi2で動作を確認しています。ほかのボードでは試していないのでインストールできないかもしれませんのであしからず。自己責任でお願いします。
前の投稿で、圧縮されたファイルを展開してからvolumioに転送していましたが、miniunzipというコマンドが内蔵されていたため、圧縮したまま転送して、volumio上で展開することができました。
秋月電子様の0.96インチ 128×64ドット有機ELディスプレイ(OLED)のvolumioプラグイン公開 [Volumio]
OPAです。
秋月電子様の0.96インチ 128×64ドット有機ELディスプレイ(OLED)を使った曲名等を表示するvolumioのプラグインを公開します。野良プラグインですので標準のインストール方法ではインストールできませんのであしからず。
以下、野良プラグインのインストール方法です。
http://volumio2.local/DEV/
にアクセスして、SSHをenableに設定します。
https://www.dropbox.com/s/kg1p6fcxdf3scn3/ssd1306I2c.zip?dl=0
※2018/4/30追記
T2さんの要望で、曲名が短い場合、スクロールしないようにしてみました。 また、サンプリングレートの表記の"KHz"を"kHz"にしました。ただし、volumio自身が"KHz"を 返却しているのでvolumioとの表記方法と異なります。
https://www.dropbox.com/s/stj9fxrjo7l6z9z/ssd1306I2c_20180430_1.zip?dl=0
圧縮ファイルを展開します。WinSCPを起動し、volumio2.localに接続します。
ユーザ名「volumio」、パスワード「volumio」です。
展開したフォルダをvolumio2.localに転送します。
volumioコマンドでプラグインをインストールします。
「インストール済みのプラグイン」タブを選択し、ssd1306_i2cプラグインをONにします。
自己責任でお願いします。以上です。
秋月電子様の0.96インチ 128×64ドット有機ELディスプレイ(OLED)を使った曲名等を表示するvolumioのプラグインを公開します。野良プラグインですので標準のインストール方法ではインストールできませんのであしからず。
以下、野良プラグインのインストール方法です。
SSHの設定
デフォルトでSSHが使えないので、Volumioの設定を変更します。ここでは、volumioのホスト名を、 volumio2.localにしています。http://volumio2.local/DEV/
にアクセスして、SSHをenableに設定します。
プラグインのダウンロード
以下から、「ssd1306I2c.zip」をダウンロードします。https://www.dropbox.com/s/kg1p6fcxdf3scn3/ssd1306I2c.zip?dl=0
※2018/4/30追記
T2さんの要望で、曲名が短い場合、スクロールしないようにしてみました。 また、サンプリングレートの表記の"KHz"を"kHz"にしました。ただし、volumio自身が"KHz"を 返却しているのでvolumioとの表記方法と異なります。
https://www.dropbox.com/s/stj9fxrjo7l6z9z/ssd1306I2c_20180430_1.zip?dl=0
圧縮ファイルを展開します。WinSCPを起動し、volumio2.localに接続します。
ユーザ名「volumio」、パスワード「volumio」です。
展開したフォルダをvolumio2.localに転送します。
プラグインのインストール
ターミナルソフト(TeraTermなど)を起動し、volumio2.localに接続します。volumioコマンドでプラグインをインストールします。
volumio@volumio2:~$ ls ssd1306I2c volumio@volumio2:~$ cd ssd1306I2c/ volumio@volumio2:~/ssd1306I2c$ volumio plugin install This command will install the plugin on your device Compressing the plugin Plugin succesfully compressed Progress: 10 Status :Downloading plugin Progress: 30 Status :Creating folder on disk Progress: 40 Status :Unpacking plugin Progress: 50 Status :Checking for duplicate plugin Progress: 60 Status :Copying Plugin into location Progress: 70 Status :Installing dependencies : : Status :Installing dependencies Progress: 90 Status :Adding plugin to registry Progress: 100 Status :Plugin Successfully Installed Done! volumio@volumio2:~/ssd1306I2c$
プラグインの起動
volumioにアクセスして、設定メニューからプラグインを選択します。「インストール済みのプラグイン」タブを選択し、ssd1306_i2cプラグインをONにします。
自己責任でお願いします。以上です。
Volumio2で音楽6 [Volumio]
有機ELディスプレイに曲名や歌手名を出すためにプログラムを書きましたが、時々表示されなくなってしまうことがありました。どうもpythonの変数の使い方が間違っていて、例外が出ていたようです。
ちょっと直してみました。
SSD1306へのアクセス部分と描画部分、通信部分を分離したので見通しが良くなったと思います。
#!/usr/bin/python # -*- coding: utf-8 -*- import os import sys import smbus import time import signal import threading from PIL import Image from PIL import ImageDraw from PIL import ImageFont from socketIO_client import SocketIO PIDFILE='/var/run/SSD1306.pid' class SSD1306(object): DISPLAYOFF = 0xAE DISPLAYON = 0xAF DISPLAYALLON = 0xA5 DISPLAYALLON_RESUME = 0xA4 NORMALDISPLAY = 0xA6 INVERTDISPLAY = 0xA7 SETREMAP = 0xA0 SETMULTIPLEX = 0xA8 SETCONTRAST = 0x81 CHARGEPUMP = 0x8D COLUMNADDR = 0x21 COMSCANDEC = 0xC8 COMSCANINC = 0xC0 EXTERNALVCC = 0x1 MEMORYMODE = 0x20 PAGEADDR = 0x22 SETCOMPINS = 0xDA SETDISPLAYCLOCKDIV = 0xD5 SETDISPLAYOFFSET = 0xD3 SETHIGHCOLUMN = 0x10 SETLOWCOLUMN = 0x00 SETPRECHARGE = 0xD9 SETSEGMENTREMAP = 0xA1 SETSTARTLINE = 0x40 SETVCOMDETECT = 0xDB SWITCHCAPVCC = 0x2 OLED_WIDTH = 128 OLED_HEIGHT = 64 OLED_PAGE_COUNT = 8 OLED_SIZE = ( OLED_WIDTH , OLED_HEIGHT ) OLED_CMDMODE = 0x00 OLED_DATAMODE = 0x40 def __init__(self,target=0x3C): self.OLED_TARGET = target self.buffer = [0] * SSD1306.OLED_PAGE_COUNT * SSD1306.OLED_WIDTH self.zero = [0] * 16 self.__bus = smbus.SMBus(1) def init(self): self.command( SSD1306.DISPLAYOFF, SSD1306.SETDISPLAYCLOCKDIV, 0x80, SSD1306.SETMULTIPLEX, 0x3F, SSD1306.SETDISPLAYOFFSET, 0x00, SSD1306.SETSTARTLINE, SSD1306.CHARGEPUMP, 0x14, SSD1306.MEMORYMODE, 0x00, SSD1306.SETSEGMENTREMAP, SSD1306.COMSCANDEC, SSD1306.SETCOMPINS, 0x12, SSD1306.SETPRECHARGE, 0xF1, SSD1306.SETVCOMDETECT, 0x40, SSD1306.DISPLAYALLON_RESUME, SSD1306.NORMALDISPLAY) self.contrast(0xCF) self.clear() self.show() def command(self,*cmd): self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_CMDMODE,list(cmd)) def contrast(self,level): self.command(SSD1306.SETCONTRAST,level) def clear(self): self.command(SSD1306.COLUMNADDR, 0x00, 128-1, SSD1306.PAGEADDR, 0x00, 8-1) for i in range(0, len(self.buffer), 16): self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_DATAMODE,self.zero) def show(self): self.command(SSD1306.DISPLAYON) def display(self,pix): index = 0 for page in range(8): for x in range(128): bits = 0 for bit in [0, 1, 2, 3, 4, 5, 6, 7]: bits = bits << 1 bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1 self.buffer[index] = bits index += 1 self.command(SSD1306.COLUMNADDR, 0x00, 128-1, SSD1306.PAGEADDR, 0x00, 8-1) for i in range(0, len(self.buffer), 16): self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_DATAMODE,self.buffer[i:i+16]) class SSD(SSD1306): def __init__(self): super(SSD,self).__init__() self.jpfont = ImageFont.truetype('/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf',12, index=0, encoding="unic") self.image = Image.new('1', (SSD1306.OLED_WIDTH, SSD1306.OLED_HEIGHT),0) self.draw = ImageDraw.Draw(self.image) def init(self): super(SSD,self).init() def set(self,album,title,artist,info): self.clean() self.display(album,title,artist,info) def clean(self): self.clear() self.draw.rectangle((0,0,SSD1306.OLED_WIDTH-1, SSD1306.OLED_HEIGHT-1), outline=0, fill=0) def max_length(self,text): length = len(text) for i in range(0,length-1,1): w = self.jpfont.getsize(text[0:i])[0] if w > 128: return i - 1 return length def display(self,album,title,artist,info): self.draw.text( (0,0), album , font=self.jpfont, fill=1 ) width = self.jpfont.getsize(title)[0] if width > 128 - 1: length = len(title) first_length = self.max_length(title) self.draw.text( (0,12), title[0:first_length], font=self.jpfont, fill=1 ) self.draw.text( (0,24), title[first_length:length-1], font=self.jpfont, fill=1 ) else: self.draw.text( (0,12), title, font=self.jpfont, fill=1 ) self.draw.text( (0,36), artist, font=self.jpfont, fill=1 ) self.draw.text( (0,50), info , font=self.jpfont, fill=1 ) super(SSD,self).display(self.image.load()) class socketio(object): def __init__(self): self.ssd = SSD() self.ssd.init() self.loopFlag = True self.album = '' self.title = '' self.artist= '' self.samplerate = '' self.bitdepth = '' def init(self): self.socketIO = SocketIO('localhost', 3000) self.socketIO.on('pushState', self.on_pushState) def on_pushState(self,args): s = '' b = '' i = '' if 'samplerate' in args : s = args['samplerate'] s = str(s) s.strip else: s = '' if 'bitdepth' in args: b = args['bitdepth'] b = str(b) b.strip else: b = '' if self.album == args['album'] and self.title == args['title'] and self.artist == args['artist'] and self.samplerate == s and self.bitdepth == b : return self.album = args['album'] self.title = args['title'] self.artist= args['artist'] self.samplerate = s self.bitdepth = b print(args['album'].encode('utf-8')) print(args['title'].encode('utf-8')) print(args['artist'].encode('utf-8')) if s =='' and b == '': i = 'NaN' else: i = '%s | %s' % (s,b) print(i) self.ssd.set( args['album'],args['title'],args['artist'], i ) def setRandom(self): self.socketIO.emit('setRandom',{'value' : 'true'}) self.socketIO.emit('getState') def loop(self): while True: if self.loopFlag == False: break self.socketIO.wait(seconds=1) def stop(self): self.loopFlag = False def daemonize(): pid = os.fork() if pid > 0: pidf = open(PIDFILE,'w') pidf.write(str(pid)+'\n') pidf.close() sys.exit() if pid == 0: def signal_handler(signal,handler): volumio.stop() os.remove(PIDFILE) sys.exit() signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) volumio = socketio() volumio.init() volumio.setRandom() volumio.loop() if __name__ == '__main__': daemonize()
SSD1306へのアクセス部分と描画部分、通信部分を分離したので見通しが良くなったと思います。
Volumio2で音楽5 [Volumio]
有機ELディスプレイに曲名や歌手名を出すためにプログラムを書きます。
以下のプログラムを書きます。
次に、起動時にデーモンとして動くように登録します。
以下の入力します。
コマンドを入力して有効にします。
再起動すれば、アルバム名、曲名、歌手名、サンプルレートが表示されます。
root@volumio:~# /var/tmp/mkinitramfs_8pJogT/bin/vi SSD1306.py
以下のプログラムを書きます。
#!/usr/bin/python # -*- coding: utf-8 -*- import os import sys import smbus import time import signal from PIL import Image from PIL import ImageDraw from PIL import ImageFont from socketIO_client import SocketIO PIDFILE='/var/run/SSD1306.pid' class SSD1306(object): DISPLAYOFF = 0xAE DISPLAYON = 0xAF DISPLAYALLON = 0xA5 DISPLAYALLON_RESUME = 0xA4 NORMALDISPLAY = 0xA6 INVERTDISPLAY = 0xA7 SETREMAP = 0xA0 SETMULTIPLEX = 0xA8 SETCONTRAST = 0x81 CHARGEPUMP = 0x8D COLUMNADDR = 0x21 COMSCANDEC = 0xC8 COMSCANINC = 0xC0 EXTERNALVCC = 0x1 MEMORYMODE = 0x20 PAGEADDR = 0x22 SETCOMPINS = 0xDA SETDISPLAYCLOCKDIV = 0xD5 SETDISPLAYOFFSET = 0xD3 SETHIGHCOLUMN = 0x10 SETLOWCOLUMN = 0x00 SETPRECHARGE = 0xD9 SETSEGMENTREMAP = 0xA1 SETSTARTLINE = 0x40 SETVCOMDETECT = 0xDB SWITCHCAPVCC = 0x2 OLED_WIDTH = 128 OLED_HEIGHT = 64 OLED_PAGE_COUNT = 8 OLED_SIZE = ( OLED_WIDTH , OLED_HEIGHT ) OLED_TARGET = 0x3C OLED_CMDMODE = 0x00 OLED_DATAMODE = 0x40 def command(self, *cmd): self.__bus.write_i2c_block_data(self.OLED_TARGET,self.OLED_CMDMODE,list(cmd)) def cleanup(self): self._hide() self.clear() self.__bus.close() def clear(self): self.display(Image.new("1",self.OLED_SIZE)) def show(self): self.command(self.DISPLAYON) def hide(self): self.command(self.DISPLAYOFF) def contrast(self,level): self.command(self.SETCONTRAST,level) def __init__(self): self.buffer = [0] * self.OLED_PAGE_COUNT * self.OLED_WIDTH; self.__bus = smbus.SMBus(1) def init(self): self.command( self.DISPLAYOFF, self.SETDISPLAYCLOCKDIV, 0x80, self.SETMULTIPLEX, 0x3F, self.SETDISPLAYOFFSET, 0x00, self.SETSTARTLINE, self.CHARGEPUMP, 0x14, self.MEMORYMODE, 0x00, self.SETSEGMENTREMAP, self.COMSCANDEC, self.SETCOMPINS, 0x12, self.SETPRECHARGE, 0xF1, self.SETVCOMDETECT, 0x40, self.DISPLAYALLON_RESUME, self.NORMALDISPLAY) self.contrast(0xCF) self.clear() self.show() def display(self,image): pix = image.load() index = 0 for page in range(8): for x in range(128): bits = 0 for bit in [0, 1, 2, 3, 4, 5, 6, 7]: bits = bits << 1 bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1 self.buffer[index] = bits index += 1 self.command(self.COLUMNADDR, 0x00, 128-1, self.PAGEADDR, 0x00, 8-1) for i in range(0, len(self.buffer), 16): self.__bus.write_i2c_block_data(self.OLED_TARGET,self.OLED_DATAMODE,self.buffer[i:i+16]) class socketio(object): def __init__(self): self.album = '' self.title = '' self.artist= '' self.samplerate = '' self.bitdepth = '' def init(self): self.socketIO = SocketIO('localhost', 3000) self.socketIO.on('pushState', self.on_pushState) self.ssd = SSD1306() self.ssd.init() def max_length(self,font,text): length = len(text) for i in range(0,length-1,1): w = font.getsize(text[0:i])[0] if w > 128: return i + 1 return length def on_pushState(self,args): s = '' b = '' if 'samplerate' in args : s = args['samplerate'] else: s = '' if 'bitdepth' in args: b = args['bitdepth'] else: b = '' if self.album == args['album'] and self.title == args['title'] and self.artist == args['artist'] and self.samplerate == s and self.bitdepth == b : return self.album = args['album'] self.title = args['title'] self.artist= args['artist'] self.samplerate = s self.bitdepth = b image = Image.new('1', (self.ssd.OLED_WIDTH, self.ssd.OLED_HEIGHT),0) draw = ImageDraw.Draw(image) draw.rectangle((0,0,self.ssd.OLED_WIDTH-1, self.ssd.OLED_HEIGHT-1), outline=0, fill=0) jpfont = ImageFont.truetype('/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf',12, encoding="unic") draw.text((0,0 ), self.album , font=jpfont, fill=1) e = 0 length = len(self.title) e = self.max_length(jpfont,self.title) if e < length: draw.text((0,12), self.title[0:e-2] , font=jpfont, fill=1) draw.text((0,24), self.title[e-2:length] , font=jpfont, fill=1) else: draw.text((0,12), self.title , font=jpfont, fill=1) draw.text((0,36), self.artist, font=jpfont, fill=1) if 'samplerate' in args and 'bitdepth' in args: f = '%s | %s' % (self.samplerate, self.bitdepth) #draw.text((0,50), str(self.samplerate) + '|' + str(self.bitdepth), font=jp draw.text((0,50), f, font=jpfont, fill=1) else: draw.text((0,50), '', font=jpfont, fill=1) self.ssd.display(image) print('-----') print(self.album.encode('utf-8')) print(self.title.encode('utf-8')) print(self.artist.encode('utf-8')) if 'samplerate' in args and 'bitdepth' in args: #print(str(self.samplerate) + "|" + str(self.bitdepth)) print(f) else: print('-NaN-') print('-----') def setRandom(self): self.socketIO.emit('setRandom',{'value' : 'true'}) self.socketIO.emit('getState') while True: self.socketIO.wait(seconds=1) def main_loop(): volumio = socketio() volumio.init() volumio.setRandom() os.remove(PIDFILE) sys.exit() def signal_handler(signal,handler): os.remove(PIDFILE) sys.exit() def daemonize(): pid=os.fork() if pid > 0: pidf = open(PIDFILE,'w') pidf.write(str(pid)+'\n') pidf.close() sys.exit() if pid == 0: signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) main_loop() if __name__ == '__main__': daemonize()
次に、起動時にデーモンとして動くように登録します。
root@volumio:~# /var/tmp/mkinitramfs_8pJogT/bin/vi /etc/systemd/system/ssd1306.service
以下の入力します。
[Unit] Description=Volumio2 SSD1306 display [Service] ExecStart=/root/SSD1306.py Restart=always Type=forking PIDFile=/var/run/SSD1306.pid [Install] WantedBy=multi-user.target
コマンドを入力して有効にします。
root@volumio:~# chmod +x SSD1306.py root@volumio:~# systemctl enable ssd1306.service
再起動すれば、アルバム名、曲名、歌手名、サンプルレートが表示されます。