の画面タッチでLチカ - OSC


iPhoneをタッチしたら、Lチカするプログラムを作成します。

構成
iPhone ->(OSC)-> Max ->(シリアル通信)->Arduino->Lチカ

通信メッセージ
iPhone -> "touch/panel/down" -> Max -> "down" -> 1 -> Arduino -> LED点灯
iPhone -> "touch/panel/up" -> Max -> "up"-> 0 -> Arduino -> LED消灯

環境
of_v0.9.3_ios_release
Xcode v7.3.1
Max/Msp 7
iPhone 6
Arduino v1.69

openFrameworks

まずはofから。iPhoneのプログラムを記述します。
projectGeneratorで、Addonsに ofxOsc を入れてプロジェクトを作成します。

作成できたらofApp.hを以下のようにします。

ofApp.h
#pragma once

#include "ofxiOS.h"
#include "ofxOsc.h"

//#define HOST "localhost"
#define HOST "192.168.100.101"
#define PORT 12345 

class ofApp : public ofxiOSApp {

    public:
        void setup();
        void update();
        void draw();
        void exit();

        void touchDown(ofTouchEventArgs & touch);
        void touchMoved(ofTouchEventArgs & touch);
        void touchUp(ofTouchEventArgs & touch);
        void touchDoubleTap(ofTouchEventArgs & touch);
        void touchCancelled(ofTouchEventArgs & touch);

        void lostFocus();
        void gotFocus();
        void gotMemoryWarning();
        void deviceOrientationChanged(int newOrientation);

    private:
        ofxOscSender sender;
        bool touch_down;
};

#define HOSTは使用しているネットワークを指します。
MacからiPhoneのシュミレーターで確認する場合、IPアドレスか"localhost"で構いません。
実機のiPhoneからであれば、IPアドレスを記述します。

また、PORTは1024~65535番の範囲で記述します。
0~1023番はサーバのアプリケーションで使用するポートとして登録されているので、被らないようにします。

ofxOscSender sender;はOSCメッセージを送信するインスタンス、bool touch_downはiPhoneをタッチしたか否かを判定するために使用します。


続いてofApp.mm。
iPhoneをタッチした際にOSCメッセージが送られるようにします。
特に記述していないところは省略しました。

ofApp.mm
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){

    ofBackground(0, 0, 0);
    sender.setup(HOST,PORT);
    ofSetFrameRate(10);

    touch_down = false;
}

//--------------------------------------------------------------
void ofApp::draw(){

    ofSetColor(255, 255, 255);
    if(touch_down == true){
        ofSetColor(255,255,255);
        ofDrawCircle(ofGetWidth()/2, ofGetHeight()/2, 10);
    }
}

//--------------------------------------------------------------
void ofApp::touchDown(ofTouchEventArgs & touch){
    ofxOscMessage m;
    m.setAddress("touch/panel");
    m.addStringArg("down");
    sender.sendMessage(m);

    touch_down = true;
}

//--------------------------------------------------------------
void ofApp::touchUp(ofTouchEventArgs & touch){
    ofxOscMessage m;
    m.setAddress("touch/panel");
    m.addStringArg("up");
    sender.sendMessage(m);

    touch_down = false;
}

sender.sendMessage(m);によってm.setAddress();m.addStringArg();
引数がMaxに送られます。

今回はiPhoneの画面に指を置いた際に"touch/panel/up"が送信され、画面から指を離した際に"touch/panel/down"が送信されます。

また視覚的にタッチしているか否かが分かるようにするため、タッチをした際に画面中央に円が描かれるようにしています。

Max

Maxのパッチです。

udpreceive
udpreceiveの引数にofで設定したポート番号を記述します。

route
routeは「routeのインレットの最初の引数」と「routeの引数」が合致した場合、合致した次のインレットの引数の値を出力します。(説明難しい)

ofから送られてくるメッセージは"touch/panel/up"もしくは"touch/panel/down"です。

"touch/panel/down"->route touch/panel/->合致->"down"
"touch/panel/up"->route touch/panel/->合致->"up"

となり、"up"もしくは"down"が出力されます。

sel
sel down upではupとdownを数値の0,1に置き換えています。
文字列だとserial: doesn't understandというエラーが出てしまうので、upやdownから数値に置き換える必要があります。

serial
serial c 9600のcはポートを、9600は通信速度を指しています。

- ポートがcの理由
serialprintメッセージを繋げます。

printをクリックすると、PCとシリアル通信が出来るデバイスの一覧がMax consoleに出力されます。

ArduinoをPCに接続しprintを押すと、私のPCでは

と出力されます。これでArduinoのportはcだとわかりました。
使用環境によって、aだったりbだったりするので確認をしましょう。

Arduino

osc_01.ino
void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {

  if(Serial.available()>0){

    int c = Serial.read();
    Serial.println(c);

    if(c == 1 ){
      digitalWrite(13,HIGH);
     }else if(c == 0){
      digitalWrite(13,LOW);
        }
    }

}

Serial.begin();の引数はMaxのserialで設定した、通信速度と同じです。

iPhoneをタッチするとMaxからは0,1の値が送信されるので、Arduinoにプログラムを書き込むことでLEDがチカチカするようになります。

コンパイルの順番によってはうまくいかなかったりしますが、Arduinoに書き込んでからMaxを立ち上げ、ofをコンパイルすると上手くいくかもしれません。

参考

openFramewoks – OSC (Open Sound Control) を利用したネットワーク連携
Port Number