arduino UNOの空きランド
arduino UNOを時々使っているが、純正品はそれなりに高い。そこで、CH340のチップを使った中国製のUNO互換機を主に利用している。このUNOには、X1という四ピンをはんだ付けできる場所があり、これが何なのかを調べてみた。CH340との接続を調べてみると、左からCTS, DSR, DCD, RIの信号に繋がっている。これらは、いずれもRS232Cの入力信号である。つまり、これらのピンに電圧をかけると、その情報をPCから読み取れるようになるはずである。
ちなみに、出力信号であるDTRは、arduinoのresetに使われているので、highに保つ必要がある。同じく出力信号であるRTSは、使っていないのかな。
rubyからだと、serialportを使えば、これらの信号を扱うことができるはずである。今考えているのは、arduinoが重い処理をしているときに、その状態をこれらのピンに与えておいて、PCからはそのピンの状態を見て、処理が終わってから、アクセスするという使い方が出来ないかというものである。
Rで式量計算
元素記号処理と原子量抽出
最近は必要なデータ処理の多くの部分をrubyでやっている。しかし、様々なデータ処理を行う上で、rubyには二つの欠点があると思う。一つは配列同士の四則演算などが面倒である点で、もう一つはすぐにグラフが書けない点である。配列にもいくつかの演算が定義されているが、+は配列を結合だし、*は繰り返しだし、通常の四則演算では無い。mapをつかってゴリゴリ書くか、Vectorを変換すれば、この問題は一部解決する。しかし、グラフを書くことは出来ない。というわけで、今回はRでデータ処理を行うことにした。 Rのスキルも少しは上がってきたので、主要なデータ処理の部分は無事に書き終えた。計算には式量の値が必要なのだが、式量は手で入力している。できれば化学式から式量を自動で計算するようにしたいというのが、次の課題である。rubyを使って式量を計算するプログラムは随分前に書いて、よく使っている。これをRで書くに当たって、二つのプロセスが必要になる。一つは化学式から元素記号と数字を探して取り出すところで、もう一つは元素記号を原子量に変換する部分である。
元素記号と数字を探すのには正規表現を使うのだが、gregexprを使うと、これが可能であることが分かった。しかし、gregexprは文字列の場所と長さを返すので、そこから文字列を取り出すためにsubstrを使ったり、長さを取り出すのにattrを使ったりと、文字列を取り出すまでが非常に面倒である。そこで、stringrというlibraryを使うことにした。library(stringr)としてこれを読み込むと、便利な関数が使えるようになる。最終的に使ったのがstr_match_allというもので、マッチした文字列と、括弧内の文字列を取り出してくれる。これで元素記号と数値を容易に取り出すことができた。
あとは、元素記号から原子量に変換すれば良い。原子量はファイルから読み込むが、read.tableで読み込むと、元素記号のベクトルと原子量のベクトルを合わせたdataframeとなる。ハッシュを使えれば、aw["Cl"]のように原子量を取り出せるのだが、Rではそう簡単にはいかない。まず考えた方法は、aw$V2[which(aw$V1=="Cl")]とか、subset(aw,V1=="Cl")$V2として、原子量を取り出す方法である。しかしこれだと、長い上に元素記号のベクトルを使って、原子量のベクトルを一度に取り出すということができなくなってしまう。
そこで考えたのがnamesを使う方法である。
aww<-aw$V2 names(aww)<-aw$V1
として、原子量のベクトルであるawwにnames属性をつけてやると、aww["Cl"]で原子量を取り出すことができる。さらに、aww[c("Na","Cl")]といくつかの原子量を一度に取り出すこともできる。しかし、dataframe以外にawwという余分なベクトルを作らないといけないのが欠点である。
最終的には、dataframeの列に元素記号の名前をつけると良いことが分かった。read.tableでrow.namesオプションを使うと列の名前を取り込むことができ、列の名前を使うとaw["Cl",]で原子量を取り出すことができる。カンマとかの意味がよく分かっていないが、動けば良いだろう。
そして、最終的にできた関数が次のようなものである。
library(stringr) fw<-function(fml){ aw<-read.table("formula.dat",row.names=1) el<-str_match_all(fml,"([A-Z][a-z]?)([0-9.]*)")[[1]] return(sum( aw[el[,2],] * ifelse(el[,3]=="",1,as.numeric(el[,3])) )) }
fw("H2O")などとすると、無事に原子量が計算できる。rubyに比べたら、長くなったし、書くのに苦労したが、これでまた少しRのスキルが上がっていたら良いな。
フォントの問題
中国語の周期表
私の環境のfirefoxでは、utf-8で作った中国語の周期表の104番元素以降のいくつかが表示されなかった。OSを新しくしても、残念ながらこれは変わらなかった。何かのフォントを入れる必要があるのだろうということで、fonts-arphic-ukaiとfonts-arphic-umingを入れてみた。すると、繁体字は116番までは表示できるようになった。簡体字もMt,Cnは新たに表示できるようになったが、それ以外はだめだった。fonts-cns11643-kaiとfonts-cns11643-sungも入れると、Ds,Fl,Lvも表示できるようになった。でもまだ9個も表示できない。
OSをupgradeして
不具合発見
昨日OSをupgradeしてDebianのstretchにした。特に問題なく使っていたのだが、ちょっとした問題が発覚した。
今回のupgradeでは、homeをすべて引き継いでいるので、個人の設定ファイルもそのまま使っている。そのことは、メールなどの設定をし直さなくても良いという意味では利点である。しかし、新しい環境用に更新されないという問題も抱えているように思う。
また、新たに発見したバグとしては、lxterminalがlxpanelから起動できないという点がある。何年か前に、そういうバグが報告されているのだが、それと関係あるのかも知れない。pcmanfmからは立ち上がるので、あまり問題は無かったが、.config/openbox/lxde-rc.xmlの中のkeybindを書き換えて、ショートカットを定義したので、それから立ち上げればlxpanelを使わなくても良くなった。
あと、これは新しいOSの問題では無いのだが、thunderbirdでmacからの添付ファイルが消えてしまう問題も見つけた。これは表示-メッセージの表示形式をプレーンテキストにしていると起こるようだ。添付ファイルが見えるように、シンプルHTMLにしておいた。
stretch
OSのupgrade
Debian stretchが出てから約三ヶ月が経過し、少し仕事も落ち着いたので、upgradeしてみた。/homeを別のパーティションにしているので、データは消えないが、念の為にbackupしてから、作業に入る。
いつもはisoをCDRに焼くが、今回は1GのUSBメモリに入れることにした。isoファイルをcpで/dev/sdbにコピーして、syncすれば準備は終わった。biosの設定をUSBからbootできるように変えて、インストール。パーティションを切るところで、ルートと/homeの設定をする以外は、特に特別なことは無い。
必要なソフトを入れたが、苦労したのはやはりプリンターだった。okiのc301dnというプリンターなのだが、hipercというdriverを使わないといけない。以前の記録を頼りにインストールした。まず、foo2zjs.tar.gzを取ってきて、展開してmakeしてmake installする。このとき、dcをインストールする必要があった。これで、cupsからppdを指定すれば無事終了。
まあ、OSをupgradeしても、背景の色が変わったぐらいで、大きな変化は感じられないけど、以前と同じような感覚で使えるのは、良いことだろう。
utf8で
新しい元素の漢字の文字コード
118までの元素名が決まってしばらくした5/9に中国語の漢字が決まったらしい。遅ればせながら、homepageを更新した。
新しい漢字もあるのだが、それに対して新しいユニコードも定義されたようだ。
今回、新しく定義されたのは、ニホニウムの簡体字とテネシンとオガネソンの漢字である。ニホニウムの漢字の予想は外れたが、あとの二つは予想通りである。ニホニウムは金偏に尔という字で鿭、テネシンは石偏に田で鿬、オガネソンは気がまえに奥で鿫である。でも、自分の環境だと新しい漢字はPCに表示出来ていない。まだフォントが無いので仕方ないが。新しいdebianだと表示できるかな。そろそろOSをupgradeしようかな。
GPIB adapter using Arduino Nano
用途限定の抵抗測定システム
arduino UNO用の電気抵抗測定シールド
電気抵抗を測定するシステムが不安定になっていたので、システムの更新を計画している。そのシステムは、限られた用途にしか使わないので、1ミリオーム程度から1オーム程度まで測定できれば良い。これまでは、GPIBで電源とデジボルを制御して測定していたが、抵抗の値が限定されるのであれば、安価なICを組み合わせれば、ほぼ同等のシステムを構築できるのでは無いかと考えられる。
そこで、計装アンプとADコンバーターとarduino UNOを使って、抵抗測定システムを作ることにした。仕様としては、白金抵抗温度計以外に4つの試料を同時に測定できるようにした。arduinoのピンから供給する0Vと5Vを使って、抵抗と直列に繋いだ試料に電流を流す。電流は標準抵抗にかかっている電圧から求め、それと試料にかかっている電圧から、抵抗が計算できる。熱起電力を打ち消すためには、arduinoのピンの電圧を反転させれば良い。
ADコンバーターとしては、MCP3425を用いた。このICは、プラスマイナスの電圧をそれぞれ15bitで読み取ることが出来、2/4/8倍のアンプも内蔵しているので、ダイナミックレンジは18bitと言える。温度計を測るには十分であるが、試料には5mA程度の電流を流すことにすると、電圧が小さすぎるので、計測アンプで増幅する必要がある。計装アンプはLT1167を使って200倍程度の増幅することにした。
最終的には、MCP3425を10個とLT1167を4個使って、arduinoで4つの試料を同時に測定できるシステムが完成した。測定時間も片側0.5秒ぐらいで測定しても、ノイズはそれほど大きくなかったので、1秒程度で測定ができる。まだ、試運転の段階で、本格稼働はしていないが、予定程度の性能を持つシステムができた気がする。
シリアルをRで使ってみた
Rでarduino
arduinoとシリアルで通信するときに、その結果をグラフをにしたかったので、Rを使ってみた。少し検索してみたが、あまり情報が見つからなかったので、手探りでやってみた。まず、fileコマンドで/dev/ttyUSB0を開けて、読んだり書いたりしてみたら、多少は動くことが分かった。しかし、読むときに、最後まで読んでしまうと、それ以上読み込めなくなることが分かった。そこで、開いて読んで閉じるということを繰り返すことによって、やりたいことができることを確認したのだが、しばしばエラーが出てしまう。手でコマンドを打つと動くのだけど、コードにすると、エラーがでる。でも、それなりに動くからいいか。必ずしも必要かどうかは不明だが、適宜sleepを入れて、結果として以下のようなコードになった。もちろん、読み込んだデータの処理もしないといけないが、それは省略している。
while(TRUE){ f<-file("/dev/ttyUSB0","r+") Sys.sleep(0.1) cat("G0000\n",file=f) Sys.sleep(0.1) d<-scan(f,quiet=TRUE) Sys.sleep(0.1) close(f) Sys.sleep(1) }
形式によるコマンドの違い
Rのグラフのセーブ
Rで作ったグラフを画像ファイルにセーブするときには、ファイル形式によって、コマンドが違う例えば、epsやpdfの場合には、
dev.copy2eps(file="temp.eps") dev.copy2pdf(file="temp.pdf")
とすると表示されているグラフがセーブできる。幅や高さも表示されている通りになる。具体的に指定するためには、グラフを書く前に、X11(width=6,height=4)として、指定すれば良い。ちなみに単位はインチである。一方pngやjpegの場合には、幅や高さのdefault値が四角くなっているらしく、表示されているグラフと、セーフされたグラフの形が違ってくる。 これを指定するためには、以下のように解像度をdpi単位で、幅と高さをpoint単位で指定する必要がある。
dev.copy(png,file="temp.png",width=72*6,height=72*4,res=72);dev.off() dev.copy(jpeg,file="temp.jpg",width=72*6,height=72*4,res=72);dev.off()
ドットで構成された図の形式だと仕方ないのかも知れないが、面倒だ。