2019年3月3日日曜日

NOOBS+Raspberry PiにRaspbian+Node-REDを入れてDHT11で温度測定

NOOBSがSDカードにプリインストールされているRaspberry Piのキットが売られているようです。
これを使ってRaspbian、Node-REDをセットアップします。
さらにNode-RED上でDHT11の値を取得してクラウドにデータを送るところまでやってみます。

材料

Raspberry Pi 3B+ に NOOBS プリインストール SD カードがセットになっているスタータキット。
ハードウェア的には一通り揃っていますが、OS (Raspbian) が動くようにするまで一手間かかります。

激安の小型ブレッドボード。
6個も何に使うんだよ、という気もしますが。

DHT11 温湿度センサ。
A/Dコンバータが内蔵されているのでとりあえずセンサを扱いたい時におすすめ。
ただし、Node-REDを使う場合はライブラリを別途入れる必要があります。

発光ダイオードの5色セット。100個入り!
電光掲示板でも作るつもりかよ、と言いたくなる量ですが、少量で買っても別に安くならないのでまとめ買い推奨。
DHT11とは関係ないですがGPIOの動作確認用。

各種抵抗600本入り!
多いことは美しい。

NOOBSとは?

NOOBSをSDカードにファイルとして書き込んでおくことで、初回起動時にRaspbianのインストーラが起動します。
Raspbian以外のOSもインストールできるようですが、Raspbianであればネットワーク不要でインストールできます。
NOOBSのオリジナルファイルはここからダウンロードし、WindowsやMacであらかじめSDカードに書き込んでおきましょう。
(キットを購入した場合は書き込み済み。)

NOOBSからRaspbianをインストールする際は1時間くらい掛かるので要注意。

NOOBSでRaspbianをインストール

あらかじめSDカードに設定を書き込んでおくと、Raspbianのインストールをヘッドレス(モニタなし)でできます。
やり方はこのあたりのブログで詳しく説明されています。
Tom's Hobby「【ラズパイ】Raspberry Pi NOOBS Wifi設定、VNCインストールなど事前設定しておく【インストール】」

NOOBSからRaspbianをインストールする方法はこのあたりを参照。
このステップでかなり時間がかかります。
第56回「改めましてラズベリーパイの基本!(1) Raspberry Pi NOOBSインストール 2017年度版」

WiFi設定してSSHを有効化する

Raspbianセットアップが済んだSDカードにMacやWindowsから設定ファイルを書き込んでおくと、Raspberry Piにモニタをつながなくても続きの作業ができるようになります。

●Macで設定する場合
「Raspberry Pi Zero W をヘッドレスでWiFi対応セットアップする」

●Windowsで設定する場合
Macの場合と同様に次の2つのファイルを書き込めばOKです。

(1) {SDカードのドライブ名}¥boot¥wpa_supplicant.conf
通常は設定済みのRaspberry Piから/etc/wpa_supplicant/wpa_supplicant.confをコピーするのが簡単です。
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
        ssid="{SSIDを書く}"
        #psk="{WiFiパスワード}"
        psk=暗号化したWiFiパスワード
}
(2) {SDカードのドライブ名}¥boot¥ssh
このファイル名で空ファイルを置きます。

●セットアップ中のRaspberry Piにモニタを繋いで設定する場合
「Raspberry Pi3 に液晶モニタを付けて一体型 PC に」
SSHは「sudo raspi-config」コマンドから「5 Interfacing Options」でSSHを有効化すれば使えるようになります。

WindowsからSSH接続する

まず、Raspberry PiのIPアドレスを調べます。
Raspberry Piのターミナル上で次のコマンドを打てばIPアドレスがわかります。
$ ifconfig

WindowsでSSHを頻繁に使う場合はTeraTermをインストールします。
一時的にSSH接続したいだけの場合はDOSプロンプトでも大丈夫です。

Windows上で次のように進めるとWindowsからRaspberry PiにSSH接続できます。
(1) WindowsでDOSプロンプトを開く。(タスクトレイで「DOS」と検索すると出てきます。)
(2) 次のコマンドを実行。
ssh pi@{Raspberry PiのIPアドレス}
(3) 初回は何か質問されるのでYESを答える。 (4) piユーザのデフォルトパスワードは「raspberry」

パスワードを変更する

デフォルトパスワードのまま公衆WiFiなどに接続するとあっさり乗っ取られます。
(そもそもRaspberry Piで公衆WiFiにつなぐなよ、という気もしますが。。。) 次のコマンドでパスワードを変更。
$ passwd

Node-REDをセットアップする

ここまででようやくRaspberry Piをコマンドラインで操作できるようになりました。
Node-REDをセットアップして、ブラウザからRaspberry Piの動作を定義できるようにします。
最近はRaspbianに標準でインストールされていますが、バージョンが古いなど問題がある場合はアップデートした方が良いかもしれません。

Node-REDのセットアップについては過去記事、、、と言いたいところですが、以下のコマンドをSSHで実行するだけです。
$ bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/update-nodejs-and-nodered)

Node-REDでLチカ

Node-REDとGPIOの動作確認としてLチカさせます。
※Lチカ=LEDをチカチカさせること。ソフトウェアで言うところの「Hello World」みたいなもの。
世の中には詳しいブログがたくさんあるのでそっちを見てください。
oh-maker「Raspberry PiとNode-REDでLチカ」

Node-REDでDHT11をつかえるようにする

Node-REDでGPIOを使えることが分かったので、DHT11と繋ぎます。
DHT11から値を取得するには、SSH接続(もしくはローカルのターミナル)で少し準備が必要です。
設定方法はこのブログが分かりやすいです。
EPIPE「Raspberry Pi + Node-RED + DHT11 で温度・湿度取得」

ちなみに、GPIOのピン番号はRaspberry Piの公式サイトにドキュメントがあります。
GPIO - Raspberry Pi Documentation

Node-REDで取得した温度をクラウドに飛ばす

Node-RED のノードリストの「ソーシャル」にある email ノードを使うと簡単にメールを飛ばせます。
デフォルトで Gmail の SMTP サーバ(メール送信サーバ)が指定されているので、自分のGoogleアカウントの情報を設定するだけです。

もう少し頑張りたい場合は Twitter に飛ばすこともできますが、事前にTwitter API keyを取得しておく必要があります。
Qiita Twitter のAPIキーの取得方法が変わった

Node-REDからTwitterにダイレクトメッセージを飛ばす方法はここで解説されています。
Qiita「Node-RED で Twitter ダイレクト・メッセージ を送る場合の備忘録」

2019年1月16日水曜日

光を追いかける自動走行車:(2)A/D変換とは?

Raspberry Pi でアナログセンサの値を取得するために、前回掲載したA/Dコンバータを使います。

arduinoをよく使う人は、ここで「あれ?」と思うかもしれません。
と言うか、私は思いました。

Arduino UNOなどのアナログ入力ピンは、A/Dコンバータ(ADC)なしでアナログセンサを接続することができます。
実は、Arduino UNOなどに使われているマイコンチップ ATmega328P は、チップにADCが埋め込まれているので
アナログ入力ピンに繋ぐといきなりA/D変換後の値を取得できます。

ところで、ハードウェア屋さんにとってはA/D変換は常識ですが、IT屋さんは、
A/D変換というのを分かっているようで分かっていないことが多いです。
そもそも、「アナログ」と「デジタル」の違いも実は怪しい人が少なくありません。
と言うか、私は分かっていませんでした。

と言うわけで、今回はA/D変換について。
  1. 材料を揃える
  2. A/D変換とは?(今回)
  3. コンバータからSPI通信で値を取得する
  4. Raspberry PiのPWMで擬似アナログ出力する
  5. モータドライバでモータ制御する
  6. 光センサからの入力とモータ制御を連動させる

アナログ値とデジタル値とA/D変換

意外とよくあるのが「実数値=アナログ値」という勘違いです。
プログラム中で値を参照できている時点でそれは全て「デジタル値」です。

また、「アナログ入力から取得した値は連続値が取れる」という勘違いもよくあります。
アナログ値がA/D変換された時点で実数の離散値になります。

さらに厄介なのが「A/D変換後の値は工学値ではない」という罠。
当然ですが、デジタル値 20(0x14) は温度20度ではありません。

ざっくり絵で描くとこんな感じ。
(1) センサの役割
大抵のアナログセンサは環境変化によって抵抗値が変化します。
この変化の仕方はセンサの特性として決まっていて、非線形なことが多いようです。
例えば、明るさが2倍になっても抵抗が2倍や0.5倍になるわけではありません。
ここまでがアナログセンサのお仕事。

(2) A/Dコンバータの役割
次に、アナログセンサをA/Dコンバータに繋いでA/D変換します。
センサの抵抗値が変わると言うことは、その両端での電圧の値が変わります。
A/Dコンバータはそれを決められたビット数に量子化します。
例えば、最大5Vの8bit A/Dコンバータなら0〜5Vを256分割。(たぶん)
本当はもっと賢いことをやっているらしいのですがイメージとしてはそんな感じ。

(3) 工学値変換の役割
最終的に摂氏などの工学値が欲しい場合はデジタル値を工学値に戻します。
センサ特性が非線形なので工学値変換も非線形になります。
また、(2)の時点で離散値になっているので、変換した工学値も離散値です。

多くの場合、A/D変換後の値をソフトウェア的に変換してやる必要がありますが、この工学値変換曲線を作るのが結構難しいと思います。
モジュール化して売られているアナログセンサの中にはは、メーカーから配られているライブラリを使うと(1)〜(3)をまとめてやってくれるものもあるようです。(温湿度センサのDHT11など)

小学生に説明してみた

A/D変換について小学四年生に説明してみました。
どこまで伝わったかは謎。



A/D変換の話が長くなってしまったので、A/Dコンバータの使い方はまた次回。
次回はSPI通信を使ってA/Dコンバータから値を取得します。

2019年1月10日木曜日

光を追いかける自動走行車:(1)準備

毎週、小学4年生(息子)にプログラミング教室を開いて9ヶ月。
ようやくそれらしいものが動きました。

光センサで周囲の明るさを調べて、明るい方に向かって走っていく自動走行車。
講義内容の振り返りを兼ねて少しずつ書いていきます。

作成の流れ

  1. 材料を揃える(今回)
  2. A/D変換とは?
  3. コンバータからSPI通信で値を取得する
  4. Raspberry PiのPWMで擬似アナログ出力する
  5. モータドライバでモータ制御する
  6. 光センサからの入力とモータ制御を連動させる

材料

Raspberry Piで学ぶ電子工作

教科書。
この本ではスマホから操作するラジコンの作り方が紹介されています。
その途中でA/D変換やモータ制御の話が出てくるので、分からなくなったらこれを参照しながら作りました。

Raspberry Pi 3 B+

Raspberry Pi2や3Bでも構いません。
Raspberry Pi Zero/Zero W はシングルコアなのでダメです。
Raspberry Pi Zero W でも動作しますが、VNCでデスクトップを表示しながらカメラを動かそうとするとかなり重くなってしまいます。

フォトレジスタ×2個

フォトレジスタというのは光センサのことです。
電子工作のスターターキットなどにもよく入っています。
車の左右の明るさを計測するので2個使います。

A/Dコンバータ:MCP3008

今回は8チャンネル10bitのA/Dコンバータを使いました。
amazonで探すと何故か1万円越えの異常な値付けになっていることがあるので要注意。
実際には2チャンネルあれば十分なので、手に入るもので構わないと思います。
見つからない場合は秋月電子で。

HiLetgo L9110S モータードライバ

ものすごく雑なつくりですが、激安のモータードライバ。
このドライバ1個でモーターを2チャンネル制御できるので、全体を小型化できます。

ダブルギヤボックス

左右独立で動くタミヤのギヤボックス。
モーターも同梱されているので、これ1つで色々遊べます。

キャタピラ

タミヤのキャタピラセット。
キャタピラの長さやホイールの配置を柔軟に変えられて便利。

ユニバーサルプレートセット

シャシーの代わり。
別にこれでなくてもかまぼこの板でもなんでも構いません。

その他、電池ボックス、モバイルバッテリー、ジャンパワイヤ多数。



今回はここまで。
気が向いたら続きを書きます。

2018年11月10日土曜日

Raspberry Piでジュークボックス(番外):現状

先日準備編だけ書いたままだったジュークボックスのその後。
リビングの家電を一通り音声操作できるようにしてリモコンを撲滅したところ、家族から次々とリクエストが出てきて意見箱が設置されることに。
意見箱の投書を粛々と実装するうち、何なのかよく分からないデバイスに進化してきました。
そもそも「デバイス」と言っても、家中に散らばったデバイスが連動して動いているので、どれが本体なのか誰も気にしていません。と言うか「本体」など存在しない状態に。

主な構成

  1. 音声入力
    ダイニングに置いてあるAmazonEcho。
  2. 音声出力
    メインはリビングのスピーカー(サウンドバー)
    AmazonEcho自体の機能に関する音声フィードバックはAmazonEchoから出るので、あちこちで違う声で喋りまくり。
  3. 制御系
    AmazonEchoとRaspberry Pi2台とArduinoとアンプが連動しているのでどれがどうとも。。。
    音声入力系については、基本的にはこの流れ。
    AmazonEcho → Node-RED(Raspberry Pi) → 赤外線(Raspberry Pi) → アンプ切り替え&各機器制御
    そのほか、時間での自動起動系はRaspberry Piとアンプが赤外線で連携。

主な実装済み機能

  1. テレビ/プロジェクター/ルンバの音声操作
  2. 携帯やPCからリビングのスピーカーで音楽再生
  3. 操作対象に合わせてアンプの音声入出力を自動切り替え
  4. 朝夕と夜に時報を喋る。
  5. 早朝にYoutubeからそれっぽいPlaylistを検索して自動再生。
  6. 誰かの誕生日には勝手に祝う。
  7. 学校に行く時間になったら音声で急かす。
  8. 週末も学校と同じ時間に学校と同じチャイムが鳴る。
  9. 時報などの音声案内は音声合成の話者をランダムに入れ替えて再生。

未実装の機能というか要望

  1. 音声合成の話者入れ替えに関して、OpenJTalkのおっさんの声が偶然私の声に似ていたらしく、娘から「もっとやれ」との指示。
  2. Logicoolのカメラをハードオフのジャンク箱から100円でゲットしたので画像入力を使いたい。
  3. 家電からのフィードバックパスが無く、細かい使い勝手に制限が出る。
    (家電用リモコンで電源を切ると音声入出力の組み合わせが連動しないとか)
  4. AmazonEchoからキーワード入力できないので、ジュークボックスにキーワード検索させようとすると携帯操作になる。
  5. 制御系を全部隠してあるのに、AmazonEchoが存在感を出しすぎ。どこかに隠したい。
  6. 音声入力を分散配置したいが質の良いマイクを自前で用意するのが厳しい。
  7. 対象機器にアナログ掛け時計を入れたい。Raspberry Piを組み込んでデジタル鳩時計にしたい。

2018年9月30日日曜日

Raspberry Piでネットワークルーティング

またしても需要がなさそうですが、Raspberry Piで2つのプライベートネットワーク間をルーティングします。

ググるとRaspberry PiをDHCP & default gateway にする方法はたくさん出てくるのですが、
DHCP と default gateway は普通の WiFi ルータに任せて、プライベートセグメントだけルーティングする、という面倒なことをやろうとしたら情報がなかったので。

やりたいこと

図のように、WiFiルータが2つあって、それぞれ LAN1(192.168.1.0/24) と LAN2(192.168.2.0/24) のネットワークを作っています。
LAN1 には NAS がぶら下がっていて、普段作業する Mac なども繋がっています。
一方、LAN2 には子供が使う Windows マシンが繋がっています。
このままでもそれぞれの WiFi ルータからネット接続できるのですが、
LAN2 側から NAS を使いたかったので Raspberry Pi でゲートウェイすることにしました。
ただし、DHCPはそれぞれのWiFiルータなので default gateway はWiFiルータです。

普通はWiFiルータ2をWiFiコンバータにすれば済む話なのですが、
たまたまWiFiルータが1台余っていたので。

しかも、自宅の壁面にマルチメディアコンセントが埋め込まれているのですが、
そこにLANケーブルを挿すとグローバルネットワークになってしまうのでこんなことに。
本当は天井裏のハブをルータに置き換えて、壁面配線をプライベートネットワークにしたいのですがそれはまた別の話。

Raspberry Piでルーティングする

Raspberry Piを有線と無線の両方につないだとしても、そのままではルーティングしてくれません。
IP forwardを許可して iptables を設定すればOKです。

まず、/etc/sysctl.conf に「#net.ipv4.ip_forward=1」という行があるのでコメントを外します。
その後、/proc/sys/net/ipv4/ip_forwardに「1」を書き込んで reboot。
root@raspberrypi:~ # echo -n 1 > /proc/sys/net/ipv4/ip_forward
root@raspberrypi:~ # reboot
さらに、ルーティングされるようにiptables に設定を追加。
素通しするだけだから「nat」とか要らないかなぁ、という気もしますが、細かい設定はよく分かりません。
誰かちゃんとした設定を教えて、エロい人。
root@raspberrypi:~ # iptables -F
root@raspberrypi:~ # iptables -X
root@raspberrypi:~ # iptables -t nat -F
root@raspberrypi:~ # iptables -t nat -X
root@raspberrypi:~ # iptables -t mangle -F
root@raspberrypi:~ # iptables -t mangle -X
root@raspberrypi:~ # iptables -P INPUT ACCEPT
root@raspberrypi:~ # iptables -P FORWARD ACCEPT
root@raspberrypi:~ # iptables -P OUTPUT ACCEPT
root@raspberrypi:~ # iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
root@raspberrypi:~ # iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
「iptables -L」でこんな感じの出力になれば成功です。
root@raspberrypi:~ # iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  
この状態で Raspberry Pi はルーティングしてくれるはずですが、
Windows マシンから 192.168.1.x のアドレスに ping を打っても返ってきません。
それは Raspberry Pi とは別の理由なので後で対応します。

iptables が起動時に設定されるようにする

Raspbian は標準で iptables が入っていますが、起動時に設定を反映してくれないようです。
「iptables-persistent」というパッケージを入れれば良い模様。

インストールは単に「sudo apt-get install iptables-persistent」でOK。
インストール時に現在のiptablesを保存するか聞かれるので「YES」。
その後、再起動すれば iptables が再設定されます。

Windowsから別セグメントのファイルサーバにアクセスできるようにする

これでルーティングされているはずなのですが Windows から NAS に ping が通りません。
なぜなら、Windows の default gateway が WiFi router2 になっているから。
WiFi router2 は NAS のアドレスを知らないため、インターネット側にルーティングしてしまいます。

もし、WiFi router2 の設定で、192.168.1.0/24 を Raspberry Pi にルーティングできるなら設定します。
普通の家庭用 WiFi ルータではそんな細かい設定ができないことが多いので、今回は Windows 側で頑張ります。

とは言え、Windows でも通常のコントロールパネルからは設定できません。
管理者権限でDOSプロンプトを開いて次のコマンドを実行。
# route -p add 192.168.1.0/24 192.168.2.10
「192.168.2.10」は Raspberry Piの LAN2 側アドレスです。
「-p」オプションは persistent のことで、このオプションを付けると再起動後にも反映されます。
もしいきなり試すのが怖ければ「-p」無しで実行すれば再起動で元に戻ります。

ここまで設定できたら Windows から ping を打ってみます。
# ping 192.168.2.10
PING 192.168.2.10 (192.168.2.10): 56 data bytes
64 bytes from 192.168.2.10: icmp_seq=0 ttl=64 time=2.546 ms
  :
# ping 192.168.1.10
PING 192.168.1.10 (192.168.1.10): 56 data bytes
64 bytes from 192.168.1.10: icmp_seq=0 ttl=64 time=2.546 ms
  :
# ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
・・・あれ?
Raspberry Pi の LAN1 側アドレスからは応答があるので、ルーティングはできています。
ところが、LAN1に繋がっているNASから応答がありません。

これは、NAS までは ping が通っています。
NAS から戻ってくるときに、NAS 側の default gateway が WiFi router1 になっているからです。
またかよ。

基本的に NAS からインターネットアクセスすることはないと思いますので、
NAS の default gateway を Raspberry Pi (192.168.1.10) にすれば大丈夫です。
もちろん、192.168.2.0/24 だけを振っても良いですが、家庭用NASではそんな設定はできないと思います。

Windowsのhostsファイルを編集する

これで、 LAN2 側の Windows から LAN1 側の NAS につながるようになりました。
ただし、このままだと名前解決できないので常に IP アドレスで繋ぐことになります。

Raspberry Pi で DNS を動かしても良いですが面倒なので Windows の hosts ファイルに直接書き込んでしまいます。
メモ帳を管理者権限で開いて hosts ファイルの末尾に設定を追加します。
Windows10 の hosts ファイルは「C:\Windows\System32\drivers\etc\hosts」です。
# cat C:\Windows\System32\drivers\etc\hosts
   :
192.168.1.10  NAS
これでホスト名でファイルサーバにアクセスできるようになりました。

おわり。

2018年8月19日日曜日

Raspberry Piでジュークボックス:(1)準備

iPhoneでYoutubeから曲を選ぶと、Raspberry Pi経由で室内のスピーカーから流れるようにしました。

何をしたいのか

私よりも自宅にいることの多い顧客(家族)からのリクエストだったものの、
本人もどうなっていれば良いのか分からなかったようで試行錯誤しながらのヒアリングになりました。
結局のところ次のことを言っていたようです。
  • スピーカーでリビングに音楽を流して欲しい。
  • 楽曲指定は基本的にキーワード指定。お気に入りとかプレイリストとか要らない。
  • 簡単に再生開始したい。音声操作でもスマホでもどちらでも良いがハードウェアボタンを押しに行くのは嫌だ。
  • 再生中にスマホで他の操作をしたいので占有されたくない。
  • 1曲終わったら関連楽曲を連続再生して欲しい。
  • 途中、気に入らない楽曲が再生されたらスキップ or 他の関連曲に変えたい。
  • レスポンスが良いに越したことはないが、再生開始に時間がかかっても許容可能。(どうせ再生しっぱなしだから)
  • 再生時に余計な家電が動いてしまうのはNG。
  • コンテンツに定額が発生しても構わないが、気に入った曲が無いならダメ。

できるようになったこと


iPhoneでSiriに「Youtubeで◯◯を検索」と頼んで、検索結果からworkflowに共有するとRaspberry PiのNode-REDにリクエストが飛ぶようにしてあります。
最初からWorkflowにキーワードを入力してもOK。

Node-REDはリクエストされたYoutubeコンテンツIDまたはキーワードをShellScriptに渡します。
ShellScriptでは内部でmps-youtube(mpsyt)を呼び出して、Youtubeの楽曲を検索して再生。

その際、Raspberry Pi Zero Wを使うと再生開始まで非常に時間がかかる(1分くらい)ので、
Open JTalkで音声案内を入れるようにしました。

ここまでできてしまうと、mpsytの関連検索コマンドなどを駆使すれば連続再生なども簡単にできます。
処理が重すぎて、再生中のコマンドはうまく受け付けてくれないことがあるので、
停止やスキップについてはShellScriptから強制終了させるなどの対応にしました。

ついでにAmazon Echoに「ジュークボックスを消して」と言うとNodeREDから停止するようにしてあります。

試したこと

今回の構成に至るまでの試行錯誤の経緯。。。

Amazon Echo Dot + Amazon Music Unlimited

・選曲操作:Amazon Echo Dot
・音楽配信:Amazon Music
・再生端末:Amazon Echo Dot
・音声出力:Amazon Echo Dot

声を掛けるだけで再生されるしレスポンスも良く、再生デバイスとしてはGood。
ところが「Amazon Music Unlimitedが対応している曲がイマイチ」ということでお客様としてはNG。

Google Homeも買おうとしましたが、顧客から「なんでやねん」というツッコミが入って断念しました。

iPad + Youtube + AirPlay + Amazon Fire TV Stick

・選曲操作:iPad + Youtubeアプリ
・音楽配信:Youtube
・再生端末:iPad + AirPlay
・音声出力:Amazon Fire TV Stick

それで良いのか?と言いたくなりますが、Amazon MusicのコンテンツがイマイチならYoutubeで。。。
ちなみに、Apple Music は宗教的理由により見送りました。
死んだ爺さんから「月額課金はAmazon大明神の思し召しのままに」と言われているので。

Amazon Fire TV Stick にAirPlayのアプリを入れてiPadからYoutubeの音声を飛ばしました。
コンテンツ的にはOKらしいのですが、Fire TVにAirPlayを繋いだ瞬間にHDMI経由で画面(プロジェクター)が起き上がってしまいNG。
いや、だって、映像再生デバイスなんだから仕方ないじゃん。。。

また、iPadだとYoutubeが関連楽曲を連続再生してくれずご不満とのこと。
ふーん。

iPhone + Youtube + AirPlay + Raspberry Pi + スピーカー

・選曲操作:iPhone + Youtubeアプリ
・音楽配信:Youtube
・再生端末:iPhone + AirPlay
・音声出力:Raspberry Pi + スピーカー

Fire TVが画面出力してしまうならRaspberry Piでヘッドレスにしてみよう、ということで。
具体的な方法は以前説明した通り。
iPhoneであればYoutubeの連続再生も可能です。

しばらく良い感じに使っていたのですが、iPhoneで他の操作をしようとしてYoutubeアプリをバックグラウンドにすると音が切れてしまい、微妙なイライラが残ります。
ブラウザを駆使するとバックグラウンドで再生できるようですが、毎回この操作をするのは耐えられないとのことでNG。

iPhone + workflowアプリ + Raspberry Pi + Node-RED + Youtube + mpsyt + OpenJTalk + スピーカー

・選曲操作:iPhone + workflowアプリ(キーワード指定のみ)
・音楽配信:Youtube
・再生端末:Raspberry Pi + mpsyt
・音声出力:Raspberry Pi + スピーカー

最終的にたどり着いた構成がこれ。
結局、楽曲検索から再生から何から全部をRaspberry Piに詰め込んでしまい
「それミュージックプレイヤーやないかい」という状態。


前置きが長くなったので続きは次回。

2018年8月16日木曜日

Raspberry Pi に日本語を喋らせる

Alexa でルンバに掃除させる際の試行錯誤で、色々な家電を音声コマンドで動かせるようになりました。

便利にはなったものの、Alexa Home Skill は返事が毎回「はい」なので無愛想に感じてしまいます。
そこで、Raspberry Piで家電を操作する際にもう少し丁寧に喋ってもらうようにしました。

Raspberry Piから音声出力できるようにする

Raspberry Piにはスピーカーがありません。
そのため、何らかの方法で音声出力できるようにする必要があります。

今回は家電が近くにあるのでHDMI出力を使いました。
HDMIから音声出力する方法は前回の「Raspberry PiをAirPlayレシーバにする」をご参照ください。

特にHDMIにこだわらない場合は、USBスピーカーを使うのが音質が良く、動作も確実なようです。
音声設定についてはこのサイトが詳しいです。
ちなみに、今回のように音声合成の結果をHDMI出力すると次の問題があってちょっと面倒です。
  • 音声をデジタル変換する処理が追いつかず、合成音の最初の2〜3文字分の音が出ない。
  • 家電操作の対象が出力先の音声デバイスとバッティングすると厄介なことになる。
前者については、合成音の冒頭に「はい」「えーと」など無意味なセリフを入れて回避するしかなさそうです。
後者は、対象デバイスのHDMI入力を一旦Raspberry Piに切り替えてから合成音を再生し、その後で家電操作する、という流れになります。

単に「切り替えてから」と書きましたが、大抵のデバイスは音声再生程度で自動切り替えしない仕様なので、
自分で赤外線リモコンコードをコピーして操作することになると思います。
方法はルンバの掃除の際に書いたものが使えると思います。

Open JTalkをインストールする

次のようにOpen JTalkをインストールします。
$ sudo apt-get install open-jtalk
$ sudo apt-get install open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
hts-voice-nitech-jp-atr503-m001 はおっさんの声の辞書です。
音声合成と言えば女性の声だろう、ということで女性の声の辞書を入れます。
$ wget http://downloads.sourceforge.net/project/mmdagent/MMDAgent_Example/MMDAgent_Example-1.7/MMDAgent_Example-1.7.zip
$ MMDAgent_Example-1.7.zip
$ sudo cp -r ./MMDAgent_Example-1.7/Voice/mei /usr/share/hts-voice/

Open JTalkに喋ってもらう

コマンド引数にテキストと音声辞書を指定すると合成してくれるのですが、
次のようなスクリプトを作っておくと便利です。
#!/bin/sh

msg="$1"

voice_type=/usr/share/hts-voice/mei/mei_normal.htsvoice

echo "$msg" |
open_jtalk  -m $voice_type -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow /dev/stdout |
aplay -
こんな感じで、このスクリプトの引数に日本語を渡せば再生してくれます。
$ ./voice.sh "抵抗は無意味だ"

使ってみる

open_jtalk には合成時のオプションを色々と指定できるのですが、
あまりいじっても音質が劣化して残念なことに。
よほど意味が分かっていない限りは、デフォルトのまま使うのがおすすめです。

crontab に次のようにスクリプトを仕込んでおくと、毎日7時〜22時に鳴る時報になります。
(タイムゾーンがUTCの場合は9時間引くなりなんなり)
$ crontab -e
0 7-22 * * * /home/pi/bin/tone.sh
呼び出されるスクリプトはこんな感じで適当に。
#!/bin/sh

DIR=`/usr/bin/dirname $0`

y=`/bin/date +%Y`
m=`/bin/date +%-m`
d=`/bin/date +%-d`
h=`/bin/date +%-h`

msg="$y年 $m月 $d日 h時です。"

$DIR/voice.sh "$msg"

Alexaと連携する

Alexa Home Skill と Raspberry Pi の連携については以前の説明をご参照ください。
NodeREDで家電の起動コマンドを送る前に音声合成のShell Execを挟み込めばOKです。

例えば、こんな感じです。
これでプロジェクターの起動待ちの間に「しばらくお待ちください」などのセリフを挟み込めます。