2012/02/16

ProcessingとArduinoをくっつける

【本日のお便りコーナー】

twitter4Jかー。この前購入してたarduino使うのかと思ってた∩(・ω・)∩2012年2月16日 9:7 via HootSuite

—— というわけで、今日は Processing と Arduino を合体させてこんなの(↓)を作ってみようと思います。わー(歓声) ぱちぱち(拍手) ……あ、ちなみにこれの正体は最後に明らかになりますよ。



—— とは言ったものの、Processing と Arduino を連繋させる方法が見当もつきません。どこかにいいサンプルはないかと探していたら、こちらの記事を見つけたので参考にする事にしました。


【配線】

まずは Arduino の配線です。13 番ピンに LED を挿すらしいです(※ ピンぼけ容赦)。
LEDのアノードを13番ピンに、カソードをGNDに接続


【スケッチ(クリックで拡大)

左側が Arduino スケッチ、右側が Processing スケッチです。サンプルとほとんど一緒。

今回は、配線 → Arduinoスケッチのアップロード → Processing スケッチの実行の順に行いました。あまり厳密にやらなくてもよさそうですが。

注意点としては、Processing 側の以下の箇所。
  1. myPort = new Serial(this, Serial.list()[1], 9600);  
コンストラクタの第2引数には Arduino が接続されているポートを指定してやる必要があります。

ここで使用しているSerial クラスの list(); メソッドは、使用可能なポート名の配列を返すメソッドです。その中から適切なポートを選んでやればよいみたいですね(僕の環境では [1] )。

もしも何番のポートを選べばよいか判らない場合は、一度 Serial.list(); を実行して有効なポート名を列挙し、Arduino が接続されているポートと一致するインデックスを探すのがよいと思います。


【実行結果】

マウスボタンを押下すると LED が点灯し、離すと消灯します。




次に、Arduino からデータを送ってみる事にします。

……で、そのサンプルがこちらなのですが、残念ながら僕は可変抵抗器を持っていません。しかも、近所に電子部品を売っているお店がないので、とりあえず CdS セルで代用してみようと思います。

まずは CdS セルのおさらいも兼ねて、Arduino だけをいじってみる事にします。


【配線】

CdS セル と LED を使ってこんな感じの配線をします。

実写だとこんな感じ。

画像では見づらいですが、CdS セルをアナログ入力用の 0 番ピンに、LED を出力の 9 番ピンにそれぞれ繋いでいます。


【Arduino スケッチ】

次に、以下のようなコードを書いて、Arduino に送ります。

  1. #define LED 9  
  2. int val = 0;  
  3.   
  4. void setup() {  
  5.   pinMode(LED, OUTPUT);  
  6. }  
  7.   
  8. void loop() {  
  9.   val = analogRead(0);  
  10.     
  11.   analogWrite(LED, val/4);  
  12.   delay(10);  
  13. }  


上記のソースの 9 行目にある
  1. val = analogRead(0);  
は、アナログ入力ピンの電圧を調べる関数です。Arduino は AD コンバータによって、0 ~ 5 [V] の入力電圧を 0 ~ 1023 の数値に変換しているため、変数 val は 0 ~ 1023 の範囲をとる事になります。


【実行結果】

これで、明るさに応じて LED の光の強さが変わるものができました。


このサンプルで得た電圧のデータを Processing に送ってやれば、今までにできなかった事ができるようになるのではないでしょうか。



やってみましょう。


【配線】

とりあえず、LED はもう要らない子なのでブレッドボードから外し、以下のような配線に戻します。



【Arduino スケッチ】
  1. int val = 0;  
  2.   
  3. void setup() {  
  4.   Serial.begin(9600);  
  5. }  
  6.   
  7. void loop() {  
  8.   val = analogRead(0);  
  9.     
  10.   // valを0~255の範囲に正規化してP5に送る  
  11.   Serial.write(map(val, 0, 1023, 0, 255));    
  12.   delay(100);  
  13. }  


【Processing スケッチ】
  1. import processing.serial.*;  
  2. Serial myPort;  
  3.   
  4. int val;  
  5.    
  6. void setup()  
  7. {  
  8.   size(400300);  
  9.     
  10.   String port = Serial.list()[1];  
  11.   myPort = new Serial(this, port, 9600);  
  12. }  
  13.    
  14. void draw()  
  15. {  
  16.   // 電圧の強さに応じて背景色が変わるよ  
  17.   background(val);  
  18. }  
  19.    
  20. void serialEvent(Serial p){  
  21.   // Arduinoからデータを読み取り  
  22.   val = myPort.read();  
  23. }  


【実行結果】

CdS セルに充分な光が当たっているときは下図左、センサを手で完全に覆い隠すと下図右のようになりました。


基本的に、一度に Arduino とやり取りできるデータ量が 8 bits なので、簡単のために val の範囲を 0 ~ 255 に正規化しています(0 ~ 1023 のデータも、一応がんばれば送る事はできますが)。



【おまけ】

最後に、電圧の変化を無駄にビジュアル化してみます。


Arduino のスケッチはそのままで、Processing の方を以下のように書き換えるだけです。

【Processing スケッチ】
  1. import processing.serial.*;  
  2. Serial myPort;  
  3.   
  4. PFont font;  
  5.   
  6. int   index;  
  7. int[] data;  
  8.   
  9. int   val;  
  10. long  time;  
  11.   
  12. void setup()  
  13. {  
  14.   size(640480, P3D);  
  15.     
  16.   font = createFont("Meiryo"20);  
  17.     
  18.   index = 0;  
  19.   data  = new int[width];  
  20.   for(int i = 0; i < data.length; ++i) data[i] = -1;  
  21.     
  22.   String port = Serial.list()[1];  
  23.   myPort = new Serial(this, port, 9600);  
  24. }  
  25.   
  26. void draw()  
  27. {  
  28.   background(0);  
  29.   camera(0, -0xFF,   width,   
  30.          0, -0xFF/20,   
  31.          0,  1,      0);  
  32.            
  33.   
  34.   float angle = radians(time) * 0.1f;  
  35.   rotateY(angle);  
  36.     
  37.   pushMatrix();  
  38.   translate(-width/2, -0xFF0);  
  39.     
  40.   int prevY = 0xFF;  
  41.   for(int x = 1; x < width; ++x) {  
  42.     int v = data[(x + index) % data.length];  // 電圧: 0 ~ 255  
  43.     int y = 0xFF - v;  // y座標値  
  44.   
  45.     stroke(255, v);  
  46.     if(prevY < 0xFF) line(x - 1, prevY, x, y);  
  47.     prevY = y;  
  48.   }  
  49.   popMatrix();  
  50.     
  51.   // じめん  
  52.   stroke(02550100);  
  53.   for(int i = -width/2; i <= width / 2; i += 40) {  
  54.     line(-width/20, i, width/20, i);  
  55.     line(i, 0, -width/2, i, 0, width/2);  
  56.   }   
  57.     
  58.   pushMatrix();  
  59.   camera();  
  60.   hint(DISABLE_DEPTH_TEST);  
  61.   textMode(SCREEN);  
  62.   // 1単位あたりの分解能: 5000[mV] / 255 ≒ 19.6[mV]  
  63.   text("Voltage: " + (val * 19.6) + " [mV]"1010);  
  64.     
  65.   hint(ENABLE_DEPTH_TEST);  
  66.   popMatrix();  
  67.     
  68.   ++time;  
  69. }  
  70.    
  71. void serialEvent(Serial p){  
  72.   // Arduinoからデータを読み取り  
  73.   val = myPort.read();  
  74.     
  75.   index = (index + 1) % data.length;  
  76.   data[index] = val;  
  77. }  

2 件のコメント:

  1. 楽しい記事でした&参考になりました。

    返信削除
  2. 非常に参考になりました。ちょうど、大学の課題で作りたいと思っていたものに必要な知識だったので、すごく助かりました。

    返信削除

ひとことどうぞφ(・ω・,,)