続 Raspberry Piでカーオーディオ(IQaudIO PiDAC+)
去年のラズパイAdvent Calender 2017でやりきれなくて、しばらく放置してましたが、GWという謎の9連休で続きをやりました。
http://morinezumiiii.hatenablog.com/entry/2017/12/23/235319
そのおかげか、9連休という休みがどこかに消えてしまいました。
車+ラズパイでやりたいことが色々増えてしまって、あれからだいぶ変わりました。
以前の記事を踏まえて、やったことを書いていきます。
参考にさせて頂いた記事が多すぎて書ききれないかもしれませんので、ご容赦願います。
関連記事
Raspberry Piでカーオーディオ(IQaudIO PiDAC+) - もりねずみーのやつ
続々 Raspberry Piでカーオーディオ(IQaudIO PiDAC+) - もりねずみーのやつ
機能
オーディオ
- USBメモリなどに入っている楽曲を再生(FLACなど)
- Bluetoothオーディオレシーバー(自動接続)
- 音量自動調整(カロッツェリアの上位モデルに付いている機能) → ノウハウが無さ過ぎて無理でした。
- イコライザー調整 (alsa-equalですら10バンドいじれる)
ドライブレコーダー
- フロント・リア
- フロントカメラはRaspberry Pi公式のカメラモジュールを使用
- リアカメラはUSBカメラを使用
- 常時録画
- 液晶ディスプレイでカメラ映像を表示
環境情報センサ類
- 気温・湿度・気圧情報を表示
- バッテリー電圧とACC電圧を表示
材料
- Raspberry Pi 3 Model B
- Samsung microSDHCカード 64GB PRO Endurance MB-MJ32GA/EC(https://amzn.to/2I0eFKt)
- IqaudIO PiDAC+ (http://amzn.to/2AwjbNe)
- Elecrow 7インチディスプレイ (http://amzn.to/2AwTNqo)
- ELP フルHDウェブカメラUSB 180度魚眼レンズ広角webカメラ(http://amzn.to/2Av0r0m)
- Arduino Nano互換ボード (https://amzn.to/2rwaxXl)
- I2C接続気温湿度気圧センサBME280(https://amzn.to/2jKtwdB)
- I2Cロジックレベル変換ボード(https://amzn.to/2FW51m5)
- RTCモジュール(https://amzn.to/2Ip6yqm)
- Raspberry Pi カメラ HDMIケーブル 拡張セット(https://amzn.to/2I2DK7u)
- 8インチ液晶ディスプレイアンチグレア保護フィルム(https://amzn.to/2jMeGTz)
- 2CH 12Vスイッチング電源(https://amzn.to/2rAEJRx)
- シガーソケット(https://amzn.to/2I3o5EQ)
- Anker PowerDrive+ 2(https://amzn.to/2FW619P)
- USBハブ(https://amzn.to/2G105N6)
- アンプ: Rockford fosgate R150X2
- サブウーファー: Pioneer TS-WH500A (https://amzn.to/2FXrTBY)
- リサイクルショップで手に入れたクラリオンの2DINオーディオ(500円)
- 3mmアクリル板
ハードウェア組み立て
- リサイクルショップで手に入れた2DINオーディオをエレメント化して2DIN筐体を手に入れる。
- 2DIN筐体にラズパイとユニバーサル基板を取り付けるためのネジ穴を空ける。
- 2DIN筐体にケーブル類を通すための穴を空ける。
- 車の電源情報を得るため、簡単な12V→5V分圧回路を作ってArduinoで常時電源とACC電源の電圧を取得するモジュール(A)を作る。
- モジュール(A)にBME280を接続
- モジュール(A)にRTCを接続
- モジュール(A)のI2C線をラズパイのI2Cピンに接続
- …。
- 残りをよしなに組み立てる。
ソフトウェア準備(OSセットアップとか、とかとか)
- お手製ArchLinuxARMインストーラを使ってSDカードにArchLinux ARMを焼く。
https://github.com/morinezumiiii/ArchLinuxARM-installer-for-raspberrypi
- /boot/config.txtを編集
- デフォルトで存在するユーザー"alarm"でログイン
ssh alarm@192.168.xxx.xxx $ su → デフォルトパスワードは"root" # passwd → rootパスワードを変更 # useradd -m -g users -G wheel -s /bin/bash morinezumiiii # gpasswd -a morinezumiiii audio # gpasswd -a morinezumiiii lp # passwd morinezumiiii → ユーザーmorinezumiiiiを作成
- 必要なパッケージをダウンロード&インストール
alarm@ # pacman -Syu alarm@ # pacman -S sudo alarm@ $ visudo <-- viではなくnanoが開く。超嘘つき。 alarm@ $ exit
- ユーザーalarmを削除
ssh morinezumiiii@192.168.xxx.xxx morinezumiiii@raspberry $ sudo userdel -r alarm
ハードウェアクロックと時刻の設定
PiDAC+
- PiDAC+設定
alsamixerを見てみると、PiDAC+が認識されてる。しかもデフォルトで選択状態になっていて、そのままspeaker-test -c 2でRCA出力から音が出た。
ロータリーエンコーダーを使って音量調整したいので、 GitHubで公開されているIQaudIOのツールを落として動かしてみる。
この時、IQ_rotを動かそうとすると「wiringPiのライブラリがねーんだけど💢」って言われるので、wiringPiをインストールしておくこと。
$ sudo pacman -S python-wiringpi $ git clone
と、色んな合間にロータリーエンコーダーとPiDAC+をつなぐためのハーネスを作っておいてつなぐ。
sudo ./IQ_rot & alsamixer
何故かAnalogueチャンネルじゃなくDigitalチャンネルのボリュームが動く。(一応音量は調整はされる)
→ Analogueチャンネルは、-6db~0dbまでのプリアンプ的な役割っぽい。(アンプではないが)
alsa-equalプラグインを入れて10バンドイコライザー機能を追加
$ sudo pacman -S alsa-equal $
音が出ることを確認。
$ speaker-test -c 2
PiDAC+のロータリーエンコーダのプログラムのSystemdユニットを作成
$ sudo nano /etc/systemd/system/pidac-rotenc.service
[Unit] Description=IQaudIO PiDAC Rotary encoder application [Service] Type=simple Restart=always ExecStart=/usr/local/bin/IQ_rot [Install] WantedBy=multi-user.target
$ sudo systemctl daemon-reload $ sudo systemctl enable pulseaudio.service $ sudo systemctl enable pidac-rotenc.service
Pulse Audioの設定
サンプルレート、ビット深度の設定(アップサンプリング)
手元にある音楽ファイルが、最大でも24bit 96kHzのFLACファイルしか無いので、あまり恩恵は受けれないかもしれないけど、とりあえずPiDAC+に搭載されているPCM5211というDACは、32bit 384kHzまで再生出来るとのことなので、/etc/pulse/default.paを編集して、デフォルトサンプルレートとビット深度を設定する。
※PiDAC+公式のスペックを見ると、最大24bit 192kHzと載ってるんだけど、なんでPCM5211のデータシートと書いてあることが違うんだろう???
ラズパイをBluetoothレシーバー化
Arduinoでラズパイの電源管理
車のバッテリーからの電源は、大きく分けて2種類あり、バッテリーから常に供給される常時電源と、キーONとエンジン始動の間のアクセサリ電源(以降ACC電源)があります。アクセサリ電源は、名前の通り常時通電する必要がないもののための電源系統です。例えば、オーディオ類、シガーソケット電源、メーターパネルのバックライト、エアコンなどがあります。 ※最近の車はエンジンスタートボタンでスタータがセルを回して自動でエンジンがかかるので、エンジンON=ACC電源ONと言ってもしまっても良いかも?
で、Linuxが走るラズパイでは、アクセサリ電源でも問題無いのかというところですが、問題大アリでした。
Arduinoなどのマイコンボードでは、単一(或いは内包された複数)のプログラムが記憶領域に書き込まれ、電源が入るとそのプログラムが走り出し、電源を落とせば止まります。
Linuxも大雑把に言ってしまえば、前述と同じなのですが、Linuxは膨大な量のプログラムが動作し、様々なファイルの読み書きが発生しています。その状態で電源を落とせば、ファイル内容の破損が発生しますが、それを防ぐためにファイルシステムという機能が働いてくれます。
Windowsの場合、(Windows10ではあまり見かけなくなりましたが)予期しないシャットダウンを行うと、たまに青い画面でディスクのチェックが走り、しばらく待たされます。これが、ファイルシステムによる保護機能です。
それと同様に、Linuxにおけるファイルシステムも、(ファイルシステムに何を使っているか、どういう設定をしているかにもよりますが)予期せぬシャットダウンを行うと、次回電源ON時に、ファイルシステムによる保護機能が働き、しばらく待たされます。
待たされるだけで済むならいいのですが、場合によってはファイルシステムが復旧不可能に陥ったり、ファイルシステムそのものが破損してしまう可能性もゼロではありません。
今回の場合の「予期せぬシャットダウン」は、ACC電源OFFに相当します。
車のナビやオーディオ機器では、ACC電源OFFで電源ブチ切りしているように見えますが、実は設定情報(オーディオ設定や時刻設定など)の記憶などのために、常時電源にもつながっています。
ちなみに、最近のスズキの車で、エンジンOFF時にどういう動きをするか観察していたら、
- エンジンストップ
- メーターパネルが光ったまま
- LCDにエコ走行したかのパーセンテージが表示される
- ナビは電源切れたように見えるがバックライトは付いてるっぽい
- しばらくしてからACC電源がOFFになるっぽい。
で、前置きが長くなりましたが、Linuxが走るラズパイがACC電源系統のみからの供給だと色々と支障をきたしてしまうので、常時電源につなぐ必要がありますが、Raspberry Pi 3は最大2.5Aの電流が流れ、USBからの給電は5Vなので、最大12.5Wの電力を消費します。
バッテリーあがりも心配ですし、何よりラズパイが燃えてたらなんか嫌ですよね。
なので、Arduinoが常時電源とACC電源の状態を監視し、ACC電源電圧が指定した下限値を下回ったら、ラズパイにシャットダウンをさせて、指定した時間後にArduinoがRaspberry Piへの電源供給をリレーで切るようにします。(今回は2分にしました ※2分以内にACC電源ONしたらどうするのっていう課題は残りますが…。)
ラズパイに接続されたモジュールからI2Cで情報を取得する。
気温、湿度、気圧センサ(BME280)
i2cdetect -y 1でアドレスが割り当たっているか確認。
i2cデバイスのアドレスは0x68っぽい。
参考にした記事からサンプルソースコードを取得して動かしてみる。
- 参考にした記事
バッテリー電源(常時電源、ACC電源)電圧情報をArduinoからI2Cで取得する。
i2cdetect -y 1でアドレスが割り当たっているか確認。
i2cデバイスのアドレスは、Arduinoのプログラムで設定した0x08。
本当はもっと色々な情報をJSONでやりとりしたかったのだけど、I2Cの仕様上1回の通信で32バイトまでという制限があるので、最大32バイトのJSON文字列をラズパイに送るように設定。
ラズパイはArduinoに対して0x08のアドレスにread_i2c_block_data()を叩くと、Arduino側のOnRequest()イベントで要求が来たことを受け取り、指定のメソッドを叩いてWire.write()でラズパイへ電圧情報を送る。
- 参考にした記事
Linuxデスクトップ環境を設定する。
Linuxデスクトップ環境は、LXQtを選択しました。
- 参考にした記事
USBメモリのマウント状態監視する。
電源ONで自動でドライブレコーダー機能の録画を行うようにしたいのだけど、Raspberry PiのmicroSDには書き込みたくないので、別途USBメモリに書き込みを行いたい。
なので、/mnt/usbdiskディレクトリを作成して、/dev/sd*にデバイスが存在したら自動で/mnt/usbdiskへマウントするようにして、マウントされていれば録画(自動開始)、マウントされていなければ録画しないようにしたい。
USBカメラで動画を録画しつつWebSocketで動画をWebブラウザに表示する。
使うものはOpenCV3です。
ImageWriterで録画しつつ、フレーム毎の画像をRedisに一時格納し、WebブラウザにWebSocketで画像を送った旨のメッセージを送って、Webブラウザ側がそのメッセージを受信したらRedisに格納された最新の画像ファイルを読み込み表示更新し続けるという処理の流れになります。
- 参考にした記事
ラズパイ公式カメラで動画を録画しつつWebSocketで動画をWebブラウザに表示する。
USBカメラと違い、OpenCVから直接カメラデバイスからのイメージ取得が出来ないので、/opt/vc/bin/raspistillを経由して画像を取得(動画なら/opt/vc/bin/raspivid)する必要がある。ネイティブなのでこちらの方が速いかもなのですが、まずはPythonライブラリのを使って録画しつつフレーム毎の画像をRedisに格納するようにしてみます。以降の処理は、USBカメラの方でやったことと同じです。
- 参考にした記事
WebブラウザからBluetooth操作を出来るようにする。
bluezとbluez-utilsをインストールしていれば、bluetoothctlというコマンドが使用できるようになります。 bluetoothctl単体で実行すると対話式コマンド入力でのBluetooth設定が可能ですが、bluetoothctl power onのように引数を渡すことで対話式でなくても操作することが出来ます。
- 参考にした記事
これまでのまとめをWebアプリケーションとして動かす。
最初はWebアプリケーションとしてBottleで作っていましたが、参考にした記事がTornadoで書かれていたので、
問題点
- Bluetooth経由でスマートフォンから音楽を再生していると、たまにブツっというノイズが起きる。
- Bluetooth経由でスマートフォンから音楽を再生を開始すると、たまにブツっというノイズが起きる。
- このブチノイズはアンプを通したスピーカーにはかなり悪影響なのではというレベル。
- USBカメラを起動した際にラズパイの電源が落ちることがある。
- Arduino側でACC電源電圧を監視しているが、瞬間的に11.2Vぐらいまで電圧降下が起きる。
- 逆に車に搭載してエンジンを始動した場合、14V台まで上がる可能性があるので問題ないか要確認。
- Arduino側でACC電源電圧を監視しているが、瞬間的に11.2Vぐらいまで電圧降下が起きる。
- 何か改良したい時にわざわざ車から取り外す必要がある。
- → もう1セット作るしか無い?
まとめ
作っているとどんどん欲しい機能が増えてくるので、今回はとりあえずこれで試作として完成とします。
ただ、Bluetooth経由で音楽を再生した場合のブツっというノイズは、カーオーディオ的にはNGだと思うので、今後も改善を加えていきたい。
とりあえず、世界初の「マウスもキーボードも使えてLinuxが好き放題触れる格安な高音質カーオーディオヘッドユニット」の完成です。
→ Androidだったら既にあった。
課題
- Bluetoothのブチノイズをどうにかする。
- クソコードを改善する。
- Bottleとか軽量なWebフレームワークに置き換える。
終わりに
最近Android Thingsが正式リリースされたというニュースがありましたが、ラズパイはあくまでもDevelopment Platformという位置付けで、サポートされているデバイスもかなり少ないので、あまりリッチなことは出来無さそうです。一時期あったUbuntu PhoneのようにLinuxデスクトップが今後も発展していくことを期待します。