8 ProcessingでArduinoの入力を処理 1[Binary]
Serial Call Response
				今回は、コール・アンド・レスポンス(ハンドシェイク)方式を使用したArduinoボードからコンピューターへのマルチバイト通信を紹介します。
				
				このスケッチでは、Arduinoが、起動時にASCII 'A'(値65)を送信し、コンピューターからシリアル応答があるまで 'A' 送信を繰り返します。応答があると、ジョイスティクからの3つのセンサー値(Xボリューム、Yボリューム、スティクSW)をそれぞれ1バイトにまとめ計 3 バイトとして送信し、コンピューターからの別の応答が来るのを待ちます。
Macの画面には、黒のウインドが現れ中央に白いボールが表示されています。接続したジョイスティックを動かすと、白いボールがスティックの動きと同じ動きをします。ジョイスティクを押し込むとスティク内のSWがONになり白いボールは見えなくなります。
				
必要なハードウエア
この記事を実行するのに必要なハードウエアは、以下の通りで SW付きジョイスティクを Arduino に接続します。
- Arduino
 - ジョイスティク
 - USBケーブル
 - Mac
 
3つのセンサー信号を発生させるのにジョイスティクを使用しましたが、電圧が 0 から 5vの範囲で変化するものなら、どのようなものでも接続が可能です。例えば、単にポテンショメータを取り付けても十分にこのスケッチの動作確認が可能です。
動作確認
動作確認は以下の手順で行います。
- Arduino にジョイスティクを取り付ける
 - Arduino IDE にスケッチを書く
 - Arduinoボードにスケッチ書き込む
 - Processing IDE にスケッチを書く
 - Processing を実行する
 
1. Arduino に ジョイスティックを取り付ける
Arduino に ジョイスティクを接続します。
配線のための回路図を以下に示します。
				
2. Arduino IDE にスケッチを書く
Arduino IDE に組み込まれているサンプルスケッチを利用します。
Arduino IDE のメニューから
ファイル -> スケッチ例 -> 4.Communicattion -> SerialCallResponse
と選択してください。読み込まれたスケッチには、説明が多く記入され、また、Processing のプログラムコードもコメント欄に書かれているため長いスケッチになっています。実際に Arduino に書き込まれるコードだけを取り出すと理解しやすくなります。
重要:ジョイスティックのSWは Arduino 内部でプルアップする必要があります。サンプルスケッチは、Arduino 内部でプルアップされていないため、 setup()関数内のpinMode()関数を INPUT_PULLUP に変更します。
				不要部分を削除し、コメントを日本語に翻訳したスケッチを参考のため以下に掲載します。
// Serial Call and Response
int firstSensor = 0;    // N01 アナログ・センサー
int secondSensor = 0;   // N02 アナログ・センサー
int thirdSensor = 0;    // デジタル・センサー
int inByte = 0;         // 受信したシリアルByte
void setup() {
  Serial.begin(9600);  // シリアルポート初期化 9600 bps:
  while (!Serial) {    // シリアアルポートの接続を待つ
    ;
  }
  pinMode(2, INPUT_PULLUP);   // pin 2 プルアップで初期化
  establishContact();         // Byteデータを送り接続の確立を待つ
}
void loop() {
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {   // データ受信したら
    // get incoming byte:
    inByte = Serial.read();  // 受信データをから読みする
    // アナログセンサの出力を1/4して 0-255 の値として読み込む
    firstSensor = analogRead(A0) / 4; // No1センサーの読み込
    delay(10);                        // ADC 安定化のため 10ms待つ
    secondSensor = analogRead(1) / 4; // No2センサーの読み込
    // デジタルセンサーは 0 or 255 として取り込む
    thirdSensor = map(digitalRead(2), 0, 1, 0, 255);
    // 取り込んだ値をByteデータ(0ー255)のまま送信する
    Serial.write(firstSensor);
    Serial.write(secondSensor);
    Serial.write(thirdSensor);
  }
}
// シリアアルポートの接続を待つ
// なんらかのデータを受信するまで、何度でも'A' を送信し続ける
void establishContact() {
  while (Serial.available() <= 0) {   // 受信しなければ
    Serial.print('A');                //  'A' を送信
    delay(300);                       //   300ms待つ
  }
}
3. Arduinoボードにスケッチ書き込む
Arduino IDE にスケッチが読み込まれたら、➡︎ ボタンをクリックして Arduinoマイコンボードにスケッチを書き込みます。
4. Processing IDE にスケッチを書く
Arduino IDE に読み込んだスケッチの後半に、コメントとして Processing IDE 用のスケッチが書かれています。その部分をコピーして Processing IDE にペーストしても構いませんが、以下に該当部分を抜き出して英語のコメントを日本語化したスケッチを示しますので、こちらを利用してください。
// Serial Call and Response
import processing.serial.*;
int bgcolor;           // 背景色
int fgcolor;           // 描画色
Serial myPort;                       // シリアルポート
int[] serialInArray = new int[3];    // 受信データ
int serialCount = 0;                 // 受信データの順番
int xpos, ypos;                      // ボールの座標
boolean firstContact = false;        // Arduino と接続済み か
void setup() {
  size(256, 256);  // ウインドのサイズ
  noStroke();      // 以降、枠線はなし
  // ボールをウインドの中央にセット
  xpos = width / 2;
  ypos = height / 2;
  // 接続しているシリアルポートをリストする
  printArray(Serial.list());
  // このスケッチでは、リストの2番のポートを使用します。
  // ユーザーがArduinoを接続している番号に置き換えてください。
  // 最後のパラメータ(e.g. 9600)は通信速度を示します。
  String portName = Serial.list()[2];
  myPort = new Serial(this, portName, 9600);
}
void draw() {
  background(bgcolor);
  fill(fgcolor);
  ellipse(xpos, ypos, 20, 20);  // ボールを描く
}
void serialEvent(Serial myPort) {
  // シリアルポートから1バイト読み込みます
  int inByte = myPort.read();
  // もしここれが初めての受信であり、その値が 'A' なら、
  // シリアルバッファーをクリアし、Arduino と接続できたことを記録します。
  // それ以外なら、受信データを配列に保存します。
  if (firstContact == false) {
    if (inByte == 'A') {
      myPort.clear();          // シリアルバッファーをクリア
      firstContact = true;     // Arduino との接続 を記録
      myPort.write('A');       // 次のデータを要求
    }
  }
  else {
    // 配列に受信データを保存する
    serialInArray[serialCount] = inByte;
    serialCount++;
    // 3ハイトのデータを受信し終えたら
    if (serialCount > 2 ) {
      xpos = serialInArray[0];
      ypos = serialInArray[1];
      fgcolor = serialInArray[2];
      // 値をプリント (デバッグ用 ):
      println(xpos + "\t" + ypos + "\t" + fgcolor);
      myPort.write('A');    // 次のデータ要求するために'A' 送信
      serialCount = 0;      // 受信データ数のクリア
    }
  }
}
5. Processing を実行する
Processing IDE にスケッチを書き込んだら、▶︎ ボタンをクリックして Processingを実行します。
実行されると、Processing IDE のコンソール部に、 Maに接続されているポートの情報が表示されます。
さらに、Mac画面ほぼ中央に、黒のウインドが表示され、接続したジョイスティックを鵜がかすと、白いボールがスティックの動きと同じ動きをします。ジョイスティクを押し込むと白いボールが見えなくなります。
				
[トラブルシュート] 白いボールが表示されない時
動作しない多くの理由が、Arduino 接続ポートの誤指示です。
Processing IDE のコンソール部を確認し、"/dev/cu.usbmodem14xxx" と表示されている番号と、上記 Processingスケッチの
String portName = Serial.list()[2];
の list( ) インデックス番号と一致しているか、確認してください。
- 参考
Maに接続されているポートの情報には、/dev/cu と /dev/tty 2種類がが表示されます。歴史的に、tty (TeleTYpe)デバイスは受信、cu (Call Up)デバイスはモデムなどの送信に利用されてきた経緯があるため、2種類のデバイスが用意されています。
なお、どちらのデバイスを使用しても Arduino は正常に動作しました。 
次回は同じ働きをするサンプルスケッチですが、今回のようなバイナリ値でセンサーの読み取り値を送信する代わりに、ASCII文字列にエンコードして送信する方法を紹介します。