バイオメディア・アート
ArduinoとProcessingの連携1 : センサーの情報を視覚化する
今日の内容
- ArduinoとProcessingを連携する
- Arduinoのアナログインにセンサーからの情報を入力
- 可変抵抗
- 光センサー
- 温度センサー
- ProcessingからArduinoの情報を取得してリアルタイムに情報を視覚化
- 今後のBio Media Artの肝となってくる部分!!
ArduinoとProcessinの連携方法
- Serial 通信による連携
- Funnelによる連携
- この授業では、Serial通信のほうを採用
- 参考として、Funnelを使用した方法も紹介
シリアル通信:全体の構成
サンプル1:可変抵抗の値を送信
- まずはシンプルな構成で連携をテスト
- ブレッドボードとArduinoの配線
- 可変抵抗1つ
- ArduinoのAnalog in 0に抵抗値を接続
- USBケーブルで、ArduinoをPCに接続
- Arduino
- Analog in の値を取得 – analogRead()
- シリアルで値を送信 – Serial.print()
- Processing
- シリアルポートに接続
- シリアルポートから値を読み取る
- 可変抵抗器 (ポテンショメーター)
- 抵抗値を変更することができる抵抗器
- 今回は、10KΩの可変抵抗器を用意
- 可変抵抗器の抵抗値をとりだす
- 全体の配線例
- Arduino側のプログラム
- setup() – 初期設定
- シリアル通信を開始
- loop() – メインループ
- Analog in 0 の値を読み取る
- Analog in の値の範囲は、0〜1024
- Serialで一度に出力できる範囲は、0〜255 (1 BYTE)
- 入力値を、0〜255の範囲にマッピング (map関数)
- シリアルで補正した値を送信
- 一定間隔静止して、繰り返す
- setup() – 初期設定
int in0; //アナログ入力0 int outByte; //シリアルで出力する値 void setup(){ //シリアル通信開始 Serial.begin(9600); } void loop(){ //アナログ入力0番ピンの値を読み取り(0~1023) in0 = analogRead(0); //値を、0〜255の範囲にマップ outByte = map(in0, 0, 1023, 0, 255); //シリアルでoutByteを送信(BYTEフォーマット) Serial.print(outByte,BYTE); //1秒間に10回ループ delay(100); }
- Processing側プログラム
- setup() – 初期設定
- シリアルポートを設定
- Serialクラスを初期化
- serialEvent() – シリアルイベント
- シリアル通信でデータを受信した際に発生するイベント
- read() で値を取得する (0〜255)
- 取得した値をモニタする – println()
- draw() – 描画
- 取得した値を背景のグレースケールのレベルに対応させている
- setup() – 初期設定
import processing.serial.*; // Serialクラスのインスタンス Serial myPort; // シリアルポートから取得したデータ(Byte) int inByte; void setup() { size(640, 640); // Macのシリアルのリストの最初のポートがFTDIアダプタのポート String portName = Serial.list()[0]; // ポートとスピードを設定して、Serialクラスを初期化、 myPort = new Serial(this, portName, 9600); } void draw() { // シリアルから取得した値を背景色に設定 background(inByte); } void serialEvent(Serial p){ // 設定したシリアルポートからデータを読み取り inByte = myPort.read(); }
- 完成!
- 可変抵抗の値を変化させると、背景色の濃度が変化する
サンプル2:複数の値を送信
- 複数のセンサーからの値を取得するには
- Arduinoには、Analog in が最大5つまで使用できる
- 複数のAnalog入力の値を取得してみる
- まずは可変抵抗でテスト
- ブレットボードとArduinoの配線例
- ArduinoとProcessinを連携する際の注意
- Arduinoからのシリアル出力は、値が順番に送られる
- 例:入力が3つ(byte0, byte1, byte2)の場合
- byte0, byte1, byte2, byte0, byte1, byte2, ….
- Processingの受信方法を工夫しないと、値がずれてしまう場合がある
- 例:
- 012012012012… – 想定した値
- 120120120120… – 順番がずれた値
- 順番がずれてしまわないように、Processing側で値のセットを受け取ったら読み込み完了の合図を送る
- 同期のイメージ
- Arduino
int in0, in1, in2; //アナログ入力0 int outByte0, outByte1, outByte2; //シリアルで出力する値 void setup(){ //シリアル通信開始 Serial.begin(9600); } void loop(){ //アナログ入力0〜2番ピンの値を読み取り(0~1023) in0 = analogRead(0); in1 = analogRead(1); in2 = analogRead(2); //値を、0〜255の範囲にマップ outByte0 = map(in0, 0, 1023, 0, 255); outByte1 = map(in1, 0, 1023, 0, 255); outByte2 = map(in2, 0, 1023, 0, 255); //Processingと同期 if(Serial.available()>0){ //シリアルでoutByteを送信(BYTEフォーマット) Serial.print(outByte0,BYTE); Serial.print(outByte1,BYTE); Serial.print(outByte2,BYTE); } //1秒間に10回ループ delay(100); }
- Processing
import processing.serial.*; // Serialクラスのインスタンス Serial myPort; // シリアルポートから取得したデータ(Byte) int inByte0, inByte1, inByte2; void setup() { size(640, 640); // Macのシリアルのリストの最初のポートがFTDIアダプタのポート String portName = Serial.list()[0]; // ポートとスピードを設定して、Serialクラスを初期化、 myPort = new Serial(this, portName, 9600); noStroke(); smooth(); } void draw() { background(inByte0); fill(inByte1); float diameter = float(inByte2)/255.0*width; ellipse(width/2, height/2, diameter, diameter); } void serialEvent(Serial p){ //Arduinoから送られてきたデータが3個来たら if(myPort.available()>2){ //順番にデータを読み込む inByte0 = myPort.read(); inByte1 = myPort.read(); inByte2 = myPort.read(); //Arduinoへ読み込み完了の合図を送る myPort.write(255); } } //マウスが押されたら通信開始 void mousePressed(){ //バッファ領域を空にする myPort.clear(); //合図用データを送る myPort.write(255); }
- 可変抵抗の設定で、背景色、描画色、円の大きさが変化する
サンプル3:光センサーを使う
- 可変抵抗でなくても、変化するアナログ値であれば、なんでも利用可能
- 可変抵抗を各種センサーに入れ替えてみる
- 光センサー (CdSセル)
- 測距センサー (赤外線センサー)
- 感圧センサー
- 振動センサー
- 曲げセンサー
- 温度センサー
- 傾きセンサー
- まずは、光センサーを使用してみます
- Arduinoと、Processingのプログラムは、そのまま流用可能
- ブレットボードとArduinoの配線例
- センサー部分拡大
サンプル4:温度センサーを使う
- 温度センサーをつかって、温度に反応するようにしてみる
- LM35DZ – 温度センサー、0℃で0V、20℃で200mVになる
- ブレットボードとArduinoの配線例
課題:センサーの値を視覚化する
- Generative Gestaltungのコードを活用して、Arduinoにとりつけたセンサーや可変抵抗、スイッチなどを操作すると形態や動きが変化するプログラムをProcessingで作成する。
- 使用するセンサーは自由に選択してください。温度センサー、光センサー、可変抵抗以外のものでもOK
- 複数のセンサー、可変抵抗を組み合せても構いません
- 次回の月曜の授業まで!
課題のサンプル
- Generative Gestaltungの”M_1_2_01″を改造して作成
- マウスのX座標によって変化する変数”faderX”を、シリアル入力の値に変更
- 色も微妙に変化させている
- Arduino側のコードは、サンプル1と一緒
int in0; //アナログ入力0 int outByte; //シリアルで出力する値 void setup(){ //シリアル通信開始 Serial.begin(9600); } void loop(){ //アナログ入力0番ピンの値を読み取り(0~1023) in0 = analogRead(0); //値を、0〜255の範囲にマップ outByte = map(in0, 0, 1023, 0, 255); //シリアルでoutByteを送信(BYTEフォーマット) Serial.print(outByte,BYTE); //1秒間に10回ループ delay(100); }
- Processing側コード
- Generative Gestaltung M_1_2_01 を改造
import processing.serial.*; import processing.pdf.*; boolean savePDF = false; int actRandomSeed = 0; int count = 360; // Serialクラスのインスタンス Serial myPort; // シリアルポートから取得したデータ(Byte) int inByte; void setup() { size(800, 800); colorMode(HSB, 360,100,100,100); cursor(CROSS); smooth(); // Macのシリアルのリストの最初のポートがFTDIアダプタのポート String portName = Serial.list()[0]; // ポートとスピードを設定して、Serialクラスを初期化、 myPort = new Serial(this, portName, 9600); } void draw() { if (savePDF) beginRecord(PDF, timestamp()+".pdf"); background(0); noStroke(); float faderX = inByte/255.0; randomSeed(actRandomSeed); float angle = radians(360/float(count)); for (int i=0; i