コミュニケーション チュートリアル 2:
シリアル・コミュニケーション

イントロダクション

このチュートリアルでは、Max の中でのシリアル通信の取り扱いをテーマにしています。多くの外部機器はコンピュータとの通信を行なう場合にシリアルプロトコル(例えば RS232 や Bluetooth など)を使用します。そして、シリアルストリームはコンピュータ間の挟帯域下の通信(ダイヤルアップ・インターネット環境を考えて下さい)であっても使用することができます。プロレベルのビデオミキサやDVDプレーヤ、劇場の照明システムなどはシリアルインターフェイスを使用してコマンドの受信を行ないます。また、フィジカル・コンピューティングの世界で用いられるマイクロコントローラ・システムでは、センサからコンピュータへのデータ送信はシリアル通信に依存しています。

このチュートリアルでは、シリアル通信の例として、非常にポピュラーなエレクトリック・プロトタイピング・プラットフォームである Arduino を使います。これは、Cに似たスタイルの言語でプログラムされるプロトタイピング・ボードに小さなマイクロコントローラを搭載したものです。Arduino はUSB 上のシリアルラインを使ってホストコンピュータに通信を行なうことができます。たとえArduino をお持ちでないとしても、このチュートリアルで示すような原則を踏まえておけば、他のシリアルデバイスとの通信が必要な場合にも応用できるはずです。

Arduino のコード

Max パッチを見る前に、このチュートリアルで使用している Auduino 用のプログラムを見ておきましょう。この例では、Arduino はセンサ情報の読み込みや、その他思いつくようないかなる動作も行ないません。単にコンピュータからの入力を待ち、入力の後にシリアルな数値のフィードバックを開始するだけです。Arduino のコードは次のようなものです。

// Arduino Serial Tester // rld, cycling'74, 3.2008

long randomvalue = 0; // ランダムな値 long countervalue = 0; // カウンタの値 int serialvalue; // シリアル入力の値 int started = 0; // シリアル入力を受信しているかどうかを示すフラグ

void setup() { Serial.begin(9600); // arduinoのシリアルポートをオープン }

void loop() { if(Serial.available()) // バッファにシリアルデータがあるかどうかをチェック { serialvalue = Serial.read(); // シリアルデータをバイト単位で読み込む started = 1; // スタートフラグをオンにセット }
if(started) // シリアルデータが受信された場合のループ処理 { randomvalue = random(1000); // 新しい乱数値を取得 Serial.print(countervalue); // カウンタを表示 Serial.print(" "); // スペースを表示 Serial.print(randomvalue); // 乱数値を表示 Serial.print(" "); //スペースを表示 Serial.print(serialvalue); // 受信したシリアル値のエコー出力 Serial.println(); // 改行処理 countervalue = (countervalue+1)%1000; // カウンタのインクリメント delay(100); // 停止
} }

Auduino のプログラミング言語の詳細を知らなくても、各行のコメントを見ればどのような処理が行なわれているかわかると思います。マイクロコントローラは自分自身を初期化し、9600ボーで動作しているシリアルポートを開きます。9600ボーはMaxパッチと通信を行なうときの通信速度です。その後、ループに入ります。このループでは何らかのデータが送信されているかどうかを確認するためのチェックを行ないます。データが送信されていた場合には、コンピュータに数値を返すストリーミングを開始します。ここでは、0 から 1000 まで繰り返しカウントする数値、ランダムな値(同じ範囲の値)、最後にチップに送信した値が生成されます。この3つの値は(ターミナルと同様に)それぞれ1行で、連続して表示されます。

serial オブジェクト

チュートリアルを開いて下さい。チュートリアルを見て下さい。パッチの上部には serial オブジェクトがあり、その出力をサポートするオブジェクトがいくつかあります。これらは、結果として lcd を操作し、Ardino から送られるデータのグラフを描画しています。Max の serial オブジェクトは、他のカテゴリ(MIDIやHID)として扱うための特定のドライバを持たないシリアルデバイスと通信を行なう場合に使用されます。このような汎用デバイスは、serial オブジェクトの第1アーギュメントで定義されるシリアルポートを介してMaxとの通信を行ないます。Max では、これらのポートを文字(a,b など)で表します。パッチの上部にある print というメッセージボックスをクリックして下さい。コンピュータで利用できるシリアルポートが、割り当てられた文字と共にMaxウィンドウに表示されます。コンピュータで使用されている他のシリアルデバイスと共に、Arduino が表示されるはずです。必要であれば、serial オブジェクトのアーギュメントの文字を変更することができます。そのためには、オブジェクトをアンロックして、オブジェクトのアーギュメントを入力し直して下さい。

シリアルポートの設定以外にも、serial オブジェクトに対して、通信プロトコルを設定するためのアーギュメントをいくつか追加することができます。serial オブジェクトの第2アーギュメントはボー・レートを設定します。これは、Arduino が使用するボー・レートに合わせる必要があります。Arduino に対して9600 ボーでデータを送信するよう指定してあるため、このserial オブジェクトにも同じ値をアーギュメントとして指定しています。serial オブジェクトに対し、さらにアーギュメントを追加して、データビット数、ストップビット、通信を行なうデバイスのパリティ(偶数パリティ、あるいは奇数パリティ)を指定することができます。Arduino は極めて標準的なデバイスであるため、デフォルトの設定で動作します。

データのポーリングと送信

serial オブジェクトはシリアルデータの送信、受信を行なうことができます。serial オブジェクトは、インレットで1バイト(0 から 255 までの整数値)単位でデータを取得し、これを選択されたシリアルポートに送信します。このバイト単位のデータは、コマンドの値を表したり、ASCII(key オブジェクトから出力される数値と同じもの)に変換したりすることができます。データを受信する場合には、serial オブジェクトは(mousestate と同様に)ポーリングを行なわれなければなりません。serial オブジェクトは、 bang を受信すると待機しているシリアルメッセージの内部のバッファを空にし、そのメッセージを連続してアウトレットから(バイト単位のデータとして)送信します。Arduino がチュートリアルで示された(上記のような)プログラムをロードしていて、コンピュータに接続されている場合、serialオブジェクトが正しいポートに設定されていれば、通信を行なうことができるはずです。toggle ボックスをクリックしてmetro オブジェクトをオンにして下さい。serial オブジェクトのアウトレットに接続されたナンバーボックスを見ても何も変化は現れません。これは、Arduino のプログラムコードが、最初にコンピュータからマイクロコントローラへ通信が行なわれるのを待ち受けているためです。

serialオブジェクトに接続されたナンバーボックスに10 という数値を入力して、[return] キーを押して下さい。serialオブジェクトがバイトを正しく送信していれば、オブジェクトから数値が出力されることがわかるはずです。1 と表示された toggle をオンにして、「生の」シリアルデータを Max ウィンドウに表示させて下さい。

データのフォーマット

serial オブジェクトから「生のまま」出力され、Max ウィンドウに表示される数値が、整合性を持たないように思えることに気がつくでしょう。これは、Arduino が値を ASCII として送信しているためです。これは、ちょうどキーボードでタイプした場合と同じです。そのため、数値 15 はASCII値49(文字 "1")の後にASCII値53(文字 "5")が続いたものになります。3つの値の間のスペースはASCIIのスペース文字(32)で表されます。そして、1組になった3つの値は、それぞれキャリッジリターンとラインフィード(ASCII 13 の後に 10が続いたもの)によって終わっています。これらの値を Max で使用する場合には、最初にまとめてグループ化し、その後ASCII から人間が読めるような文字列に変換します。

訳注:キャリッジリターン(CR)は行頭への復帰、ラインフィード(LF)は行送り(改行)を表すコードです。

1 と表示された toggle のチェックを外し、 2 と表示された toggle をチェックして下さい。これにより、パッチの中のzl group オブジェクトの出力が表示されます。zl オブジェクトは一連のASCII値を受信し、それらをリストとしてグループ化します。zl の上にあるselect オブジェクトは、13(キャリッジリターン)を受信するとzlから強制的にリストを出力させます(同時にzl の内容をクリアします)。加えて、ストリームからラインフィード(ASCII 10)文字を取り除くことも行なっています。select オブジェクトの右アウトレットからは、オブジェクトによって選択されたもの以外の値が出力されるため、13と10 以外の値はzl に流し込まれます。結果として、Max ウィンドウには、スペース文字(ASCII値32)で区切られた3つの値を表すASCII値のリストが表示されます。

2と表示された toggle のチェックを外して、3 と表示された toggle をオンにして下さい。これにより、itoa オブジェクトからの出力が表示されます。このオブジェクトはグループ化されたリストを受け取り、その整数値を該当するASCII文字に変換します。結果として、Max ウィンドウには、Arduino のプログラムコードによって与えられたデータが、最終的に意味を持った値として表示されます。ここでは、0から1000 までのカウントの後にランダムな値が続き、さらに値10(私たちが最初にマイクロコントローラに送信した値)が続きます。

itoa オブジェクトはMaxシンボルを生成します。このシンボルはデバッグ用として見ることはできますが、このパッチで本当に必要としているものではありません。私たちはこのメッセージを3つの整数として読むことができますが、unpackなどのオブジェクトはそのようには認識しません。fromsymbol オブジェクトはシンボルを解析し、スペースにもとづいて様々なデータ型に分割します。この結果、シンボルは3つの整数のリストに変換され、unpack オブジェクトによって分離することができるようになります。unpack オブジェクトの出力を表示するナンバーボックスが正しい値を表示している点に注目して下さい。最も上にあるナンバーボックスを再び変更すると、それによりserial オブジェクトから出力される第3の値が更新されることがわかるでしょう。

パッチの描画部分に目を移して、その動作を見て下さい。これは、多くの lcd を使った例と同様に、serial オブジェクトの出力を単純にビジュアライズしたものです。ここでは、カウンタ(xの値)、乱数(yの値)、エコーバックされたバイト値(色の値)に基づいてグラフを描画しています。これらの値は、どのような動作をコントロールする場合にでも、簡単に適用することができます。

結び

Max の serial オブジェクトは、Max 環境の中で標準のシリアルデバイスと送受信を行なうための機能を提供してくれます。このオブジェクトはデータを1つのバイト単位で送信、受信します。zl、itoa、 fromsymbol のようなオブジェクトは、それらのデータすべてを意味あるものにするために使用することができます。

参照

serial シリアルポートやカードからの文字を送信、受信することができます。
itoa 整数値を ASCII 文字に変換します。
fromsymbol シンボルを個別の数値やメッセージに変換します。