読者です 読者をやめる 読者になる 読者になる

😃 mattintosh note 📝

Hello Raspberry Pi!

シェルスクリプトで2進数や16進数を変換

最近、A/Dコンバーターを使うので2進数を扱うことが多くなってきた。Python なんかだと 0b や 0x といった書式や bin() や hex() といった関数があるが、シェルスクリプトの場合はどうするのか?マニュアルを見るとこんな風に書いてある。

Constants with a leading 0 are interpreted as octal numbers.
A leading 0x or 0X denotes hexadecimal.
Otherwise, numbers take the form [base#]n, where the optional base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base.
If base# is omitted, then base 10 is used.
When specifying n, the digits greater< than 9 are represented by the lowercase letters, the uppercase letters, @, and _, in that order.
If base is less than or equal to 36, lowercase and uppercase letters may be used interchangeably to represent numbers between 10 and 35.

0x は使ったことがあったけど、[base#]n という書き方で基数が指定できるようだ。(ver3時代からあったっけ???)

$ echo $((2#0)) $((2#1)) $((2#1111)) $((2#11111111))
0 1 15 255

ビットシフトや AND/OR とかもオッケー。

$ echo $((2#101)) $((2#101 << 2)) $((2#101 << 4)) $((2#101 << 8))
5 20 80 1280
$ echo $((2#10101010)) $((2#10101010 & 2#1111)) $((2#10101010 | 2#1111))
170 10 175

変数も使える。

$ var=1111
$ echo $((2#${var}))
15

16進数や8進数もおんなじ感じだね。

$ echo $((0xff)) $((16#ff))
255 255
$ echo $((077)) $((8#77))
63 63

2進数や16進数からの変換は上記の方法でできるけど、2進数への変換はどうするのか?

とりあえず bc や配列を使う方法があるけど、bash 標準の機能で出来るかどうかはいまのところわからない。

$ echo "obase=2;8" | bc
1000
$ echo "obase=2;1;2;4;8;16" | bc
1
10
100
1000
10000

配列の場合は 0 から始まるのでそのまま指定すればいいが、set を使う場合は 1 から始まるのでその分を足してあげる必要がある。いずれも関数にしておけば簡単に使えそうだ。

$ set -x
$ d2b=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
+ d2b=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
$ echo ${d2b[8]}
+ echo 00001000
00001000

$ set -- {0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}
+ set -- 00000000 00000001 00000010 00000011 00000100 00000101 00000110 00000111 00001000 00001001 00001010 00001011 00001100 00001101 00001110 00001111 00010000 00010001 00010010 00010011 00010100 00010101 00010110 00010111 00011000 00011001 00011010 00011011 00011100 00011101 00011110 00011111 00100000 00100001 00100010 00100011 00100100 00100101 00100110 00100111 00101000 00101001 00101010 00101011 00101100 00101101 00101110 00101111 00110000 00110001 00110010 00110011 00110100 00110101 00110110 00110111 00111000 00111001 00111010 00111011 00111100 00111101 00111110 00111111 01000000 01000001 01000010 01000011 01000100 01000101 01000110 01000111 01001000 01001001 01001010 01001011 01001100 01001101 01001110 01001111 01010000 01010001 01010010 01010011 01010100 01010101 01010110 01010111 01011000 01011001 01011010 01011011 01011100 01011101 01011110 01011111 01100000 01100001 01100010 01100011 01100100 01100101 01100110 01100111 01101000 01101001 01101010 01101011 01101100 01101101 01101110 01101111 01110000 01110001 01110010 01110011 01110100 01110101 01110110 01110111 01111000 01111001 01111010 01111011 01111100 01111101 01111110 01111111 10000000 10000001 10000010 10000011 10000100 10000101 10000110 10000111 10001000 10001001 10001010 10001011 10001100 10001101 10001110 10001111 10010000 10010001 10010010 10010011 10010100 10010101 10010110 10010111 10011000 10011001 10011010 10011011 10011100 10011101 10011110 10011111 10100000 10100001 10100010 10100011 10100100 10100101 10100110 10100111 10101000 10101001 10101010 10101011 10101100 10101101 10101110 10101111 10110000 10110001 10110010 10110011 10110100 10110101 10110110 10110111 10111000 10111001 10111010 10111011 10111100 10111101 10111110 10111111 11000000 11000001 11000010 11000011 11000100 11000101 11000110 11000111 11001000 11001001 11001010 11001011 11001100 11001101 11001110 11001111 11010000 11010001 11010010 11010011 11010100 11010101 11010110 11010111 11011000 11011001 11011010 11011011 11011100 11011101 11011110 11011111 11100000 11100001 11100010 11100011 11100100 11100101 11100110 11100111 11101000 11101001 11101010 11101011 11101100 11101101 11101110 11101111 11110000 11110001 11110010 11110011 11110100 11110101 11110110 11110111 11111000 11111001 11111010 11111011 11111100 11111101 11111110 11111111
$ eval echo \${$((8 + 1))}
+ eval echo '${9}'
++ echo 00001000
00001000
$ eval echo \${$((255 + 1))}
+ eval echo '${256}'
++ echo 11111111
11111111

Hyper-V 上の Ubuntu で Time has been changed が止まらない

会社の仮想環境で Ubuntu を使っているのだけど、いつからか

  • bmon の表示が「止まったと思ったら一気に流れだした」
  • htop や glances が途中で止まる

と言ったことが起こるようになってしまった。

で、gnuplot で timestamp を使ってグラフを作ると何故か逆走するポイントがあったりしたので、watch date してみたら時間が一時的に20分先に進んでしまうという症状を発見した。

hwclock や timedatectl で見てみると、ハードウェアクロックがおかしいようで、20分先に進んだり20分前に戻ったりしている。酷い時は当日の 00:00:00 まで戻る。

f:id:mattintosh4:20170521000608p:plain

systemd-timesyncd は有効になっているし、ntpdate で時間を調整しても症状は改善せず。

一旦、ntp 関連をすべて切ってみるとハードウェアクロックが20分進んだ状態でシステムクロックも安定しだした。その状態で ntpdate、hwclock してもまたすぐ20分進んでしまう。

Hyper-V を稼働しているマシンで Time synchronization を有効にしている場合、Linux の場合は起動時に影響があるようだが、起動後は NTP による制御になる。

と、ずっと思っていたのだが、journalctl を見てみると5秒おきに Time has been changed が出る。NTP も切っているのに何故だ???

色々探してみてようやく答えを見つけた。

I have a lot of "Time has been changed" in the journal of my linux boxes

どうもゲストマシンに Hyper-V 用のモジュールを入れていると勝手に時間をハードウェアクロックに合わせようとしてしまうらしい。

Time Synchronization のデバイスIDは決まっているようなので unbind すれば同期が止まる。

echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind

Time Synchronization は hv_vmbus に含まれていそうだけど下手に抜いて止まると厄介なので上のコマンドを rc.local にでも書いておくか…。

$ lsmod | grep hv
hv_netvsc              40960  0
hv_utils               28672  0
hv_storvsc             20480  2
scsi_transport_fc      61440  1 hv_storvsc
hv_vmbus               90112  6 hyperv_keyboard,hv_netvsc,hid_hyperv,hv_utils,hyperv_fb,hv_storvsc

とりあえず ntp をインストール。Ubuntu デフォルトだと Ubuntu の NTP サーバを使うようになっているので他のサーバに変更。

$ sudo apt-get install ntp
$ sudo -e /etc/ntp.conf
server ntp.nict.jp
server time1.google.com iburst
server time2.google.com iburst
server time3.google.com iburst
server time4.google.com iburst

systemd-timesyncd はオフにして ntp だけにしとく。

$ sudo systemctl stop systemd-timesyncd
$ ^stop^disable
$ sudo systemctl start ntp
$ ^start^enable

ようやく安定。

$ watch timedatectl
      Local time: Sun 2017-05-21 00:36:26 JST
  Universal time: Sat 2017-05-20 15:36:26 UTC
        RTC time: Sat 2017-05-20 15:36:26
       Time zone: Japan (JST, +0900)
 Network time on: no
NTP synchronized: yes
 RTC in local TZ: no

仮想マシンは仕組み上、システム時間とハードウェアクロックがどんどんずれていくものなので定期的にハードウェアクロックの調整が必要のようだが、今回はちょっと違った問題だったので直すのに手間取った…。

MediaWikiで致命的例外Symfony\Component\Process\Exception\ProcessTimedOutExceptionが発生する

MediaWiki と MySQL を使っているんだけど、最近よく下記のエラーが発生するようになった。

[a7a5567fcc6f7e711b3cfddf] 2017-05-13 17:21:38: 種別「Symfony\Component\Process\Exception\ProcessTimedOutException」の致命的例外

ProcessTimeOut とあるように、何かしらが時間切れになっているようだが、恐らく MySQL なんだろうなぁ…。とりあえず MySQL のデータベース最適化を実行してみる。

$ mysqlcheck -u root -proot --all-databases --optimize

これでもまだ直らないので MediaWiki のモジュールをチェック。エラー内容の文字列を検索すると mediawiki/vendor/symfony/process/Process.php が見つかった。中身を見てみると44行目にタイムアウトの設定らしきものがあった。

43     // Timeout Precision in seconds.
44     const TIMEOUT_PRECISION = 0.2;

とりあえず 0.2 を 8.0 ぐらいに変更して様子見。

土壌湿度センサーを自作した話

秋月電子で買った DFRoboto 製の Arduino 用土壌湿度センサーを Raspberry Pi Zero で2ヶ月ほど使ってました。

楽しい #RaspberryPi #土壌センサー

Makoto Yoshidaさん(@mattintosh4)がシェアした投稿 -

最近、ヘデラの方が水をやっているのに ADC で測定している電圧がなかなか上がらず…。土との接触が悪いのかと思い、センサーを掘り出してみたら見事に金メッキが剥げていました。

土壌の質のせいなのかよくわかりませんが、500円でこんなもんか…という感じ。買い直してもまた2、3ヶ月で同じ状態になっても困るので別の手段を考えることに。

この土壌湿度センサー、公開されている回路図を見るとトランジスタと抵抗しか使っていないっぽい。

ということは作れるのか…?

と、思い、トランジスタと100Ω抵抗を使ってセンサーと同じ回路を作成してジャンパーピンを土にプスっと挿してみた。

…

………

………………あ、反応するんだw

というわけで別に「土壌湿度センサー」という製品に拘る必要はなく、トランジスタと抵抗と適当な金属板か棒があればいいようで。

とりあえず秋葉原の電気街で一般的なバナナプラグを買ってきて土にプスっと。コンセントプラグがネタとして面白いかなと思ったけど、ねじ山切ってある金属棒にニチフの丸端子を固定してもいいかな。

ヘデラの方はバナナプラグ、ベンジャミンの方は金メッキが剥げていないので市販の土壌湿度センサー。どちらも問題なく稼働中。

自作(?)土壌湿度センサー問題なく稼働中 #RaspberryPi

Makoto Yoshidaさん(@mattintosh4)がシェアした投稿 -

バナナプラグだと長さが短いので柔らかい土だと接触不良を起こすかも。そのうちもう少し長めの棒に変える予定。

バナナプラグが一番高くて2個で100円くらいだったけど、有り物で作ればトランジスタと抵抗代くらいで済むので数十円で作ることができる。土の抵抗が大きくなったらLEDが点灯するみたいな回路なら簡単に作れるね。

DFRoboto さん、製品改良してくれないかなー。

Raspberry Pi で HDMI 出力を初期化する

mpv を複数同時に起動したら [vo/rpi] Could not get DISPMANX objects. のメッセージと共に画面が固まった。OS を再起動すれば直るんだろうけど面倒なので tvservice やら fbset のヘルプを見てみると再起動できそうなオプションがあった。

$ tvservice --preferred

で、直りましたとさ。tvservice で済んでしまったので fbset は試してないけど、もしかしたらそっちでも直るかも。

mattintosh.hatenablog.com