openFrameworksとArduinoで音量メーター

February 20, 2010
 前回、ようやくArduinoを繋ぐ事ができたので、LEDを光らせて何か作ってみようと思います。せっかくopenFrameworksからコントロールしているのでPC側の機能を使った物ということで、マイクで拾った音量をLEDで表示してみます。

■サンプルの内容
 まず、firmataExampleを見てLEDのon/offの方法を調べます。

□ testApp.h
 ofArduino というのがArduinoを管理してくれるクラスですね。

□testApp.cpp - setup
 ard.connectで接続開始しています。前回ハマったのはこのドライバ名(?)でした。

□testApp.cpp - update
 接続チェックかな。

□testApp.cpp - setupArduino
 ピンのモード設定。ARD_OUTPUT=デジタル出力用、ARD_ANALOG=アナログ入力用、ARD_PWM=PWM出力用。PWMというのは、デジタル出力を細かくOn/Offする事で階調を表現する事。たとえば、LEDを1秒間に0.1秒点灯、0.1秒消灯を5回繰り返せば、常につけている場合と比べて、半分の明るさになる。

□testApp.cpp - updateArduino
 Arduinoオブジェクトをアップデートしています。ard.sendPwm()で、Pin11に50%〜100%の明るさになるようにPWMを送っています。

□testApp.cpp - draw
 ard.getAnalog(0)で、pin0(半固定抵抗)のアナログ入力の値を取得しています。


 という事で、以下の命令でコントロールする事ができます。簡単!便利!
     : 送る : 受け取る
 デジタル:sendDigital:getDigital
 アナログ:sendPwm:getAnalog
(sendPwmはアナログを出力するわけではありません)




■音量を扱ったサンプル
 LEDのコントロールが分かったところで、今度は音量を取得する方法を探します。examplesにaudioInputExampleというのがあるので、開いてみます。PCのマイクの音を周波数別に表示しているみたいです。

□ testApp.h
 float * left、float * right、左右の音量が格納されます。周波数ごとの配列として使われます。

□testApp.cpp - setup
 ofSoundStreamSetup(0,2,this, 44100, 256, 4);
 left = new float[256];
 right = new float[256];
 音の入出力のセットアップですね。周波数を256段階に分けて取り込みます。

□testApp.cpp - draw
 left[]とright[]に入っている値を使って、波形を描画しています。

□testApp.cpp - audioReceived
 引数として渡されるinputに左右の値が交互に入っているみたいですね。それを分けて、left,rightに入れています。


 音量を直接取り出す命令が分からなかったのですが、left,rightに入っている全ての値を合算すれば、全体の音量になるはず。多分。



■組み合わせる
 以上でそれぞれ必要な準備と使い方が分かったので、新しいプロジェクトを作って、各要素をコピーしてきます。

testApp.h

#ifndef _TEST_APP
#define _TEST_APP


#include "ofMain.h"

class testApp : public ofBaseApp{

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

void keyPressed (int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);

void setupArduino();
void updateArduino();

// Arduino
ofArduino ard;
bool bSetupArduino; // flag variable for setting up arduino once

// Sound
void audioReceived (float * input, int bufferSize, int nChannels);
float * left;
float * right;
};

#endif


testApp.cpp

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
ofSetVerticalSync(true);
ofSetFrameRate(60);
ofBackground(255,255,255);

// Arduino setup
ard.connect("/dev/tty.usbserial-A7005OBP", 57600);
bSetupArduino = false;

// Sound setup
ofSoundStreamSetup(0,2,this, 44100, 256, 4);
left = new float[256];
right = new float[256];
}

//--------------------------------------------------------------
void testApp::setupArduino(){
// 全てのPinをデジタル出力モードに設定
for (int i = 0; i < 13; i++){
ard.sendDigitalPinMode(i, ARD_OUTPUT);
}
}

//--------------------------------------------------------------
void testApp::update(){

if ( ard.isArduinoReady()){

// 1st: setup the arduino if haven't already:
if (bSetupArduino == false){
setupArduino();
bSetupArduino = true; // only do this once
}
// 2nd do the update of the arduino
updateArduino();
}
}

//--------------------------------------------------------------
void testApp::updateArduino(){
ard.update();
}

//--------------------------------------------------------------
void testApp::draw(){
// draw the left:
ofSetColor(0x333333);
ofRect(0, 0, ofGetWidth(), ofGetHeight() );
ofSetColor(0xFFFFFF);

for (int i = 0; i < 256; i++){
ofSetLineWidth(4);
ofLine(i*4, ofGetHeight()/2, i*4, ofGetHeight()/2+left[i]*100.0f);
}

if (!ard.isArduinoReady()){
cout << "arduino not read" << endl;
} else {
float volume = 0;
for (int i = 0; i < 256; i++){
volume += left[i];
}

volume *= 100;

for (int j = 1; j<6; j++) {
if (volume > j * 30) {
ard.sendDigital(j+1, 1);
}else {
ard.sendDigital(j+1, 0);
}
}
}
}

//--------------------------------------------------------------
void testApp::audioReceived (float * input, int bufferSize, int nChannels){
for (int i = 0; i < bufferSize; i++){
left[i] = input[i*2];
right[i] = input[i*2+1];
}
}


■Arduino側の配線
 テストでLEDを1つ点けましたが、ほぼ一緒です。2〜6Pinの5個になっただけです。0と1Pinは書き込みのために使われているので空けています。(ん?今回は書き込みしないから使ってもいいのかな・・?)




■動画
太陽の塔

太陽の塔



太陽の塔

私の大学生活には華がない。特に女性とは絶望的に縁がない。三回生の時、水尾さんという恋人ができた。毎日が愉快だった。しかし水尾さんはあろうことか、この私を振ったのであった!クリスマスの嵐が吹き荒れる京の都、巨大な妄想力の他に何も持たぬ男が無闇に疾走する。失恋を経験したすべての男たちとこれから失恋する予定の人に捧ぐ、日本ファンタジーノベル大賞受賞作。


 小説的なストーリー展開はあまり無くて、ひたすら主人公の妄念が語られています。筋が少ない分、筆者の体験の欠片という印象を持ちました。デビュー作だし。「夜は短し」>「四畳半」>「太陽の塔」と遡る順番で読んできたので、作品として再構成する前の生の体験に戻っていくように感じられたのかもしれません。だから、大好きな作家の源流を知るという意味で楽しめました。


森見 登美彦 (著)
文庫: 237ページ
出版社: 新潮社 (2006/05)
発売日: 2006/05
京都魔界案内―出かけよう、「発見の旅」へ

京都魔界案内―出かけよう、「発見の旅」へ



京都魔界案内―出かけよう、「発見の旅」へ

日本を代表する「雅」の都・京都は、陰陽師や呪術僧が活躍する、呪いや怨念の渦巻く霊的空間でもあった。晴明神社、神泉苑、貴船神社…、名うての「魔界」を巡り歩くうちに、「異なる者」たちが跳梁跋扈する刺激に充ちた時空が蘇ってくる―そんな「魔界」発見の旅へようこそ!読んでから行くか、行ってから読むか。


小松 和彦 (著)
文庫: 264ページ
出版社: 光文社 (2002/02)
発売日: 2002/02

Arduinoを繋いでみる

February 18, 2010
今回は、openFrameworksでArduinoをコントロールしてみます。

Arduinoとは、単純な入出力を備えた基板と Processing/Wiring 言語を実装した開発環境から構成されるシステム、だそうです。要するに、PCとの通信・書き込みもセットになったI/Oボードという事かな。詳しくはWikiで。


■Arduinoの準備

□ハードの準備
 Arduinoはオープンハードウェアなので、仕様をみて作ろうと思えば作れますが(僕には無理ですが)、最近はAmazonでも購入できます。たくさんの種類がありますが、最初は基本的なものを用意するのがいいと思います。その辺の事情はこちらで書かれています。スタパ齋藤の「週刊スタパトロニクスmobile」

 僕が買ったのはこれ。電源をUSB、ACアダプタで供給でき、シールド(拡張ボード)と組み合わせる事もできます。
Arduino Duemilanove 328

 電子工作をやった事が無く、ブレッドボードを持っていなければ、Arduinoをはじめようキットも一緒に買うといいかもしれません。





□ソフトの準備
 Arduino IDE(開発環境)はこちらから自分の環境にあったものをダウンロードしてください。Download the Arduino Software
 解凍したフォルダの中の「FTDIUSBSerialDriver」を実行して、USB-Serialドライバーをインストールします。

□サンプルの実行
 まずは最もシンプルなLEDが点滅するサンプルを動かしてみます。

 下の写真のように13番のOutput PinにLEDを繋ぎ、USBでパソコンに接続します。

 
 次にAruduino IDE を起動し、File > Examples > Digital > Blink を選択すると、以下のようなウィンドウが開きます。

「Upload」のアイコンをクリックすると、Arduinoへプログラムを書き込みを始め、正常に終了するとLEDが1秒ごとに点滅します。IDEに戻り、loop()の中のdelay(1000)をdelay(500)に変えて再度Uploadすると、0.5秒毎の点滅に変わると思います。

 

■サンプルを開く
 Arduinoへの書き込み確認ができたので、いよいよopenFrameworksからコントロールしてみます。そのためには「Firmata」という物を使います。Firmataとは、マイクロコントローラとホストコンピュータ上で通信するための一般的なプロトコル、だそうです。PCからの命令に受け答えるソフトをArduinoに入れ、openFrameworksからはそのソフトが分かるように命令を渡してあげる、という事のようです。なので、Firmataに従っていれば、Processingからコントロールする事もできます。

 まず、Arduinoにfirmataを入れます(こういう言い方でいいのかな?)File > Examples > Firmata > StandardFirmataを開き、Uploadします。

 次にoFのapps/firmataExample/firmataExample.xcodeproj を開きます。まずはそのままビルドしてみてください。下記のようにアプリは起動しますが、Arduinoが接続されていないと表示されます。

 写真に従ってLED, 半固定抵抗を繋ぎます。半固定抵抗は「始めようキット」に入っていないので、別に用意する必要があります。Amazonでは半固定可変抵抗器セットがありますが高いので、千石電商などの電子パーツ屋さんで買うのがよいと思います。

 この状態でビルドしてエラーが出なければ成功です。右上に半固定抵抗の値が表示されます。ちなみに僕はここで躓きました。ビルドでエラーはでませんが、Arduinoが認識されません。試しにProcessingのFirmataサンプル(SketchBook > librarys > arduino > examples > arduino_output)を試したところ、ちゃんと動きました。
 かなり悩んだ結果、ようやく分かったのは、Processingのメッセージでusb serialを探している(?)表示がありますが、この名前とopenFrameworksのfirmataExampleのtestApp.cppで呼び出している名前が違っていました。Processingで表示されている名前に書き換えたところ、ちゃんと動くようになりました。

Processingのarduino_output、実行時のメッセージ
 [0] "/dev/tty.usbserial-A7005OBP"

openFrameworks > firmatExample > testApp.cpp
 ard.connect("/dev/ttyUSB0", 57600);
 ↓
 ard.connect("/dev/tty.usbserial-A7005OBP", 57600);




こんな感じで、ようやくopenFrameworksでArduinoをコントロールできるようになったので、次回はLEDで音量を表示するメーターを作ってみます。
新しいプロジェクトを作る

新しいプロジェクトを作る

February 16, 2010
■コピーで作ってみる
openFrameworksの新しいプロジェクトを作るには、「emptyExample」という空っぽのサンプルをコピーして使います。こちらが大変参考になりました。

相対パスが同じになるようにコピーし、名前を変えます。
 apps/examples/emptyExample/
 ↓
 apps/myApps/myApp/


■テンプレート
ただ、上記の方法はアプリ名を変えるためにあちこち書き換える必要があり、それが結構手間になります。

Xcodeはプロジェクトのテンプレートをユーザーが作る事ができるので、誰か作っているんじゃないかと思って探してみたところ(他力本願...)、こちらで公開されている方がいました。(ありがとうございます!)

memo.tv
XCode templates for openFrameworks on Desktop and iPhone


■インストール
上記のサイトからこちらに飛び、右上の「Download Source」からファイルをダウンロードします。

解凍してできた「Project Templates」を以下に置きます。
/Library/Application Support/Developer/Shared/Xcode/Project Templates
このフォルダは最初は無いので、自分で作ります。

Xcodeを再起動して、新規プロジェクトを選ぶとウィンドウが開き、User TemplatesからMac OSX Empty ExampleとiPhone EmptyExampleが選択できるようになります。

次に保存場所と名前を決めます。この名前がアプリの名前になります。保存場所は、コピーで作る場合と同じく、apps以下に置く必要があります。

「ビルドと実行」で、コンパイルできます。ただ、左上の対象OSが僕の環境ではベースSDKとなっていて、そのままではエラーが出たので、10.6を選択したら正常にコンパイルできました。



以上で、新しいプロジェクトを作る事ができるようになったので、次はサンプルをいじってArduinoを繋いでみます。


(2010/2/17 追記)
書き終えた後で気がつきましたが、田所先生のサイトでインストーラー付きのテンプレートを配布されていました。こちらの方が導入しやすそうです。
openframeworks.jp

初めてのopenFrameworks

■開発環境
Flash以外の開発環境も使ってみたいなーと思い、調べてみたところ色々ありました。

・Unity
・openFrameworks
・XNA
・WPF
・Qt
・processing

それぞれ、プラットフォームや思想の違いがあり、使いどころが違うようです。まずは一番気になったopenFrameworksを触ってみる事にしました。


■openFrameworksの特徴
・C++のライブラリ
 openFrameworksとは、プログラミング言語C++向けの、クリエイティブ・コーディングに特化したライブラリ、だそうです。難しい事は置いといて、絵を描いたり音を出したり反応したりする部分から制作に入れるらしいです。便利。

・対応プラットフォームが多い
 Mac/Winで開発ができ、それぞれのネイティブアプリとして動作します。また、拡張機能としてiPhoneアプリや、Arduinoをコントロールするアプリも作る事ができます。デバイス開発もやりたい事なので、一つの環境でこれらを開発できるのは素敵すぎます。


■インストール方法
 MacのXcodeでのインストール方法を書きます。ほとんどの事は、こちらを参考にさせていただきました。

1.ダウンロード
 こちらからダウンロードします。現在の最新版はv0.061。Mac OSX10.6の場合は、x-code FAT(10.6)を選びます。(FATはアドオンを含んでいるかどうか)

2.インストール
 ダウンロードしたファイルを解凍してできた「of_preRelease_v0061_osxSL_FAT」というフォルダを任意の場所に置きます。僕は ~/Develop/of/ の中に置きました。

3.サンプル
 apps/example/ の中にサンプルファイルが入っています。.xcodeprojという拡張子のファイルをXcodeで開きます。Xcodeのインストールはこちらを参考にしてください。(というかこちらのサイトにほとんど全部書いてありますね)

4.ビルド
 試しにgraphicsExample.xcodeprojを開いてみました。こんな画面になります。

 
 「ビルドと実行」をクリックするとコンパイルが始まり、問題なく終了するとサンプルが表示されます。


 
こんな感じでネイティブで動くアプリを書き出せます。FlashやDirectorで開発していた自分としては「ネイティブ」ってだけでテンションが上がります!次は、テンプレートを導入し新規プロジェクトを作ってみます。