なんとかやり方を見つけた
簡単な数式はRのexpressionを使うと書くことができる。垂直記号(⊥)をどうやって出すのかを聞かれて、少し調べて分からなかったので、psfragなどに頼ろうと思ったら、demo(plotmath)としたら、やり方が出てきた。
expression(symbol("\136"))
とすれば良いようです。symbolのフォントの文字が他にも出せるようだが、文字コードと数字の対応がよく分からない。
なんとかやり方を見つけた
簡単な数式はRのexpressionを使うと書くことができる。垂直記号(⊥)をどうやって出すのかを聞かれて、少し調べて分からなかったので、psfragなどに頼ろうと思ったら、demo(plotmath)としたら、やり方が出てきた。
expression(symbol("\136"))
とすれば良いようです。symbolのフォントの文字が他にも出せるようだが、文字コードと数字の対応がよく分からない。
USBハブが原因だった
測定装置に組み込んでいるモーターの挙動が変だということなので、原因を調べてみた。このモーターは、USBシリアルで変換した信号を、AVRのtiny2313で読み取って、ソリッドステートリレーを制御することによって、回転させている。しかし、時々逆回転をしたりしている。
まず疑ったのが、rubyのversion問題である。回転方向を指定するときに、binaryを送っているので、以前遭遇したunicodeへの自動変換が行われているのでは無いかと疑った。しかし、これは問題無いようだった。次に疑ったのが、ハードウェアの故障である。しかし、ランプなどを見ていると問題無い。仕方がないので、オシロでシリアルの信号を見てみる。すると、時々文字が化けていることが分かった。
以前、USBのハブが悪さをしていたのだが、モーターのためのシリアルには、大した情報は送っていないので、ハブを介してUSBシリアルを接続していた。これをPCというかRaspberry Pi2に直挿しすると、文字化けは無くなった。しかしこのままではUSBのポートが足りないので、手持ちのUSBハブをいろいろ持って行って、交換してみたら、ひとつ目でうまく行くようになった。
システムを入れ替えたのが7月なので、約半年も気づかずに使っていたようだ。しかし、これで別の装置との通信も安心して行えるようになる気がする。
割り込みを利用するUARTの使い方
AVRを使うときに、以前はtiny2313をよく使っていたが、最近は秋月の価格が高くなって、megaとあまり変わらなくなったので、mega88をよく使うようになってきた。megaの方がtinyよりも安いのは、変な気がする。
AVRの書き込みにはFTDIのFT232RLを使っているが、PCとUSBで通信する時にも同じ石を使っている。arduino-ft232rの書き込みpinとTX,RXの通信pinをつないでおくと、通信と書き込みの両方ができるようになる。この配線をするのが面倒だと思っていたのだが、UncomPatino基板を使うと、この配線をする手間が省けるので、この基板を利用することが多くなってきた。それなら、Arduinoを使えば良いじゃないかとも思えるが、クロック用に2pinを奪われるので、IOに使えるpinが減ってしまう。
PCとは、USBからFT232RLでUARTに変換して、mega88と通信する。そのとき、できるだけマイコンの負荷を減らすには、割り込みをうまく使うと良い。これまで、マイコンが受信するときは、割り込みでバッファに取り込んでいたが、バッファの内容を送信するときには、一文字送信されるのを待って次の文字を送信していた。以下のようにすると、送信のときの処理時間が減らせる。
#define BUFSIZE 100
static volatile unsigned char buf[BUFSIZE];
static volatile unsigned char i_buf=0;
static volatile unsigned char run_CMD=FALSE;
ISR(USART_RX_vect){ /* received */
volatile unsigned char c;
c=UDR0;
buf[i_buf++]=c;
if(i_buf>=BUFSIZE){i_buf=0;}
if(c==10){
run_CMD=TRUE;
i_buf=0;
}
}
ISR(USART_UDRE_vect){
if(buf[i_buf]!=10){UDR0=buf[++i_buf];} //next
else{i_buf=0;clearbit(UCSR0B,UDRIE0);} //end
}
void buf_rs232c(){ // buffer transmit
while(checkbit(UCSR0B,UDRIE0)){} //previous buffer transmit is running
UDR0=buf[i_buf=0];
setbit(UCSR0B,UDRIE0);
}
ちなみに、setbit,clearbitやcheckbitなども定義している。
仕方がない
Debian Wheezyにpovrayをインストールしようとしたら、packageから削除されていた。ubuntuにはあるのに。公式サイトにはソースがあるので、それをコンパイルすれば良いのかもしれないが、面倒だ。調べてみると、Debian jessieだとpovrayもあるようだ。まあ、jessieがでて、数カ月経っているし、そろそろインストールしようということで、OSを入れ替えることにした。CDを焼くのに一回失敗したが、無事にOSを入れ替えて、povrayも実行できた。日本語は特に設定無しで使えるし、icedoveとrubyとemacs24とanthy-elを入れたら、まあ今日すべきことはできるかな。/homeは別のパーティションなので、以前の設定はそのまま使えるし。
目覚まし更新
久々に目覚ましを更新した。だんだんと高性能になるにつれて、使い方も複雑になって来ているのを感じる。説明書も少し読んで、最低限の使い方ができるようになった。使っているうちに、だんだんと分かってくるだろう。
golfのテクニックも使って
大昔に書いて、長らく使っていたrubyのスクリプトを、書き換えてみた。古いバージョンのものは、2004年にはほぼ出来上がっていたようなので、十年以上ぶりの大幅の書き換えとなる。
全体としては、rubyっぽい書き方を取り入れた。例えば、以前は
f=open("filename","w")
f.print str
という書き方をしていたが、新しいものでは、
open("filename","w"){|f|f.print str}
となっている。また、少しgolfっぽくif文を無くして
n=ARGV[0] || puts("data file: ") || STDIN.readline
などの書き方も使っている。この十年で、私のrubyの書き方もずいぶん変わった気がする。rubyの仕様もそれなりには変わっているし。
MCP3425のくせ
マイコンでICと通信するために、UARTやSPIを使ったことがあったが、これらは基本的には一対一の通信である。一方、I2Cは、原理的には128個のICと二本の線で通信できる。
電子工作をしていて、16bitのADコンバーターであるMCP3425をI2Cでマイコンから読み取ることにした。3つのMCP3425を使うことにしたのだが、これを二本の線だけで通信できるのは素晴らしいと思っていたのだが、買ってから資料をよく読むと、アドレスが八種類あるのだが、普通に買うと一種類のアドレスのICとなり、これらを同時に使うことができないことが分かった。六本も使うのは悔しいので、クロックを共通にして、四本で3つのICを使うことにした。
I2CをAVRから使うのは始めてだったので、最初はうまく通信ができなかった。読み取りの時にPINでは無くPORTから読んだり、いくつかのバグを発見して、一応の通信はできるようになったが、まだ何か変であった。
接続してから一回目はうまく読み取れるのだが、二回目以降がうまく行かないことに気がついて、資料をよく読みなおしてみたら、読み取るときの最終データに対しては、ACKを送らないという約束になっているようだ。ううん、ややこしい。
でも、これでMCP3425との通信ができるようになり、ADコンバーターとしてもそれなりに精度もあって使いやすいことが分かった。参照電圧も不用だし。
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で種類を設定できるようだ。あと、自動起動で不要なものを消しておくと良いかも知れない。
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もあまり変わらない気がする。