yoppa.org


immediate bitwave

バイオメディア・アート

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関数)
      • シリアルで補正した値を送信
      • 一定間隔静止して、繰り返す
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() – 描画
      • 取得した値を背景のグレースケールのレベルに対応させている
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