報告遅れましたが、7月26日より山口情報芸術センターYCAMでオープンした、
半屋外の公園「コロガルパビリオン」の音響、照明システムを担当致しました。
http://10th.ycam.jp/term1/488/
お子様連れのかた、夏の思い出をご家族で体験して見てはいかがでしょう、是非!
技術的な事で言うとシステム全般をSuperColliderで実装しています。
フルカラーLED照明 DMX 約400ch, オーディオスピーカー14chという構成でリアルタイム制御しています。
ofxiPhone のアプリで環境設定でユーザー設定を設けたくなるときがあると思います。
これはCcocoaTouchの時と同じように、プロジェクトにSettings.bundleを追加して、testApp::setup()時にNSUserDefaultsを呼び出せばできます。
1) Settings.bundleの追加
XCodeのインスペクタでxcodeprojファイルを左クリック->New Group でSettings のようなグループを作成
作成したグループを左クリック->New File で iOS / Resource の Settings Bundle を選択してプロジェクトのディレクトリに作成
以下のように作成されるので Settings.bundle / Root.plist を編集して設定を作成する
2) Root.plist の編集
plistの編集については
iPhoneプログラミング広場 Settings Bundle サンプルプログラム
や
iPhoneアプリを「設定画面」にて設定するための手順 などを参考に。
3) NSUserDefaultsでplistを取得
o/FのtestApp::setup()時にNSUserDefaults を使ってplistの Identifier でしたキーを指定すれば取得できる。
#include "testApp.h" NSString const *portNumber;
//--------------------------------------------------------------
void testApp::setup(){
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
portNumber = [defaults stringForKey:@"portNumber"];
NSLog(@"portNumber is _________ %d" port.intValue);
} 接続先サーバの指定とかユーザーに設定を選択させるのに便利。
SuperColliderで
object.hash でそのオブジェクトの一意のハッシュ値が帰ってくる。
こんな使い方はどうだろう、例えばインスタンスメソッド内でタスクを実行する時、 他のインスタンスで上書きされるのを防ぐのに使う。
クラス宣言のインスタンスメソッド内で以下のようにハッシュ値を使ってシンボル名を作ってTdefを実行するようにする...
var taskName; taskName = ("task_"++this.hash.asString).asSymbol;
Tdef(taskName,{ "this is task".postln; }).play;
すると他のインスタンスとシンボル名かぶらずに、かつインスタンスにつき一タスクが実行される。 他にもたくさん使い道はあると思う。
前々から気になっていた ofxiPhone で Cocoa UIKit にアクセスする方法。
rootViewController になっている ofxiPhoneViewController を NavigationController に むりやりねじ込む方法をやってみた。
ofxiPhoneViewController は setup では早すぎてまだ生成されてないので、 draw の中でdispatch_once している。もっといい方法はないのかな...。
testApp.h#pragma once
#include "ofMain.h" #include "ofxiPhone.h" #include "ofxiPhoneExtras.h"
class testApp : public ofxiPhoneApp{
private: UIViewController *subViewController; UINavigationController *navigationController; 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);
}; testApp.mm
#include "testApp.h"
static dispatch_once_t onceToken;
//-------------------------------------------------------------- void testApp::setup(){ ofxAccelerometer.setup();
ofRegisterTouchEvents(this); ofxiPhoneAlerts.addListener(this); subViewController = [[UIViewController alloc] init]; subViewController.title = @"Second View Controller";
}
//-------------------------------------------------------------- void testApp::update(){
}
//-------------------------------------------------------------- void testApp::draw(){
dispatch_once(&onceToken, ^{ UIWindow * window = ofxiPhoneGetUIWindow(); UIViewController *firstViewController = ofxiPhoneGetViewController(); firstViewController.title = @"First View Controller"; window.rootViewController = subViewController; navigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController]; window.rootViewController = navigationController; dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 0.1f * NSEC_PER_SEC); dispatch_after(delay, dispatch_get_main_queue(), ^{ [[(ofxiPhoneViewController*)firstViewController glView] startAnimation]; // GLViewがstopしてしまうのでstartを少し遅れて呼ぶ }); }); ofSetColor(0, 0, 0); ofDrawBitmapString("This is ofxiPhoneGLView.. \nTouch and Push viewController", 10, ofGetHeight() / 2 - 50 );
}
//-------------------------------------------------------------- void testApp::exit(){
}
//-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs & touch){
}
//-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs & touch){
}
//-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs & touch){
/* touch window to push viewController.. */ [navigationController pushViewController:subViewController animated:YES];
}
//-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs & touch){
}
//-------------------------------------------------------------- void testApp::touchCancelled(ofTouchEventArgs & touch){
}
//-------------------------------------------------------------- void testApp::lostFocus(){
}
//-------------------------------------------------------------- void testApp::gotFocus(){
}
//-------------------------------------------------------------- void testApp::gotMemoryWarning(){
}
//-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){
}
ここに
https://github.com/moxuse/ofxiPhonePushViewControllerTest/ プロジェクトのソース上げています。 Second View Controller 以降をストーリーボードを使用するようになっています。
XBee Wi-Fi を手に入れてほったらかしにしてあったので、いい加減動かしてみる。
以前やった APIモードとADサンプリングで三軸加速度センサーを作った物を今度はWi-Fi経由で
PCに送るまでをやってみた...。
回路は以前のものと全く同じで、ボタン電池で駆動、D0~D2ピンに加速度のXYZ軸のピンをそれぞれアサインさせるもの。
XBeeはホストとして、サンプリングしたデータをアドレス指定したクライアントへUDP経由でたれ流す。
小文字が打てないのでIDやPKの設定はモデム通信用のソフトで。私は ztermを使用した。
主な設定としては..、
[ID] ネットワークのSSID: X-CTUでは大文字しか入力できなかったので、ZTermで手打ち設定。
[AH] Wi-Fiの種類: WPA2だったので2
[PK] ネットワークのパスワード: こちらも小文字が打てなかったのでZTermで手打ち。
[IP] プロトコル: UDPなので0
[DL] 送信先IP: デフォルトではローカル内でブロードキャストになっている。
[IR] XBeeのインターバルサンプル機能のサンプルレート: 0x0Aにしてみた インターバルの計算は0xFFFF [x 1 mSec] とのこと。
[AP] APIモードの設定 : 1でネーブルに。
[D0 ~ D2] i/oモード: 2でADCモードに。
うまく行けばリセット後、指定したSSIDに接続しようとして、DHCPでIPが自動で割り振られる。
ZTermでATMYコマンドなどで確認できる。
データはクライアント指定したIPへUDPで送られる。
当初SuperColliderで受けようとしたが、なんとSCLangでは 生のUDPソケット通信を受けるのができないとのこと..
OSCのパケットは受けられるが"/~"みたいに先頭がアドレスになっている物以外は"ERROR: OSC messages must have type tags"
というエラーを吐いて終わる..。なんてこった。
かろうじて送信はできるみたい。送信先をXBeeに割り振られたIP, ポート 9750( このポートが分からなかった*1)に。// SCLang Code // send raw udp to xbee wifi NetAddr("192.168.100.38",9750).sendRaw("Hello World!");
しょうがないのでProcessingで。
UDP用のエクステンションライブラリが あるので、これを使用する。
ソケットを ローカルホスト3054番( このポートも分からなかった、どこに載っていたんだ..*2[DE]設定で指定した物とは違うので注意)に。
以下Processingのコード(汚)
// Processing Code // import UDP library import hypermedia.net.*;
UDP udp;
void setup() { udp = new UDP( this, 3054 ); //port from xbee wi-fi udp.listen( true ); }
void draw() {;}
void keyPressed() {
String message = str( key );
String ip = "localhost";
int port = 9670; //port to xbee wi-fi
message = message+";\n";
udp.send( message, ip, port );
}
void receive( byte[] data, String ip, int port ) { int len = data.length; byte[] message = subset(data, 0, len);
for( int i = 0; i<len; i++ ){ if (message[i] == 0) { if (message[i + 1] == 7) println (message[i + 2] + " " + message[i + 3]+ " " + message[i + 4]+ " " + message[i + 5]+ " " + message[i + 6]+ " " + message[i + 7] ); } } }
パーズして6バイト分なにやら送られてきているのがわかる。 あとはこれを適切な値に変換してあげればいいはず。上記パーズするところ間違ってるくさい、後で直す。 と今のところはここまで。
*1 0x2616ポートDestination PortとSerial Communication Service Portのデフォルトのポートらしい。 *2 0xBEEポートといって特別なポートらしい。