mattintosh note

Hello Raspberry Pi!

dwm の st のフォントを変更する

Raspberry PiX Window System を使うときはだいたい dwm なんだけどなんか OS を再インストールする度にフォントが変わっている気がするので直に指定することにした。

と、言っても dwm から st を呼び出すときは Alt + Shift + Enter で、このカスタマイズが多分 config.h を変更することになりそうなので st の実行ファイル自体を細工する。

まず st の実行ファイルをリネームする。

$ sudo mv /usr/bin/st /usr/bin/st.bin

新しく /usr/bin/st を作る。

#!/bin/sh
exec /usr/bin/st.bin -f "Sazanami Gothic:size=10" "$@"

あとは実行権限を付与する。

$ sudo chmod +x /usr/bin/st

Raspbian とか Ubuntu で簡単に root になる

いままで「Ubuntu は初期状態ではパスワードが設定されてないから root には慣れないよ!」みたいなものを何度も見てきたので自分もそう思っていた。

Raspbian で GPIO にアクセスしたいから root になりたいと思ってなんとなくやってみたら簡単にできた。

pi@raspberrypi:~ $ sudo su -

SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.

root@raspberrypi:~# id
uid=0(root) gid=0(root) groups=0(root)
root@raspberrypi:~# 

Ubuntu でも同様。普通に root でログイン出来るようにしておいたトラブルが起きた時には助かるんだけどね。

Raspbian + DHCP で DNS サーバの固定

Raspberry Pi Zero で /etc/network/interfaces に以下のように設定した。

iface wlan0 inet manual
    dns-nameservers 8.8.8.8
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

/etc/resolv.conf は以下のようになった。

# Generated by resolvconf
nameserver 192.168.1.1
nameserver 8.8.8.8

違う!違うよ!!!

Raspbian だと /etc/dhcpcd.conf の設定が優先されるらしい。

man dhcpcd.conf には以下のように書いてあった。

Here is an example which configures a static address, routes and dns.
    interface eth0
    static ip_address=192.168.0.10/24
    static routers=192.168.0.1
    static domain_name_servers=192.168.0.1

static domain_name_servers= で固定できそうだ。しかし、servers と言うからには複数設定できると思われるのだが、デリミタが何なのかが書いてない。man -K domain_name_servers で全マニュアルを検索してみたがやっぱり書いてない。

とりあえず当てずっぽうで space にして /etc/dhcpcd.conf に書いてみた。。

interface wlan0
static domain_name_servers=8.8.8.8 8.8.4.4

期待通りになった。

# Generated by resolvconf
nameserver 8.8.8.8
nameserver 8.8.4.4

NetworkConfiguration - Debian Wiki に似た書式で書いてあったけど微妙に違う。

Linux はほんとこの辺統一してほしい…。

Raspberry Pi の GPIO の意外な?真実

Raspberry Pi の GPIO についてちょっと気になったことがあったので色々試してみた。

Raspberry Pi の GPIO2 と GPIO3 は物理的にプルアップされているそうだ。これは実物を見れば抵抗につながっているのが確認できる。その他のピンは「プルアップされている」とか「プルダウンされている」とか、よくわからない。

とりあえずうちにある Raspberry Pi 3 のうちの Element14 番で試してみる。

まず最初に /sys/class/gpio の初期状態。

$ ls -l /sys/class/gpio
total 0
--w------- 1 root root 4096 Jan  7 00:01 export
lrwxrwxrwx 1 root root    0 Dec 10 10:11 gpiochip0 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpiochip0
lrwxrwxrwx 1 root root    0 Dec 10 10:11 gpiochip100 -> ../../devices/platform/soc/soc:virtgpio/gpio/gpiochip100
--w------- 1 root root 4096 Jan  7 00:01 unexport

一気に書き込むとエラーになるので sleep 2 を入れつつ徐々に有効にする。

$ for f in {4..27}; do echo $f >/sys/class/gpio/export; sleep 2; done

GPIO4 から GPIO27 までが使えるようになった。

$ ls -l /sys/class/gpio
total 0
--w------- 1 root root 4096 Jan  7 00:04 export
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio10 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio10
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio11 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio11
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio12 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio12
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio13 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio13
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio14 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio14
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio15 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio15
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio16 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio16
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio17 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio17
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio18 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio18
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio19 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio19
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio20 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio20
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio21 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio21
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio22 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio22
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio23 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio23
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio24 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio24
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio25 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio25
lrwxrwxrwx 1 root root    0 Jan  7 00:05 gpio26 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio26
lrwxrwxrwx 1 root root    0 Jan  7 00:05 gpio27 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio27
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio4 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio4
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio5 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio5
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio6 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio6
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio7 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio7
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio8 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio8
lrwxrwxrwx 1 root root    0 Jan  7 00:04 gpio9 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio9
lrwxrwxrwx 1 root root    0 Dec 10 10:11 gpiochip0 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpiochip0
lrwxrwxrwx 1 root root    0 Dec 10 10:11 gpiochip100 -> ../../devices/platform/soc/soc:virtgpio/gpio/gpiochip100
--w------- 1 root root 4096 Jan  7 00:01 unexport

この状態で各ピンのモードと値を取ってみたところ、モードはすべて in。値は一部のピンはプルダウンされていないのか、1 になっていた。ちなみに /sys/class/gpio/unexport してやり直しても directionvalue の値は同じだった。このことを考えると入力として使うのに向いたピンとそうでないピンがあるのだろうか。

$ for f in {4..27}; do printf '%2s %3s %s\n' $f `cat /sys/class/gpio/gpio$f/{direction,value}`; done
 4  in 1
 5  in 1
 6  in 1
 7  in 1
 8  in 1
 9  in 0
10  in 0
11  in 0
12  in 0
13  in 0
14  in 0
15  in 1
16  in 0
17  in 0
18  in 0
19  in 0
20  in 0
21  in 0
22  in 0
23  in 0
24  in 0
25  in 0
26  in 0
27  in 0

今度はすべてのピンを out にしてみる。値はすべて 0 になった。

$ for f in {4..27}; do echo out >/sys/class/gpio/gpio$f/direction; sleep .5; done
$ for f in {4..27}; do printf '%2s %3s %s\n' $f `cat /sys/class/gpio/gpio$f/{direction,value}`; done
 4 out 0
 5 out 0
 6 out 0
 7 out 0
 8 out 0
 9 out 0
10 out 0
11 out 0
12 out 0
13 out 0
14 out 0
15 out 0
16 out 0
17 out 0
18 out 0
19 out 0
20 out 0
21 out 0
22 out 0
23 out 0
24 out 0
25 out 0
26 out 0
27 out 0

direction の設定は inout だと思っていたのだが、ネットを徘徊していたときにちらっと high というワードを見かけたので一旦 in に戻した後、high にしてみたら驚いた。すべて綺麗に 1echo out >/sys/class/gpio/gpioX/directionecho high >/sys/class/gpio/gpioX/direction は別物のようだ。

$ for f in {4..27}; do echo in   >/sys/class/gpio/gpio$f/direction; sleep .5; done
$ for f in {4..27}; do echo high >/sys/class/gpio/gpio$f/direction; sleep .5; done
$ for f in {4..27}; do printf '%2s %3s %s\n' $f `cat /sys/class/gpio/gpio$f/{direction,value}`; done
 4 out 1
 5 out 1
 6 out 1
 7 out 1
 8 out 1
 9 out 1
10 out 1
11 out 1
12 out 1
13 out 1
14 out 1
15 out 1
16 out 1
17 out 1
18 out 1
19 out 1
20 out 1
21 out 1
22 out 1
23 out 1
24 out 1
25 out 1
26 out 1
27 out 1

high があるなら low もあるんだろうということでやってみたら今度は out だけど値は 0 になった。

$ for f in {4..27}; do echo in   >/sys/class/gpio/gpio$f/direction; sleep .5; done
$ for f in {4..27}; do echo low  >/sys/class/gpio/gpio$f/direction; sleep .5; done
$ for f in {4..27}; do printf '%2s %3s %s\n' $f `cat /sys/class/gpio/gpio$f/{direction,value}`; done
 4 out 0
 5 out 0
 6 out 0
 7 out 0
 8 out 0
 9 out 0
10 out 0
11 out 0
12 out 0
13 out 0
14 out 0
15 out 0
16 out 0
17 out 0
18 out 0
19 out 0
20 out 0
21 out 0
22 out 0
23 out 0
24 out 0
25 out 0
26 out 0
27 out 0

以前、エアコンの信号を夜に取るのに赤外線受光モジュールの足を15番に繋いだような繋いでないような。ものすごく不安定でまともに信号を読み取れなかったのだが、何か関係しているのだろうか。(この時は充電最適化機能付きの電源を使っているのが問題だったのだが)

とりあえずボタン入力とかは 4/5/6/7/8/15 を避けた方が安定しそうだ。

時間ができたら UK 版と JP 版の Raspberry Pi 3、それから Zero でも調べてみよう。入力で初期値を決めるワードってなんだろうか。あと OS とか Raspberry Pi のバージョンでも違うんだろうか。

そういえばよく見たら17番ピンの3.3Vにちゃんと抵抗ついてた。これを目印にすれば3.3Vの取り出しは間違え無さそうだ。

Raspberry Pi Zero Raspbian

Raspberry Pi Zero Raspbian でも試してみたところ、こちらは 4/5/6/7/8/15 に加え、14 も 1 になった。

# for f in {4..27}; do echo $f >/sys/class/gpio/export; sleep 2; done
# for f in {4..27}; do printf '%2s %3s %s\n' $f `cat /sys/class/gpio/gpio$f/{direction,value}`; done
 4  in 1                                                                                                                                              
 5  in 1                                                                                                                                              
 6  in 1                                                                                                                                              
 7  in 1                                                                                                                                              
 8  in 1                                                                                                                                              
 9  in 0                                                                                                                                              
10  in 0                                                                                                                                              
11  in 0                                                                                                                                              
12  in 0                                                                                                                                              
13  in 0                                                                                                                                              
14  in 1                                                                                                                                              
15  in 1                                                                                                                                              
16  in 0                                                                                                                                              
17  in 0                                                                                                                                              
18  in 0                                                                                                                                              
19  in 0                                                                                                                                              
20  in 0
21  in 0
22  in 0
23  in 0
24  in 0
25  in 0
26  in 0
27  in 0

4/5/6/7/8 に関しては http://elinux.org/RPi_BCM2835_GPIOs に High と書いてあるのだけど 14/15 はわからないな。

YouTubeのプレイリストのURLを解析してプレーヤーにぶち込む

youtube-dl が YouTube の視聴ページだけではなくプレイリストにも対応しているので mpv ではプレイリストの URL を渡すだけで連続視聴ができていた。

しかし、Raspberry Pi Zero では MMAL を使ったハードウェアデコーディングがまともに動かないことがわかり、omxplayer での再生が必須になった。

omxplayer で YouTube の動画をダイレクトに再生する

youtube-dl で動画をローカルに落としてしまえば omxplayer でも簡単に再生できるのだが、貧弱な microSD にそこまで負荷をかけたくない。

youtube-dl -g {URL} で取得した URL を omxplayer に渡せば omxplayer でも YouTube の動画をそのまま再生できるのだが、これには YouTube の仕様の問題がある。

例えば以下のようにコマンド置換で動画の URL を直接 omxplayer に渡したとする。

$ omxplayer `youtube-dl -g {URL}`

この場合、動画が 1920x1080 以上の解像度を持っていると、ビデオとオーディオの URL が分割されてしまうため、恐らくはビデオしか再生されない。

YouTube の仕様上、ビデオとオーディオが一体になっているのは 1280x720 までのようなので omxplayer にダイレクトに渡すなら以下のようにするのが正しい。-f best でフォーマットを「ビデオ + オーディオの最高品質」にすれば URL はひとつになる。ただし、解像度は 1280x720 まで。

$ omxplayer `youtube-dl -f best -g {URL}`

プレイリストの再生

さて、omxplayer に YouTube の URL を渡して直接再生出来るようになったが、omxplayer は YouTube のプレイリストの URL は受け取らない。これでは1曲ごとに URL を叩くことになるので非常に面倒。

というわけで YouTube のプレイリストに含まれる動画の URL を根こそぎ拾ってくることにした。プレイリストのサンプルは Flying Dog のページから借りる。

www.youtube.com

プレイリストが長いと取得に時間がかかるので、ここでは --playlist-end=10 として10個まで拾ってくることにする。

$ youtube-dl --playlist-end=10 -f best -g 'https://www.youtube.com/user/flyingDOGch/videos'

jq を使って JSON から取り出してもいい。ビデオとオーディオが一体になっている URL は entries のひとつ下の url に含まれている。

$ youtube-dl --playlist-end=10 -f best 'https://www.youtube.com/user/flyingDOGch/videos' | jq -r '.entries[].url'

あとはこの結果をループに流してしまえばいい。

$ for f in `youtube-dl --playlist-end=10 -f best -g 'https://www.youtube.com/user/flyingDOGch/videos'`; do omxplayer "$f"; done

ランダム再生がいいのなら | sort -R する。

$ for f in `youtube-dl --playlist-end=10 -f best -g 'https://www.youtube.com/user/flyingDOGch/videos' | sort -R`; do omxplayer "$f"; done

無限ループにするなら while の中に入れる。

$ while :; do for f in `youtube-dl --playlist-end=10 -f best -g 'https://www.youtube.com/user/flyingDOGch/videos' | sort -R`; do omxplayer "$f"; done; done

毎回プレイリストの URL を拾ってくるのも時間がかかるので普通ならテキストファイルに落として再生かな。

$ for f in `<youtube.m3u`; do omxplayer "$f"; done

プレイリストを毎回ダウンロードするのも一応メリットがあり、ブラウザで YouTube のプレイリストの編集をしたときに常に最新の物が拾ってこれる。

トレンドチャンネルや映画予告チャンネルなんかを取得するようにしておけば常に最新の情報が手に入る…かも。

プレイリストの取得は時間がかかるので cron で更新するようにしておくようにするかな。