MCP3425のくせ
マイコンでICと通信するために、UARTやSPIを使ったことがあったが、これらは基本的には一対一の通信である。一方、I2Cは、原理的には128個のICと二本の線で通信できる。
電子工作をしていて、16bitのADコンバーターであるMCP3425をI2Cでマイコンから読み取ることにした。3つのMCP3425を使うことにしたのだが、これを二本の線だけで通信できるのは素晴らしいと思っていたのだが、買ってから資料をよく読むと、アドレスが八種類あるのだが、普通に買うと一種類のアドレスのICとなり、これらを同時に使うことができないことが分かった。六本も使うのは悔しいので、クロックを共通にして、四本で3つのICを使うことにした。
I2CをAVRから使うのは始めてだったので、最初はうまく通信ができなかった。読み取りの時にPINでは無くPORTから読んだり、いくつかのバグを発見して、一応の通信はできるようになったが、まだ何か変であった。
接続してから一回目はうまく読み取れるのだが、二回目以降がうまく行かないことに気がついて、資料をよく読みなおしてみたら、読み取るときの最終データに対しては、ACKを送らないという約束になっているようだ。ううん、ややこしい。
でも、これでMCP3425との通信ができるようになり、ADコンバーターとしてもそれなりに精度もあって使いやすいことが分かった。参照電圧も不用だし。
ubuntu mate on raspberry pi2で計測
ruby2.1とgtkとusb hubに苦しめられたが
数年間計測に使っていたnote PCが遅くなってきたので、制御用のPCを入れ替えることにした。noteは余っていないし、desktopも邪魔なので、raspberry piを使ってはどうかと考えた。しかし、raspbianではusbtmcを使うためにkernelをコンパイルしないといけない。raspberry pi2で動くubuntu mateだと、usbtmcはそのままで使えるというわけで、これを使って測定系を組むことにした。いくつかのハードルはあるとは思っていたが、予想していたよりも、少し苦労させられることになったが、なんとかうまく動くようになった。
まず、最初にはまったのが、rubyのversionによる問題である。それまでのシステムはruby1.8で動いていたのだが、今回はruby2.1で動かしている。version依存の命令は使っていないつもりだったので、そのままで動くと予想していたのだが、考えが甘かった。usb-serialで通信していたのだが、なぜかうまく動かない。オシロを使って信号を読んでみると、送ろうと思っている文字列と違う文字列が送られていることに気がついた。このとき、"%c"%nのような書き方をしていたのだが、このときに、勝手にunicodeに変換されてしまっていた。そこで、[n].unpack(“c”)としたら、変換されなくなり、通信できるようになった。
次の問題は、ruby/tkである。ubuntuでは、なぜかruby/tkがサポートされなくなってきているようなので、ruby/gtk2に移植する必要があった。少し時間はかかったが、tkとほぼ同じ感じでgtk2も使えるようになった。
しかし、実際に動かしてみると、通信エラーを頻繁に起こすことが分かった。いろいろと原因を考えた結果、usbのhubを疑うことにした。raspberry pi2には四つのusb portがある。ここに、mouseとkeyboardとusbtmcとusb-serial*2の合計五つのusb機器をつないでいる。そのため、usbのhubが必要で、それまでは、測定機器はすべてhubを介して接続されていた。そこで、mouseとkeyboardをhubを介して接続し、残りの三つの装置を直接つなぐようにしたら、通信エラーが起こらなくなった。
これで、測定できるシステムが完成した。あとはftpdを入れて、固定IPにして、ntpの設定をして、keyboardのlocaleを合わせるぐらいかな。ftpは以前使っていたvsftpdを入れればよい。固定IPにするのは、/etc/network/interfacesをいじりたくなるのだが、メニューからネットワーク接続を選んで、設定すればよいようだ。ntpはおそらく/etc/ntp.confをいじるのだと予想している。keyboardもmateのメニューのkeyboardで種類を設定できるようだ。あと、自動起動で不要なものを消しておくと良いかも知れない。
ruby/tkからruby/gtk2への移行
tkとgtk2の違い
これまで、rubyでGUIを作る必要があるときには、主にtkを使っていた。しかし、最近のubuntuは、ruby/tkとは相性が悪いようで、今後はruby/tkがどうなって行くのかが不安である。そこで、ruby/tkの代わりにruby/gtk2を使ってみることにした。これまでtkを使って書いていたのものを、gtkに簡単に移植するために、tkライクにgtkを使えるwrapperのようなものを書いたら、なんとかひとつのプログラムの移植は完了した。その作業の中で、tkとgtkの違いについて、いくつか感じたことを書いておこう。
tkの場合には、toplevelの中に、一つずつpackしたり、frameを作ってその中にpackしたりして、配置する。一方、gtkでは、windowの中に入れることができるのは、一つだけで、通常はvboxなどを入れて、その中に配置していく。わざわざboxを入れないといけないのは、少し面倒だなと感じた。
面倒と言えば、gtkではwindowを閉じたときの処理とか、fileを開くための画面などで、ボタンを押したときの処理を一々指定しないといけない。これは、細かい指定ができるという意味ではメリットかも知れないが、何も指定しなくても、cancelのときは、普通にcancelしてくれる方が良い気もする。
gtkでaddしたあとにshowしないといけないのも、面倒かな。
また、tclの仕様のために、tkの場合には、数字という概念があまり無いので、数字を扱うときには、rubyで受け取るときに、数字に変換する必要がある。
まとめると、ruby/tkはオプションの指定などの仕方が独特で、取っ付きにくいけど、意外に指定することが少ない場合もある。ruby/gtkはきめ細やかな設定ができる代わりに、デフォルトの設定が少なくて、いろいろと指定する必要がある。まあ、一応つかえるようになってしまえば、tkもgtkもあまり変わらない気がする。
loginできない
/dev/nullのpermission
今日、debianにloginしようと思ったら、なぜかうまく行かなかった。passwordを打ち間違えたかと思ったけど、そうでは無いようだ。rootではloginができたので、少し調べてみたら、.xsession-errorsには、
cannot create /dev/null: Permission denied
となって、Xが立ち上がらないのが原因のようだ。こうなってしまった理由は良く分からないのだが、/etc/rc.localのexit 0の前に、
chmod 0666 /dev/null
と入れれば良いというのを見つけたので、そうしたらloginできるようになった。なんか、気持ち悪いけど、まあいいか。
code golf
久々にrubyでgolfをやってみた。
このサイトのgolfを試してみた。そのNo.902の1 2 32 4 512というものである。具体的には、2のn乗で1から100までの数字から始まるものを順に探して表示するというものである。まず、普通に書いてみたのが、
100.times{|i|r=1;r*=2 until r.to_s=~/^#{i+1}/;p r}
で50bytesである。そのすぐ後に、スペースを取り除けることに気が付き、
100.times{|i|r=1;r*=2until"#{r}"=~/^#{i+1}/;p r}として、48bytesまでになった。ここから、いろいろな工夫をしてみたが、どうしても48を切ることができなかった。例えば、
1.upto(100){|i|r=1;r*=2until"#{r}"=~/^#{i}/;p r} 1.upto(100){|i|r=1;r*=2until"%s"%r=~/^#{i}/;p r} 1.upto(100){|i|r=1;r*=2until"#{r}"[/^#{i}/];p r} 1.upto(100){|i|r=1;$_="#{r*=2}"until/^#{i}/;p r}
などを作ったが、何をやっても48止まりだった。特に、最後のは1に対する答えが16になってしまうという欠点もあるし。ruby1.8なら、100の代わりに?dを使うという技を使えるのだが。その時、一位の人は46で二位が47だった。10bytesぐらい差をつけられていたら、もう諦めるのだが、数byteとかだと、なんとかなるのでは無いかと思ってしまう。散々考えていたら、昨晩、47に到達した。
($.+=r=1;r*=2until"#{r}"=~/^#$./;p r)until$.>99
というものである。行数を表す組み込み変数$.を使って、初期値の代入と#{}の括弧をなくしたり、最初に1を足すことによって、100の代わりに99を使えるようにして、なんとか1byte減らすことに成功した。これでなんとか二位には追いついたが、一位の46bytesはどうやっているのか、全く見当もつかない。
2015/6/30追記 二位の人は、ruby1.8流のやり方をしていた。これなら、1.9以降でも動く私のscriptの方が上とも言える。一位の人は、これに加えて、補数を求める~演算子を使っていた。なるほど、これなら100を99までで良くなるのでtimesが使えるし、行頭の^も省略できる。
共用PCの入れ替え
debian8のPC
長らく共用のPCとして使っていたnoteが死んだので、別のnoteに入れ替えた。実はそのnoteには、しばらく前にdebian8をインストールしたのだが、起動しようとしたらビープ音が鳴るようになってしまい、電源がおかしいのかなと思って放置してあった。少し調べていたら、どうやらキーボードのどれかのキーが押された状態と認識されており、そのために音がいる可能性があることが分かった。そこで、分解してキーボートのフラットケーブルを外してみたところ、うまく動くようになった。基本的には、外付けのキーボートとマウスを繋いで使うので、これで問題が無い。ftpdやntpの設定をして、共用のPCとして使えるようになった。
debian8のLXDEを少し使ってみたが、windowの移動のときに、遅れて着いてくる感じで、気持ち悪い。単にPCの性能が低いだけかも知れ無いが。
rpi2にubuntu mate
usbtmcが使える
raspberry pi 2を使って、測定システムを組もうと思い、OSを調べていたら、新しくubuntu mateというOSが加わっていたので、試してみた。これまで、raspberry piにはraspbianを入れていたが、usbtmcがそのままでは使えないので、kernelをコンパイルし直して使っていた。これがそれなりに面倒だし、kernelが新しくなったら、またコンパイルしないといけない。しかし、ubuntu mateはそのままでusbtmcが使えたので、測定用に適しているのでは無いかと感じた。
ubuntu mateのインストールは、以下のように行った。まず、イメージの圧縮ファイルをdownloadして、解凍する。これを、
sudo dd bs=1M if=ubuntu-mate-15.04-desktop-armhf-raspberry-pi-2.img of=/dev/sdX
などとして書き込む。sdXのところにはmicroSDを指定するようにして下さい。今回は8GBのmicroSDを使ったのだが、ubuntu mateには、partitionの格調をする機能が無いようなので、gpartedを使って拡張する。microSDの二番目のpartitionを選んで、リサイズする。そして、あとはrpi2に挿して起動である。 セットアップの仕方は、ubuntuとかに慣れていれば、それほど難しくないだろう。日本語を入力できるようにするために、ibus-anthyを入れて、あとは必要なr-baseやrubyを入れれば、測定に使えるようになる。ただ、いくつかのパッケージの取得に失敗したので、source.listを少し書き換えたが。 無事usbtmcの制御もできたし、測定用のマシンとしてのセットアップをしよう。
PWMを使ってみた
attiny2313のタイマーとPWM
LEDの光量を調節するために、AVRのattiny2313のPWMを使ってみた。もちろん、マニュアル通りにやれば動くのだが、そのすべてを読むのは大変だし、私がいくつか迷った点を書いておこうと思う。
attiny2313には、二つのタイマーがあり、timer0は8bitでtimer1は16bitである。この二種類のタイマーに対してPWMがあり、それぞれOC0A,BおよびOC1A,Bのピンが対応している。さらに、AとBの使い分けは、通常のPWMはどちらを使っても良いが、カウンタを途中までで使うときにはBのを使う。つまり、8bitの場合に255までカウントするときにはどちらでも良く、例えば100までカウントするときにはBを使うというわけである。
同様にタイマーに関して、通常の場合はOVFの割り込みで良いが、途中までのカウントの場合には、COMAの割り込みを使う。
tinyとmega
レジスタの名称
これまで、AVRマイコンとしては、tiny2313かtiny261などを良く使っていた。今回、atmega88を使ったのだが、tinyのプログラムを流用して書いたら、エラーが沢山出てしまった。uartのところで、レジスタの名称に0を付けないといけないというのが主な原因だった。いくつかある場合に番号をつけないといけないのはわかるが、0は省略しても良いようにしておいてくれると、tinyとmegaで同じプログラムが使えるのに。折角なので、tinyとmega用のuartのsubroutineを別のファイルにして、コンパイルできるようにしておいた。これで、今後は困らないはずだ。
ubuntu14.04にavrdude6.1をインストール
avrdudeでarduino-ft232r
久々にavrを使おうと思って、書き込みをしようと思ったら、うまくいかなかった。ft232rを使ったarduino-ft232rまたはdiecimilaというタイプの書き込み機を指定したのだが、flushの消去に失敗する。どうやら、バグがあったようで、去年の9月末ぐらいには対策されている。しかし、ubuntu14.04のマシンのavrdude6.01では、動かないようだ。6.1ももう出ており、ubuntu14.10ではこれが標準になっている。しかし、ubuntu14.04はLTSなので、このままでなんとかしたい。
調べてみたら、以下のようにすると、avrdude6.1をインストールできるらしい。
sudo aptitude remove avrdude sudo add-apt-repository ppa:pmjdebruijn/avrdude-release sudo apt-get update sudo apt-get install avrdude
これで書き込んでみたら、うまくいった。