今回からは、いよいよToucheセンサーを自作してタッチ検出に挑戦します。まずは、Toucheのセンサーのハードウェアを制作します。センサーが完成したら、水を入れたコップ、金属製の製品、植物など様々な物体でタッチ検出できるか試してみましょう。後半は、ソフトウェアを解析して、表示や表現の方法を変更するにはどう改造していけば良いのか考えていきます。
Toucheに必要な材料
ArduinoでToucheセンサーを自作するには以下の部品が必要となります。それぞれのパーツは、どれも入手は難しくないものです。今回はArduinoプロトシールドなどは使用せず、まずはブレッドボードで配線することにします。
Arduino
Usbケーブル(ArduinoとPCを接続)
ブレッドボード
抵抗器: 10KΩ, 1MΩ, 3.3KΩ
コンデンサー: 100pf (絶縁型ラジアルリード型積層セラミックコンデンサー100pF 50V±5%5mmなど 千石電商 、秋月電子通商 )
コンデンサー: 10nf (絶縁型ラジアルリード型積層セラミックコンデンサー0.01μF 50V±10%5mmなど 秋月電子通商 )
ダイオード: 1N4148 (汎用小信号高速スイッチング・ダイオード 1N4148 100V200mAなど 千石電商 、秋月電子通商 )
インダクター: 10mH (太陽誘電 LHLC10NB 103Jインダクタ10mH 0.14Aなど 千石電商 )
Toucheハードウェアを制作
まず、Touche for Arduinoの回路図をみてみましょう。この配線を実現するためにブレッドボードにどのようにパーツを配置して、Arduinoと結線していけば良いのか考えていきます。
この回路をブレッドボードで実現する方法はいろいろ考えられます。パズルを解くような気分で配線してみましょう。例えば先週の矢坂先生の授業では以下のような配線を紹介しました。
配線を少し簡略化した別バージョンの配線です。
これらの配線図を参考に、Toucheセンサーを自作してみましょう。
Toucheソフトウェアをダウンロード
早速、自作したToucheセンサーを試してみましょう。ソフトウェアは前回と同様下記のGithubアカウントからダウンロードして使用します。
ソフトウェアの使い方
Zipファイルをダウンロードして、まず「Arduino_sensing」フォルダ内の「Arduino_sensing.ino」プログラムをArduino.appから開いてボードに書き込みます。次に「Processing_graph」フォルダ内の「Processing_graph.pde」をProcessing.appで開き、Processingを実行してみてください。
すると、下記のような画面が表示されるはずです。
このプログラムは以下のようにして使用します。
Toucheセンサーを接続
Arduino_sensing.inoをArduinoに転送
Processing.appでProcessing_graph.pdeを開いて実行
センサーで計測された値がグラフで表示される(はず)
ジェスチャーをして、右側のボタンで登録(全部で4種類まで可能)
同じジェスチャーを再現
右側のボタンで該当するものが点灯する(はず)
様々な物体でのタッチ検出に挑戦!
次にタッチを検出する物体を用意しましょう。まずは、水を入れたペットボトルで実験してみます。容器に水を溜めて、水の中にセンサー用のワイヤーを垂らします。
物体とTouchセンサーを接続したら、Processing側のアプリProcessing_graph.pdeを起動します。
もし下記のようにグラフの反応が少ない場合は、グラフの最大値と最小値を調整します。
Processing_graph.pdeの、draw()関数内、「Print the graph」というコメントのすぐ下にある、下記のコードを調整します。
[code lang=”cpp”]
MyArduinoGraph.yMax=1000;
MyArduinoGraph.yMin=-200;
[/code]
デフォルトの状態では、最大値1000、最小値-200なので、例えばこれを最大値200、最小値-10にするのであれば、
[code lang=”cpp”]
MyArduinoGraph.yMax=100;
MyArduinoGraph.yMin=-10;
[/code]
とします。すると、表示が拡大され、はっきりとグラフの曲線が観察できます。
水を入れたペットボトルがうまくいったら、様々な物体でタッチ検出ができるか試してみましょう。例えば、水耕栽培している植物にタッチセンサーを入れてみました。
Toucheプログラムを解析する
今後はこのToucheのプログラムを利用して、作品を制作していきます。まず始めにこのToucheのProcessigのプログラムは何をしているのか、実際にソースを解析しながら理解していきましょう。
[code lang=”cpp”]
// グラフ描画のクラスのインスタンス化(初期化)
Graph MyArduinoGraph = new Graph(150, 80, 500, 300, color (200, 20, 20));
// 4つのジェスチャーを記録する配列
float[][] gesturePoints = new float[4][2];
// 現在のジェスチャーと登録したジェスチャーとの距離
float[] gestureDist = new float[4];
// それぞれのジェスチャーの名前
String[] names = {
"Nothing", "Touch", "Grab", "In water"
};
void setup() {
size(1000, 500);
// グラフのラベル設定
MyArduinoGraph.xLabel="Readnumber";
MyArduinoGraph.yLabel="Amp";
MyArduinoGraph.Title=" Graph";
noLoop();
PortSelected=4; //ポートを設定
/* ====================================================================
adjust this (0,1,2…) until the correct port is selected
In my case 2 for COM4, after I look at the Serial.list() string
println( Serial.list() );
[0] "COM1"
[1] "COM2"
[2] "COM4"
==================================================================== */
SerialPortSetup(); // speed of 115200 bps etc.
}
void draw() {
background(255);
/* ====================================================================
グラフを描画
==================================================================== */
if ( DataRecieved3 ) {
pushMatrix();
pushStyle();
MyArduinoGraph.yMax=100;
MyArduinoGraph.yMin=-10;
MyArduinoGraph.xMax=int (max(Time3));
MyArduinoGraph.DrawAxis();
MyArduinoGraph.smoothLine(Time3, Voltage3);
popStyle();
popMatrix();
float gestureOneDiff =0;
float gestureTwoDiff =0;
float gestureThreeDiff =0;
/* ====================================================================
ジェスチャーを比較
==================================================================== */
float totalDist = 0;
int currentMax = 0;
float currentMaxValue = -1;
for (int i = 0; i < 4;i++) { //4つの登録したジェスチャーを比較
//ボタンをマウスでクリックしたときには、現在のジェスチャーを配列に記録
if (mousePressed && mouseX > 750 && mouseX<800 && mouseY > 100*(i+1) && mouseY < 100*(i+1) + 50) {
fill(255, 0, 0);
gesturePoints[i][0] = Time3[MyArduinoGraph.maxI];
gesturePoints[i][1] = Voltage3[MyArduinoGraph.maxI];
}
else {
fill(255, 255, 255);
}
//それぞれの点と現在の状態の距離を算出
gestureDist[i] = dist(Time3[MyArduinoGraph.maxI], Voltage3[MyArduinoGraph.maxI], gesturePoints[i][0], gesturePoints[i][1]);
//距離の合計を算出
totalDist = totalDist + gestureDist[i];
//最大値を算出
if (gestureDist[i] < currentMaxValue || i == 0) {
currentMax = i;
currentMaxValue = gestureDist[i];
}
}
totalDist=totalDist /3;
// 現在のジェスチャーと登録したジェスチャーの距離から、ボタンの色を描画
for (int i = 0; i < 4;i++) {
float currentAmmount = 0;
currentAmmount = 1-gestureDist[i]/totalDist;
if (currentMax == i) {
fill(currentAmmount*255.0f, 0, 0);
}
else {
fill(255, 255, 255);
}
stroke(0, 0, 0);
rect(750, 100 * (i+1), 50, 50);
fill(0, 0, 0);
textSize(30);
text(names[i], 810, 100 * (i+1)+25);
fill(255, 0, 0);
}
}
}
void stop() {
myPort.stop();
super.stop();
}
[/code]
「Beyond Interaction[改訂第2版] -クリエイティブ・コーディングのためのopenFrameworks実践ガイド」がいよいよ発売になりました! 店頭にも並び始めたようです。
今回はサブタイトルに「クリエイティブ・コーディングのためのopenFrameworks実践ガイド」とあるように、現場の第一線で活躍するクリエイターの方々に、すばらしい原稿を寄稿いただきました。前回に引き続き、久保田晃弘さん始め、openFrameworks開発陣からはZach Liebermanさん、Memo Atkenさん、Kyle McDonaldさんのインタビュー、Rhizomaticsの真鍋大度さん、堀宏行さん、比嘉了さん、Takramの緒方嘉人さん、VJ Kezzardrixとしても有名な神田竜さん、oFの日本の拠点ともいえるYCAM Interlab、openFrameworksの様々なアドオンや作品を手掛ける早坂あきらさん、ミュージックビデオなどでoFを活用しているMaxillaさんとTELESCOPEのひつじさん。素晴しい方々の知恵とノウハウが詰まった内容となっています。みなさま、多忙な中すばらしい原稿を執筆していただいて、本当にありがとうございます。そして、多くのクリエイターの方々をとりまとめていただいた、斎藤あきこさん、本当にお疲れさまでした。また、今回も素晴しい表紙のデザインと本文のエディトリアルデザインをしていただいたsignの森浩明さん、ありがとうございます。そして、何よりも前回に引き続き編集で尽力していだたいた、BNN出版の村田純一さんにはとてもお世話になりました。心から感謝しております!!
もちろん、前半の基礎編はopenFrameworksの最新版に対応。サンプルコードは全てGithubのリポジトリから入手可能です。
openFramwroksで既に開発をしている方も、まだ触れたことのない方も、この機会にぜひこの本をきっかけにopenFrameworksの世界を体験してください!
今回も引き続き、Tumblrのテーマのカスタマイズについて解説していきます。今回は、前回のテーマのカスタマイズよりもさらに高度な方法として、Thumblrの「edit HTML」の機能を使用して、自分独自のテーマをまっさらな状態から作成する方法について取りあげていきます。
前回はJavascritを使用してCanvas要素に直接描画をする方法を解説しました。しかし、実際やってみるとわかるようにプレーンなJavascriptで複雑な描画をしようと思うと、なかなか骨の折れる作業となります。今回はより洗練された方法で、Webブラウザに図形を描画したりアニメーションをする方法として、Processing.jsを紹介します。
この講義も前期の最終発表に向けて徐々に大詰めの段階になりました。今回はまず、オンライン・ポートフォリオを作成する際に便利な外部のWebサービスについて紹介します。写真や動画、音楽、音響などのメディアをWebサイトに載せる際には、無料で利用可能な様々なWebサービスを利用すると便利です。また、Webサービスの利用とあわせて、SNS(TwitterやFacebookなど)に向けて作成したWebサイトを効果的に露出させる方法について紹介します。後半は、サイト全体の設計の手順について実例を交えながら紹介していきます。
サンプルプログラムのダウンロード
サンプルプログラムは下記からダウンロードしてください。
ProcessingとArduinoの連携: シリアル通信を自作する方法 (先週のつづき)
次に、ArduinoとProcessingのもう一つの連携方法について試していきましょう。次に試す手法は、Arduino、Processing双方でシリアル通信のためのコードを自作して、通信の仕組み自体を自作していく方法です。Firmataを使用する方法に比べてきめ細かく効率的な通信が可能となります。また、Processing 2.0でも問題なく作動します。このワークショップで最終的に使用するToucheセンサーに関しても、このシリアル通信を自作する方法を用います。
今回のシリアル送受信には「ハンドシェイキング(handshaking)」という手法を使用してみます。ハンドシェイキングとは、2点間の通信路を確立した後、本格的に通信を行う前に事前のやり取りを自動的に行うことをいいます。実際の通信を行う前に、まず握手(ハンドシェイク)を行うイメージです。ハンドシェイキングした後は、通常の情報の転送を行います。
今回のArduinoとProcessingの通信では、まず実際のセンサーの値を送る前に、Processingからデータを送って欲しいというきっかけの合図を送る仕組みになっています。今回のサンプルでは任意の一文字(例えば’A’など)をArduinoに送ると、通信の開始のきっかけになります。ひとつのきっかけでArduinoからセンサーの数だけデータをコンマ区切りで送出し、最後に改行コードをつけます。Processingはこの一連のメッセージを受信して、受信が完了したら次のデータを要求するため再度任意の文字列(例えば’A’など)を送信します。
この通信の様子を図示すると以下のようになります。
先程のFirmataを使ったサンプルと同様にArduinoに読み込んだ2つのアナログセンサーの値を、Processingに送信して視覚化してみましょう。Arduino側の配線は、先程のFirmataのサンプルと同じ2つのアナログ入力(Analog Pin 0と1)です。
arduino側プログラム
/*
* Arduino - Processingシリアル通信
* Arduino側サンプル
*/
int sensors[2]; // センサーの値を格納する配列
int inByte; // 受信するシリアル通信の文字列
void setup(){
// 9600bpsでシリアルポートを開始
Serial.begin(9600);
// センサーの値と受信する文字列を初期化
sensors[0] = 0;
sensors[1] = 0;
inByte = 0;
// 通信を開始
establishContact();
}
void loop(){
// もしProcessingから何か文字を受けとったら
if (Serial.available() > 0) {
// 受信した文字列を読み込み
inByte = Serial.read();
// アナログセンサーの値を計測
sensors[0] = analogRead(A0);
sensors[1] = analogRead(A1);
// コンマ区切りでセンサーの値を送出
Serial.print(sensors[0]);
Serial.print(",");
Serial.println(sensors[1]);
}
}
void establishContact() {
// Processingから何か文字が送られてくるのを待つ
while (Serial.available() < = 0) {
// 初期化用の文字列
Serial.println("0,0");
delay(300);
}
}
Processing側プログラム
/*
* Arduino - Processingシリアル通信
* Processing側サンプル
*/
import processing.serial.*;
Serial myPort; // シリアルポート
float fillColor;
float diameter;
void setup() {
size(640, 480);
// ポート番号とスピードを指定してシリアルポートをオープン
myPort = new Serial(this, Serial.list()[4], 9600);
// 改行コード(\n)が受信されるまで、シリアルメッセージを受けつづける
myPort.bufferUntil('\n');
}
void draw() {
// 受信したセンサーの値で円を描画
background(0);
fill(fillColor);
ellipse(width/2, height/2, diameter, diameter);
}
void serialEvent(Serial myPort) {
// シリアルバッファーを読込み
String myString = myPort.readStringUntil('\n');
// 空白文字など余計な情報を消去
myString = trim(myString);
// コンマ区切りで複数の情報を読み込む
int sensors[] = int(split(myString, ','));
// 読み込んだ情報の数だけ、配列に格納
if (sensors.length > 1) {
fillColor = map(sensors[0], 0, 1023, 0, 255);
diameter = map(sensors[1], 0, 1023, 0, height);
}
// 読込みが完了したら、次の情報を要求
myPort.write("A");
}
プログラムを実行すると、センサーの値で大きさと明るさの変化する円が描かれます。
データの変化をグラフにプロット
では、次にもう少し実践的な視覚化にトライしてみましょう。アナログ入力に入ってくるセンサーの値は時間の経過とともに変化します。センサーの状態変化のパターンを視覚的にすぐに把握できるようにグラフで表示してみましょう。この手法は後でToucheでのジェスチャーの記録・判定の際にも関連してきます。
Arduinoのコードをもう少し改良して、センサーの数を簡単に変更できるようにしてみたいと思います。配列とくりかえしの部分を工夫することで実現しています。下記のようなコードに変更してみましょう。
冒頭の命令
#define NUM 2 // センサーの数
の数値を変化させると使用できるセンサーの数が変化します。(この例では2つ)。入力はAnalog pin 0から順番に使用してください。
arduino側プログラム
/*
* Arduino - Processingシリアル通信
* Arduino側サンプル
* センサーの数、可変パージョン
*/
#define NUM 2 // センサーの数
int sensors[NUM]; // センサーの値を格納する配列
int inByte; // 受信するシリアル通信の文字列
void setup(){
// 9600bpsでシリアルポートを開始
Serial.begin(9600);
// センサーの値と受信する文字列を初期化
for(int i = 0; i 0) {
// 受信した文字列を読み込み
inByte = Serial.read();
// アナログセンサーの値を計測
for(int i = 0; i
Processing側サンプル
このArduinoからの複数のセンサーの値を受けとり、グラフにプロットするサンプルをみてみましょう。下記のサンプルはとてもシンプルに取得した値をもとに点を打っていくことで、グラフをプロットしています。
このプログラムもセンサーの数をすぐに変更できるように作成しています。プログラム冒頭の
int NUM = 2; //センサーの数
の値を変更して、センサーの数を変更します。この数は先程作成したArduinoのプログラムで定義したセンサーの数と同じでなくてはなりません。
/*
* Arduino - Processingシリアル通信
* センサーの値をグラフにプロット
* Processing側サンプル
*/
import processing.serial.*;
int NUM = 2; //センサーの数
Serial myPort; // シリアルポート
int[] sensors = new int[NUM]; //センサーの値を格納する配列
int cnt; //カウンター
// グラフの線の色を格納
color[] col = new color[6];
void setup() {
//画面設定
size(800, 400);
frameRate(60);
// シリアルポートのリスト取得
println(Serial.list());
// ポート番号とスピードを指定してシリアルポートをオープン
myPort = new Serial(this, Serial.list()[4], 9600);
// 改行コード(\n)が受信されるまで、シリアルメッセージを受けつづける
myPort.bufferUntil('\n');
//グラフ初期化
initGraph();
}
void draw() {
// センサーの数だけ、グラフをプロット
for (int i = 0; i < NUM; i++) {
fill(col[i]);
float tx = map(cnt, 0, width, 0, width);
float ty = map(sensors[i], 0, 1023, height, 0);
ellipse(tx, ty, 4, 4);
}
// 画面の右端まで描画したら再初期化
if (cnt > width) {
initGraph();
}
//カウンタアップ
cnt++;
}
//グラフの初期化
void initGraph() {
background(47);
noStroke();
cnt = 0;
// グラフ描画の線の色を定義
col[0] = color(255, 127, 31);
col[1] = color(31, 255, 127);
col[2] = color(127, 31, 255);
col[3] = color(31, 127, 255);
col[4] = color(127, 255, 31);
col[5] = color(127);
}
void serialEvent(Serial myPort) {
// シリアルバッファーを読込み
String myString = myPort.readStringUntil('\n');
// 空白文字など余計な情報を消去
myString = trim(myString);
// コンマ区切りで複数の情報を読み込む
sensors = int(split(myString, ','));
// 読込みが完了したら、次の情報を要求
myPort.write("A");
}
では、この2つのプログラムの連携を試してみましょう。まずAnalog In 0とAnalog In 1に何かセンサーからの値を2つ入力します。例えば、下記では可変抵抗と明るさセンサーを入力にしています。
配線が完了したら、グラフの描画を試してみましょう。2つのデータが独立して画面に描かれる様子がみてとれます。
Touche for Arduino導入
いよいよ、このワークショップのメインの課題である、Toucheについて探っていきましょう! 今回はまずは導入として、Toucheのソフトウェアのインストールと、その操作方法について簡単に解説していきます。
まず下記の動画をみてAndorid版のToucheでのジェスチャー認識のイメージを掴みましょう。
Touché for Arduino from Mads Hobye on Vimeo .
この動画を観るとわかるように、Toucheのでははごく短時間の間隔で変化するセンサーの値(電位)を計測しています。この時間軸上での変化は、ジェスチャーによって特徴があります。この特徴をProcessing側で計測して今は何をしているのかを判定しているのです。実際には一定時間内での最大値とその時間を記録して(画面上の丸が描かれてい位置)、その位置によってジェスチャーの種類を登録・判定しています。
この計測のためのArduinoのプログラムと、グラフの描画とジェスチャーの登録・判定のためのProcessingのプログラムは下記のGithubアカウントから入手可能です。
Zipファイルをダウンロードして、まず「Arduino_sensing」フォルダ内の「Arduino_sensing.ino」プログラムをArduino.appから開いてボードに書き込みます。次に「Processing_graph」フォルダ内の「Processing_graph.pde」をProcessing.appで開き、Processingを実行してみてください。
すると、下記のような画面が表示されるはずです。
このプログラムは以下のようにして使用します。
Toucheセンサーを接続 (これは今後の授業で)
Arduino_sensing.inoをArduinoに転送
Processing.appでProcessing_graph.pdeを開いて実行
センサーで計測された値がグラフで表示される(はず)
ジェスチャーをして、右側のボタンで登録(全部で4種類まで可能)
同じジェスチャーを再現
右側のボタンで該当するものが点灯する(はず)
現在はToucheセンサーが無いので、実際にタッチジェスチャーで試すことはできませんが、Analog in 0に何かしらセンサーの値を入力すると擬似的に動作の体験が可能です。例えばAnalog 0に明るさセンサーの値を入力し、その距離に応じて4種類のジェスチャーを登録し、実際に再現できるか試してみましょう。
今回も引き続きTumblrを使用したWebサイト制作について解説していきます。Tumblrでは「テーマ」を選択することで誰でも簡単にデザインを変更することが可能です。さらに多くのテーマは色やフォントなど様々なページ内のデザイン要素をカスタマイズしていく機能が提供されています。テーマをカスタマイズすることで自分の好みにあわせたページを作っていくことができるようになります。今回はこのテーマのカスタマイズ方法についてとりあげていきます。
前回は、「HTML5」という様々な技術の集合体について、その成り立ちと技術の内容について解説しました。今回からHTML5を用いたWebサイトを、実際に制作しながら学んでいきます。今回はHTML5の中で2次元の描画やアニメーションを作成することが可能な「Canvas」という技術についてとりあげて、その制作方法について解説していきます。
サンプルファイルのダウンロード
以下の解説で使用したサンプルは、下記からダウンロードしてください。
HTMLウィジットとは
iBooks Authorに「HTMLウィジット」を使用することで、ブックの中にHTMLを埋めこむことが可能となります。この手法を応用すると、自分で作成したHTML5+JavaScriptのプログラムを組み合わせて、よりインタラクティブな電子書籍を作成することが可能となります。
HTMLウィジットには以下の要素が含まれています。
メイン HTML ファイル:このファイルはウィジェットの主要部分です。ファイル名には任意の名前を付けられますが、拡張子は必ず「.html」にします。CSS や JavaScript をこのメイン HTML ファイルに入れることができます。または、.css ファイルと .js ファイルをウィジェットのバンドルとしてメイン HTML ファイルとのセットにして読み込むこともできます。これらのファイルには、ウィジェットをデザインする際に使えるテクニックやトリックを使用できます。一般的には、HTML でウィジェットの構成を定義して CSS でビジュアルスタイルを提供し、JavaScript でインタラクティビティをサポートします。
Default.png:これはページに表示される画像で、ユーザがウィジェットを開くためにこれをタップします。ファイル名は必ず、大文字の「D」で「Default.png」とします。Default.png を作成するもっとも簡単な方法として、Web コンテンツ作成 App または Web ブラウザで表示しているメイン HTML ファイルのスクリーンショットを録ります。ウィジェットがアクティブなときに、Info.plist で指定しない限りこの画像は、Default.png の実際のサイズになります。
Info.plist:このファイルは、ウィジェット実行に必要な情報を iBooks Author と iBooks に提供します。ファイル名は必ず「Info.plist」とします。
シンプルなHTMLを貼り付けてみる
まずはシンプルなHTMLをウィジットとして貼りつけてみましょう。下記のようにプレーンなHTML書類を作成し、index.htmlという名前で、新規に作成したフォルダ内に保存してください。フォルダの名前は任意のもので構いませんが、例えば「html_widget1」としてみます。
[code lang=”html”]
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>HTMLウィジットのテスト</title>
</head>
<body>
<h1>HTMLウィジットのテスト</h1>
<p>このページはHTMLが埋めこまれてます。本文から外部のWebサイトへリンクを貼ることも可能です。</p>
<h2>リンクのテスト</h2>
<ul>
<li><a href="http://www.tamabi.ac.jp/index_j.htm">多摩美術大学</a></li>
</ul>
<p>画像も埋めこめます!!</p>
<p><img src="http://tamabi.jp/resources/logo_tau-j.png" alt="image" /></p>
</body>
</html>
[/code]
このフォルダに下記のファイルを作成し「Info.plist」という名前でindex.htmlと同じ場所に保存します。
[code lang=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AllowNetworkAccess</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>HTML Widget Test 1</string>
<key>CFBundleIdentifier</key>
<string>jp.ac.idd.tamabi.itamabi.widgetTest1</string>
<key>CFBundleName</key>
<string>widget_test</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>Height</key>
<integer>640</integer>
<key>MainHTML</key>
<string>index.html</string>
<key>Width</key>
<integer>1024</integer>
</dict>
</plist>
[/code]
新規に作成した「html_widget1」フォルダ内は、以下のようにindex.htmlとinfo.plistの2つのファイルが入った状態となります。
フォルダの内容を確認したら、このフォルダの名称を「html_widget1.wdgt」と変更します。すると自動的にフォルダから「ウィジット」という形式に変化して、ファインダー上に表示されます。
ここまで出来たら、iBooks Authorを起動します。ウィジットを貼りつけたい場所へ移動して、ウィジットメニューからHTMLウィジットを選択して貼り付けます。
ウィジットを選択した状態で「インスペクタ」ボタンを推してインスペクタを表示して「選択」ボタンを押します。するとファイルダイアログが表示されるので、先程作成した「html_widget1.wdgt」を選択します。
この状態で、iPadでプレビューしてみましょう。作成したHTMLがiBooks内で表示されるはずです。
JavaScriptとの組み合わせ1: 時計ウィジット
ウィジットにはHTMLだけでなく、CSSやJavaScriptを埋めこむことも可能です。例えば、下記のサンプルは現在時刻をJavascirptで取得して表示するサンプルです。
先程と同じようなやりかたで、ウィジット用のフォルダを用意して、HTMLファイルを以下のように変更します。info.plistはそのままで構いません。
[code lang=”html”]
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>時計</title>
<style>
body{
width:800px;
margin:2em auto;
font-family: "Trebuchet MS", Helvetica, sans-serif;
}
h1 {
color:#3399cc;
border-bottom: 1px solid #3399cc;
}
#time {
color:#666666;
font-size:120px;
}
</style>
</head>
<body>
<h1>iBooks Clock</h1>
<p>現在の時刻</p>
<output id="time">00:00:00</output>
<script>
setInterval(function(){
var dateObj = new Date();
var h = dateObj.getHours();
var m = dateObj.getMinutes();
var s = dateObj.getSeconds();
var timeStr = h + " : "+m+" : "+s;
document.getElementById("time").innerHTML = timeStr;
}, 1000);
</script>
</body>
</html>
[/code]
このフォルダも拡張子「.wdgt」の形式にしてウィジット化します。そのウィジットを先程と同じようにiBooks Authorを使用してブック内に貼りこむと以下のように時計が表示されるでしょう。
Processing.jsで、さらに高度なインタラクション
最後により高度なインタラクティブなコンテンツをiBooksに埋めこんでみましょう。HTML+Javascriptで記述されたページであれば、基本的にはHTMLウィジット化することが可能です。例えば、Processing という開発環境も、最近ではJavascriptモードで書き出すことが可能となったので、そのままHTMLウィジットにすることが可能です。
まずProcessingのコンテンツを表示するためのテンプレートをダウンロードしてください。
このファイルを展開し、中にあるsketch.pdeをProcessing.appから編集します。例えば、以下のようなインタラクションを加えたプログラムにしてみましょう。
[code lang=”java”]
int NUM = 32;
float[] x = new float[NUM];
float[] y = new float[NUM];
float phase, speed, radius, ratio;
void setup() {
size(960, 640);
frameRate(30);
background(0);
speed = 3.0;
radius = height/4.0;
ratio = 1.33;
}
void draw() {
if (mousePressed) {
ratio = float(mouseX) / float(mouseY);
}
fade();
translate(width/2, height/2);
phase += speed;
for (int i = 0; i < NUM; i++) {
x[i] = cos(radians(phase) / NUM * (i + 1)) * radius;
y[i] = sin(radians(phase) / NUM * (i + 1) * ratio) * radius;
noFill();
stroke(0, 127, 255);
ellipse(x[i], y[i], radius/float(NUM) * i, radius/float(NUM) * i);
}
}
void fade() {
noStroke();
fill(0, 10);
rect(0, 0, width, height);
}
[/code]
このフォルダの拡張子を「.wdgt」 に変更してウィジット化し、iBooks Authorでブックに張り込みます。すると以下のようにインタラクティブにアニメーションするページが表示されます。
この手法をつかうことで、高度なインタラクティブなコンテンツや、生成的なコンテンツをiBooksに埋め込むことも可能となるでしょう。工夫次第で非常に大きな可能性を秘めた機能といえるのではないでしょうか。
今回は、いよいよProcessingとArduinoを連携する方法について実際にプログラミングしながら学んでいきます。ProcessingとArduinoを連携する方法は大きく分けて2つのやり方があります。
1. 既存のライブラリを使用する方法
Arduino側にFirmataライブラリ、Processing側にArduinoライブラリをインストールして、Processingから直接Arduinoの入出力を操作する方法。
2. シリアル通信を自作する方法
外部ライブラリは使用せず、ArduinoとProcessing双方で、シリアル入出力のプログラミングを行う方法。
今回はこの2つの方法の双方を紹介していきます。
連携方法 1: ArduinoライブラリとFirmataを使用する方法
注意!!: Processing 2.0は、Arduinoライブラリ+Firmataの環境に対応していません。この方法を試す場合には、Processing 1.5.1を使用してください。インストールは下記のリンクから、v1.5.1を選択してダウンロードしてください。
Arduino側にFirmataライブラリ、Processing側にArduinoライブラリをインストールして、Processingから直接Arduinoの入出力を操作する方法です。この方法を図にすると以下のようなイメージとなるでしょう。
Arduino側の準備: Firmataライブラリをインストール
では、まずArduino側から準備を始めましょう。
ArduinoにはFirmataと呼ばれる、ArduinoなどのマイコンとPCとのコミュニケーションのための汎用のプロトコルを使用します。そのために、ArduinoにFirmataのためのプログラムをアップロードして使用します。今回はArduinoのサンプルの中に掲載されている「Standard Firmata」というプログラムを使用していきます。
Arduinoのメニューから以下のプログラムを開きます。
File > Examples > Firmata > StandardFirmata
Firmataの動作確認
Firmataの動作確認には、プロジェクトページから配布されているテストプログラムを使用します。
このページの「Firmata Test Program」の項目にある
をダウンロードします。プログラムを展開し、FirmataをアップロードしたArduinoがUSBに接続されている状態で「firmata_test.app」を起動します。
プログラムのメニューバー「Port」メニューから接続しているポートを選択すると、下記のようなテスト画面になります。Pin 2 〜 Pin 21までの入出力をGUIで操作しながら試すことが可能です。
Processing側の準備: Arduinoライブラリのインストール
次にProcessing側の準備をしましょう。ArduinoにFirmataライブラリをインストールしたのと同様に、Processing側にはArduinoをコントロールするためのライブラリをインストールします。Arduinoライブラリは、ProcessingからArduinoをコントロールするためにデザインされたライブラリで、Arduino側にはFirmataがインストールされていれば、特に追加でコーディングする必要はありません。
まず、Arduinoライブラリをダウンロードします。下記のリンクから「Processing Library: processing-arduino.zip」を選択してダウンロードしてください。
ダウンロードした「processing-arduino.zip」を展開すると、「arduino」というフォルダが生成されます。このフォルダを、「書類」フォルダ内の「Processing」>「libraries」にコピーしてください。
Processing + Firmataをつかってみる: シリアルポートの確認
まず、ProcessingからArduinoにインストールしたFirmataを操作するには、まず使用しているシリアルポートの環境を知る必要があります。下記のコードをProcessingに入力してください。
import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
void setup() {
println(Arduino.list());
}
すると、Processingの下部のコンソールに以下のようなメッセージが表示されるはずです。
[0] "/dev/tty.Bluetooth-PDA-Sync"
[1] "/dev/cu.Bluetooth-PDA-Sync"
[2] "/dev/tty.Bluetooth-Modem"
[3] "/dev/cu.Bluetooth-Modem"
[4] "/dev/tty.usbserial-A900ceWs"
[5] "/dev/cu.usbserial-A900ceWs"
この中から、「/dev/tty.usbserial…」もしくは「/dev/tty.usbmodem…」から始まる記述の先頭の番号(上記の例では4番)を憶えておきます。
Processing + Firmataをつかってみる 1: Digital OUT – LEDを点灯
では、まず簡単なプログラムで動作を確認してみましょう。Processingの画面でマウスを押すとLEDが点灯するプログラムを作成してみましょう。Arduino側は、Digital Outの13番にLEDを接続しておきます。
/*
* Arduino - Processingシリアル通信
* Firmataを使用したサンプル
* Processing側
*/
import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
int ledPin = 13;
color bgColor = color(0);
void setup() {
size(400, 200);
arduino = new Arduino(this, Arduino.list()[4], 57600);
arduino.pinMode(ledPin, Arduino.OUTPUT);
}
void draw() {
background(bgColor);
}
void mousePressed() {
arduino.digitalWrite(ledPin, Arduino.HIGH);
bgColor = color(255,0,0);
}
void mouseReleased() {
arduino.digitalWrite(ledPin, Arduino.LOW);
bgColor = color(0);
}
画面をクリックすると、LEDが点灯するはずです。
Processing + Firmataをつかってみる 2: Analog In – センサーの情報を視覚化
では次に、アナログ入力を試してみましょう。この方法が、今後、様々なセンサーからの情報をProcessingで視覚化していく基本となります。
まずは、Arduino側のセンサーの準備をしましょう。まずはシンプルに2つの可変抵抗(もしくは光センサーなどの簡単なセンサー)を用いて実験してみましょう。例えば、下記の図は、2つの可変抵抗を接続した際の配線のサンプルとなります。
このセンサーの情報を視覚化するProcessingのコードを書いてみましょう。まずはシンプルにセンサーから取得した値の数値をモニターしてみましょう。
/*
* Arduino - Processingシリアル通信
* Firmataを使用したサンプル
* Processing側
*/
import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
int input0 = 0;
int input1 = 1;
void setup() {
size(400,200);
arduino = new Arduino(this, Arduino.list()[4], 57600);
}
void draw() {
background(0);
fill(255);
int analog0 = arduino.analogRead(input0);
int analog1 = arduino.analogRead(input1);
text("input0 = " + analog0, 10, 20);
text("input1 = " + analog1, 10, 40);
}
このコードを実行すると、Analog0とAnalog1に入力したセンサーの生の値が、文字で表示されます。センサーの値は、ほぼ0〜1023の範囲となっているでしょう。
では、この数値を利用して、簡単な視覚化を行ってみましょう。下記のサンプルは、Analog Pin 0の値を円の直径に、Analog Pin 1の値を円のグレースケールの濃度に適用しています。
/*
* Arduino - Processingシリアル通信
* Firmataを使用したサンプル
* Processing側
*/
import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
int input0 = 0;
int input1 = 1;
void setup() {
size(640, 480);
arduino = new Arduino(this, Arduino.list()[4], 57600);
arduino.pinMode(input0, Arduino.INPUT);
arduino.pinMode(input1, Arduino.INPUT);
}
void draw() {
background(0);
fill(255);
int analog0 = arduino.analogRead(input0);
int analog1 = arduino.analogRead(input1);
text("input0 = " + analog0, 10, 20);
text("input1 = " + analog1, 10, 40);
float diameter = map(analog0, 0, 1024, 0, height);
float fillColor = map(analog1, 0, 1024, 0, 255);
fill(fillColor);
noStroke();
ellipse(width/2, height/2, diameter, diameter);
}
連携方法 2: シリアル通信を自作する方法
次に、ArduinoとProcessingのもう一つの連携方法について試していきましょう。次に試す手法は、Arduino、Processing双方でシリアル通信のためのコードを自作して、通信の仕組み自体を自作していく方法です。Firmataを使用する方法に比べてきめ細かく効率的な通信が可能となります。また、Processing 2.0でも問題なく作動します。このワークショップで最終的に使用するToucheセンサーに関しても、このシリアル通信を自作する方法を用います。
今回のシリアル送受信には「ハンドシェイキング(handshaking)」という手法を使用してみます。ハンドシェイキングとは、2点間の通信路を確立した後、本格的に通信を行う前に事前のやり取りを自動的に行うことをいいます。実際の通信を行う前に、まず握手(ハンドシェイク)を行うイメージです。ハンドシェイキングした後は、通常の情報の転送を行います。
今回のArduinoとProcessingの通信では、まず実際のセンサーの値を送る前に、Processingからデータを送って欲しいというきっかけの合図を送る仕組みになっています。今回のサンプルでは任意の一文字(例えば’A’など)をArduinoに送ると、通信の開始のきっかけになります。ひとつのきっかけでArduinoからセンサーの数だけデータをコンマ区切りで送出し、最後に改行コードをつけます。Processingはこの一連のメッセージを受信して、受信が完了したら次のデータを要求するため再度任意の文字列(例えば’A’など)を送信します。
この通信の様子を図示すると以下のようになります。
先程のFirmataを使ったサンプルと同様にArduinoに読み込んだ2つのアナログセンサーの値を、Processingに送信して視覚化してみましょう。Arduino側の配線は、先程のFirmataのサンプルと同じ2つのアナログ入力(Analog Pin 0と1)です。
arduino側プログラム
/*
* Arduino - Processingシリアル通信
* Arduino側サンプル
*/
int sensors[2]; // センサーの値を格納する配列
int inByte; // 受信するシリアル通信の文字列
void setup(){
// 9600bpsでシリアルポートを開始
Serial.begin(9600);
// センサーの値と受信する文字列を初期化
sensors[0] = 0;
sensors[1] = 0;
inByte = 0;
// 通信を開始
establishContact();
}
void loop(){
// もしProcessingから何か文字を受けとったら
if (Serial.available() > 0) {
// 受信した文字列を読み込み
inByte = Serial.read();
// アナログセンサーの値を計測
sensors[0] = analogRead(A0);
sensors[1] = analogRead(A1);
// コンマ区切りでセンサーの値を送出
Serial.print(sensors[0]);
Serial.print(",");
Serial.println(sensors[1]);
}
}
void establishContact() {
// Processingから何か文字が送られてくるのを待つ
while (Serial.available() <= 0) {
// 初期化用の文字列
Serial.println("0,0");
delay(300);
}
}
Processing側プログラム
*
* Arduino - Processingシリアル通信
* Processing側サンプル
*/
import processing.serial.*;
Serial myPort; // シリアルポート
float fillColor;
float diameter;
void setup() {
size(640, 480);
// ポート番号とスピードを指定してシリアルポートをオープン
myPort = new Serial(this, Serial.list()[4], 9600);
// 改行コード(\n)が受信されるまで、シリアルメッセージを受けつづける
myPort.bufferUntil('\n');
}
void draw() {
// 受信したセンサーの値で円を描画
background(0);
fill(fillColor);
ellipse(width/2, height/2, diameter, diameter);
}
void serialEvent(Serial myPort) {
// シリアルバッファーを読込み
String myString = myPort.readStringUntil('\n');
// 空白文字など余計な情報を消去
myString = trim(myString);
// コンマ区切りで複数の情報を読み込む
int sensors[] = int(split(myString, ','));
// 読み込んだ情報の数だけ、配列に格納
if (sensors.length > 1) {
fillColor = map(sensors[0], 0, 1023, 0, 255);
diameter = map(sensors[1], 0, 1023, 0, height);
}
// 読込みが完了したら、次の情報を要求
myPort.write("A");
}
プログラムを実行すると、センサーの値で大きさと明るさの変化する円が描かれます。
応用: センサーの値ビジュアライズ
では、この手法をつかって、既存のプログラムをセンサーの情報によって変化するように書き換えてみましょう。例えば、下記のプログラムは、Processingに付属しているサンプル「Examples > Demo > Performance > DynamicParticleImmediate」を改造して、2つのアナログ入力でパーティクルの場所を変化させています。元のサンプルでは、パーティクルの位置はマウスの位置に対応させている部分を、2つのアナログ入力の値を保持したPVectorクラスのインスタンス「pos」に書き換えることで実現しています。
/*
* Arduino - Processingシリアル通信
* Processing側サンプル
*/
import processing.serial.*;
Serial myPort; // シリアルポート
PVector pos = new PVector();
PShape particles;
PImage sprite;
int npartTotal = 10000;
int npartPerFrame = 25;
float speed = 1.0;
float gravity = 0.05;
float partSize = 20;
int partLifetime;
PVector velocities[];
int lifetimes[];
int fcount, lastm;
float frate;
int fint = 3;
void setup() {
size(640, 480, P3D);
frameRate(120);
// ポート番号とスピードを指定してシリアルポートをオープン
myPort = new Serial(this, Serial.list()[4], 9600);
// 改行コード(\n)が受信されるまで、シリアルメッセージを受けつづける
myPort.bufferUntil('\n');
particles = createShape(PShape.GROUP);
sprite = loadImage("sprite.png");
for (int n = 0; n < npartTotal; n++) {
PShape part = createShape();
part.beginShape(QUAD);
part.noStroke();
part.texture(sprite);
part.normal(0, 0, 1);
part.vertex(-partSize/2, -partSize/2, 0, 0);
part.vertex(+partSize/2, -partSize/2, sprite.width, 0);
part.vertex(+partSize/2, +partSize/2, sprite.width, sprite.height);
part.vertex(-partSize/2, +partSize/2, 0, sprite.height);
part.endShape();
particles.addChild(part);
}
partLifetime = npartTotal / npartPerFrame;
initVelocities();
initLifetimes();
// Writing to the depth buffer is disabled to avoid rendering
// artifacts due to the fact that the particles are semi-transparent
// but not z-sorted.
hint(DISABLE_DEPTH_MASK);
}
void draw () {
background(0);
for (int n = 0; n < particles.getChildCount(); n++) {
PShape part = particles.getChild(n);
lifetimes[n]++;
if (lifetimes[n] == partLifetime) {
lifetimes[n] = 0;
}
if (0 <= lifetimes[n]) {
float opacity = 1.0 - float(lifetimes[n]) / partLifetime;
part.setTint(color(255, opacity * 255));
if (lifetimes[n] == 0) {
// Re-spawn dead particle
part.resetMatrix();
// パーティクルの位置を、センサーからの情報で移動
part.translate(pos.x, pos.y);
float angle = random(0, TWO_PI);
float s = random(0.5 * speed, 0.5 * speed);
velocities[n].x = s * cos(angle);
velocities[n].y = s * sin(angle);
}
else {
part.translate(velocities[n].x, velocities[n].y);
velocities[n].y += gravity;
}
}
else {
part.setTint(color(0));
}
}
shape(particles);
fcount += 1;
int m = millis();
if (m - lastm > 1000 * fint) {
frate = float(fcount) / fint;
fcount = 0;
lastm = m;
println("fps: " + frate);
}
}
void initVelocities() {
velocities = new PVector[npartTotal];
for (int n = 0; n < velocities.length; n++) {
velocities[n] = new PVector();
}
}
void initLifetimes() {
// Initializing particles with negative lifetimes so they are added
// progressively into the screen during the first frames of the sketch
lifetimes = new int[npartTotal];
int t = -1;
for (int n = 0; n < lifetimes.length; n++) {
if (n % npartPerFrame == 0) {
t++;
}
lifetimes[n] = -t;
}
}
void serialEvent(Serial myPort) {
// シリアルバッファーを読込み
String myString = myPort.readStringUntil('\n');
// 空白文字など余計な情報を消去
myString = trim(myString);
// コンマ区切りで複数の情報を読み込む
int sensors[] = int(split(myString, ','));
// 読み込んだ情報の数だけ、配列に格納
if (sensors.length > 1) {
pos.x = map(sensors[0], 0, 1023, 0, width);
pos.y = map(sensors[1], 0, 1023, 0, height);
}
// 読込みが完了したら、次の情報を要求
myPort.write("A");
}
実習(課題?): センサー情報を視覚化する
今日解説した方法で、ArduinoとProcessingを連携してセンサー情報を視覚化するスケッチを来週までに1つ作成してください。スケッチは、既存のプログラムを改造したもので構いません。例えば以下のリソースが役に立つでしょう。
好きなサンプルを一つ選び、センサーからの情報で変化するようにしてみましょう!