Gainerは設定にもよるが 4ないし8本のアナログ出力(PWM)を使うことが出来る。前に作成した power gainer は電源にもよるがトランジスタアレイにより小型のモータを回転させるには十分な電力を供給することができる。そこで、前からやってみたかったアンビエントディスプレイである「かざぐるま」を作ってみた。
これは MITのメディアラボで行われているタンジブルコンピューティングの象徴的なアンビエントデバイスの一つである。(詳しくは Media LabのTangible Media Group を参照。) 使ったのは前に作成したTD62083をワンボードに組み込んだGainer(Power gainer)とタミヤのプーリー基本キットである。これらをささえる土台となっているのは、100円ショップで買ってきたアクリルのメニュー立てだ。プラスチックのプーリーをゴムベルト(ゴムバンド)で回転させるプーリーキットは回転時に音がほとんどしないので、ギアボックスと違い常時動かしておくアンビエントディスプレイに適している。これに、ケント紙で作った風車を両面テープで貼付けてハードウェアのほうは完成である。
gainerのconfiguration3ならばPWM出力が8ch仕様ということで作成した風車のセットを同時に8つコントロールできるが、今回はサンプルということもあり1つの風車だけで満足しておくこととする。8ch同時で動かすにはUSBに寄生するだけではなくターゲットボードにACアダプタ等の外部電源が必要だろう。
このgainerをコントロールするプログラムはまず、テスト用ということで簡単なものを用意した。マウスカーソルを動かすとそれに従ってアナログ値が変化するものだ。これで、ウインドウ上をマウスを左右に動かすだけで回転を変化させることが出来るので動作確認には十分だろう。このプログラムはPWMで動かすデバイスの試験にいつも使っているものでもある。
以上のように風車は簡単に動くところまではきたのだが、ひとつ大きな問題が残ってしまった。ほとんど動いていないときもピーピーとモーターから音がする。これは Gainerの PWMの周波数が1KHzであるため、 1KHz周期でモータが振動してしまっている音であり、PWMでモータを動かす場合に起きる現象だ。このノイズを解決するためにはモータを駆動するPWMの周期を25KHz以上に上げる方法がよく使われる。こうなると、モーターの振動音が超音波の領域に入るため人間には聞こえなくなるのである。もちろんノイズがなくなるわけではないので、コウモリやイルカには迷惑なのかもしれないが、そこは気にしないことにして、ファームウェアを改造しPWMの周波数を上げる対策をとることとした。
(つづく)
PWMテスターのソースコードは以下のとおり。
----------
import processing.gainer.*;
Gainer gainer ;
void setup() {
size(500,100) ;
gainer = new Gainer(this) ;
}
void draw() {
int i ;
background(mouseX/4) ;
for ( i = 0; i<500;i+=100) {
stroke(255,0,0) ;
line(i ,0,i,100) ;
}
gainer.analogOutput(1,mouseX/2) ;
stroke(0,0,255);
line(mouseX,0,mouseX,100) ;
println("NOW: " + mouseX/2 + "*" ) ;
}
----------
2008年6月25日水曜日
gainer clone で「かざぐるま」あるいは PWMによるモーターの駆動
ラベル: gainer, Processing, 作ってみた
2008年6月24日火曜日
Processingでtwitterと http認証 (basic auth)
Processingをつかって、httpをしゃべらせることは難しくはない。ただ通信してページを取ってくるだけならば、loadStrings() の引数にURLを指定してやれば、自動的にJavaのURLクラスを使ってStringsの配列として格納できる。これをつかって、twitterのデータを読み込もうとおもったのだが、twitterではbasic authを使わなければ自分のfriends timelineを取り出すことが出来ない。そこで basic authを processingでやってる例をさがしたのだが、発見できなかったので生のjavaでのbasic authの方法をそのまま取り込んで実現してみた。
さまざまなページによると javaでのhttp認証では java.net.authenticator とjava.net.PasswordAuthentication の2つのクラスを使い、Authenticator クラスを継承した認証クラスを作ってハンドラを設定する、というのが正解らしい。つまり、以下のようなコードとなるわけだ。
import java.net.Authenticator;
import java.net.PasswordAuthentication;
//public
class BasicAuth extends java.net.Authenticator{
private String user;
private String pass;
public BasicAuth(String user, String pass)
{
this.user = user;
this.pass = pass;
}
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user,pass.toCharArray());
}
}
このクラスの利用方法は、user名とpasswordを設定して作成したクラスのインスタンスを生成し、そのあとで、Authenticator の setDefaultを呼び出す。前処理としてこの作業を行うと以降の http通信で認証が必要とされる場合には設定した情報をベースに自動的に認証が行われる。これをそのまま、processingに追加して使った。Processingは基本的にjavaそのものなので、このような場合の拡張は非常に簡単ですばらしい。
本当はpackage化してライブラリとするといいのだろうがそれはまた今後の課題ということにしておこう。
さて、現実にtwitterの出力するXMLの解析には、simlpeMLというライブラリを使うことにした。simpleMLはdaniel shiffman(http://www.shiffman.net/) の開発したライブラリであり彼のページからダウンロードできる。loadStrings()を使うよりもよい点は、後で XMLライブラリを使ってエレメントを取り出すよりも簡単なことと thread をつかって非同期にhttpリクエストを発生させて、ページを取得できたときにイベントを発生させることが出来る点である。とくに後者は、一定時間ごとにページを取得して書き換えるような動作を行いたい場合には、非常に有効であろう。
timelineの twitterAPI呼び出しを行うにはBasic認証付きでAPIで定められたURLを呼びだせばよい。受信形式はいろいろ見比べた結果、後処理がもっともやりやすそうなRSS形式を指定した。これらをまとめるとコードは以下のようになる。あとは、数分おきにreloadをするとか、スクロールするとかのフィーチャーを盛り込めば、twitter viewerとしての機能は十分だろう。
ちなみに書き込みは post method が必要なのだが、こちらも processingで使えるモジュールはなさそうなのとすこし複雑な処理が必要そうなのでもう一工夫必要なようなので今後の課題としておこう。
動作させるためには、フォントを作成する必要がある。Processingのメニューから Tools-->Create Fontを選択すると次のような画面が出るので Osakaフォントの16pointを指定する。日本語表示には日本語のフォントも必要なので All Fontのチェックボックスにもチェックをいれておく必要があるだろう。こうやってフォントを作成した後、コードの中の user と pass を自分のものに入れ替えれば動作させてみることができる。
--------------------------------
import simpleML.*;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
// configration
String user = "uname" ;
String pass = "xxxxx" ;
// request url
String url = "http://twitter.com/statuses/friends_timeline.rss" ;
//public
class BasicAuth extends java.net.Authenticator{
private String user;
private String pass;
public BasicAuth(String user, String pass)
{
this.user = user;
this.pass = pass;
}
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user,pass.toCharArray());
}
}
XMLRequest xmlRequest;
void setup() {
size(screen.width/2,screen.height/2);
BasicAuth tw_authenticator = new BasicAuth(user, pass);
Authenticator.setDefault(tw_authenticator);
// Creating and starting the request
xmlRequest = new XMLRequest(this,url);
xmlRequest.makeRequest();
}
void draw() {
// background(frameCount % 255);
}
// When the request is complete
void netEvent(XMLRequest ml) {
PFont fontA = loadFont("Osaka-16.vlw");
textFont(fontA, 16);
// Retrieving an array of all XML elements inside "
String[] titles = ml.getElementArray("title");
for (int i = 0; i < titles.length ; i++) {
println(titles[i].replaceAll("\n",""));
fill(10*i,0,0) ;
text( titles[i].replaceAll("\n",""),5,18*(i+1)) ;
}
}
--------------------------------
ここまで。
ラベル: Processing, twitter, 作ってみた
2008年5月22日木曜日
2008年5月15日木曜日
Xbeeの開発環境
東京ビックサイトで5/14-16で行われているESEC2008(組込システム開発技術展)にちょっとだけ用事があったので行ってきた。名前の通り、様々な組込系のボードや技術に関係しているベンダーがいろいろな製品やサービスを展示する展示会なんだが、いくつかのブースでは展示&会場限定で即売、みたいな事もやっていることがある。
2008年5月13日火曜日
OpenBSDでEmobile D02HWを使う(1)
縁あってOpenBSDの開発者の人たちと一緒にhackする機会があったので、なにかコントリビューションできることはないかなと考えたところ、OpenBSDの3Gモデムのサポートを拡張することにした。
特にD02HWは、本当の名前はE220といって世界各地で使われているメジャーなモデムなので、これがまともに使えるようになるとうれしい人がそれなりにいるだろうから、ちょうど良い。
OpenBSDもNetBSDと同様に、FreeBSD由来のUSBサブシステムを採用しているので、usbデバイスドライバは大きな差異は存在しない。NetBSD用につくったuhmodem(4)をそのまま移植するという手もあったのだけど、OpenBSDにはHSDPAモデム用のドライバとしてumsm(4)がすでに存在していたので、それを拡張する形で実装してみることにした。
umsm(4)(拡張前)
dev/usb/umsm.c(rev.1.21)を眺めてみると、非常にシンプルなドライバになっていた。具体的に言うと、
struct ucom_methods umsm_methods = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
となっていた。struct ucom_methods は、上位ドライバとなるucom(4)のopen/closeなどの各処理におけるデバイス依存コードへの関数ポインタを渡すための構造体なので、この状態ではシリアルに関する処理はucomでのデフォルト動作だけで実行されることを意味している。
どうしてこれで他のドライバが動作しているのだろうか?と「???」と思いながらざっくりとコードを追ってみたところ、シリアルデバイスのinterrupt endpointに関する処理がざっくりと抜け落ちていることに気がついた。単なるin/out endpointを処理するだけなら、確かにucom(4)における特別な処理は必要ないが、モデムで通信を行う際には自分から始めるだけではなく割り込み処理が必要である。
近くにいたOpenBSD開発者に聞いてみたら「おれが使っているE220で昔だれかが作ったパッチで試した見たところ、たしかにPPPまでは張れることもあるがうまく動かなかった。つながるけど切れたり通信できなかったりしてね。それから使ってない」と言われた。さもありなん、ということでinterrupt endpointの処理を拡張するところから始めることにする。D02HW(E220)以外でも役にたつだろう。
interrupt endpoint処理の追加
endpointの割り当て処理はumsm_attach()の中で行われる。data用のbulk in/out endpointしか処理していなかった部分を、以下のように変更する。また、struct umsm_softcにもinterrupt endpoint周りの状態を保持するための変数を拡張しておく。
if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
sc->sc_intr_number = ed->bEndpointAddress;
sc->sc_isize = UGETW(ed->wMaxPacketSize);
DPRINTF(("%s: find interrupt endpoint for %s\n",
__func__, sc->sc_dev.dv_xname));
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
uca.bulkin = ed->bEndpointAddress;
else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
uca.bulkout = ed->bEndpointAddress;
これで、interrupt endpointを持っているinterfaceがあったら、interrupt endpointを正しく扱うための準備ができる。
次に、ucomをopenしたときに検出したinterrupt endpointをucom割り込みとして利用するためのコードを追加しなければならない。まずucomをopenしたときにusb的にinterrupt endpointを登録するコード(usbd_open_pipe_intr()を呼ぶ)と、closeしたときに後始末(usbd_about_pipe() & usbd_close_pipe()を呼ぶ)をするデバイス依存の関数を追加する。それぞれubsa(4)から持ってきて、umsm_open(), umsm_close()ということにしておく。ucomがopen/closeされるタイミングで呼ばれるデバイス依存関数は、前述のstruct ucom_methodsで指定しておけばよい。
さらに割り込み発生時に呼び出されるデバイス依存関数とその補助関数として、同じくubsa(4)からumsm_intr(), umsm_get_status()を持ってくる。同様にstruct ucom_methodsに指定する。
これで、interrupt endpoint周りの処理は完了。普通のHSDPAモデムのDoCoMo A2502をつなげて試してPPPセッションが正しく張れるようになっていることを確認。とりあえずここまでで半分くらい終了。
ここまでのコードの差分は、OpenBSD CVSwebで確認できる。
次回のエントリーでは、D02HWのモード遷移のための関数の統合について書く予定。
2008年5月12日月曜日
2008年4月28日月曜日
PSoC書き込み器またまたあらわる



ということで、ジャンパピンがでっぱってケースに入らないことがあるので、