まゆたまガジェット開発逆引き辞典

電子工作やプログラミングのHowtoを逆引き形式で掲載しています。作りたいモノを決めて学んでいくスタイル。プログラマではないので、コードの汚さはお許しを。参照していないものに関しては、コピペ改変まったく問いません

MESHのデータをProcessingに送ってアニメーションさせる

Bluetooth通信でスマホタブレットにセンサーのデータを簡単に送れるSonyのMESH。
このセンサーのデータをIFTTT+Googleスプレッドシート経由でProcessingに送って、アニメーションの速度と色を変えてみました。
APIを使っていないので、Googleスプレッドシートにどれだけの回数アクセスしても大丈夫か判断がつかなかったため、データのローディングはかなりゆっくりです。
テストなので見た目関係なしのシンプルなコードです。

f:id:prince9:20171026023211g:plain

テキストプログラミングさえいらず、ブロックをつなげていくことでプログラミングをするのでIoTデバイスの試作に便利です。
成人男性の親指くらいの大きさに電池・センサー・通信できるチップが入っていて、小さくて良いですね。
MESHは専用のスマホタブレットアプリをプログラミングをして動作させますが、複数のWebサービスを連携させる「IFTTT」を使えばGoogleスプレッドシート経由で他の開発環境にデータを送ることができます。
GoogleスプレッドシートのデータをJSONXML化して、それをProcessingなりUnityなりで読み込みます。

またGPIOというタグを使って、Arduinoやラズパイ経由でMESHにないセンサーや出力を使うことができます。
Bluetoothのパケットを解析して公式アプリを介さずに自作アプリでデータを直接やりとりする方法もあるようです(公式からのアナウンスはなし)。

ひとまずいちばん楽なIFTTTを使ってProcessingに「動きタグ」のデータを送ってみます。
まず大まかな流れとしては、

  1. IFTTTのアカウント作成を行い、MESHアプリのIFTTTタグでアカウントの紐付けを行う
  2. IFTTTにログインした状態で、アプレットを作成する
  3. GoogleドライブからGoogleスプレッドシートを作成し、スクリプトエディタでスクリプトを入力する
  4. MESHアプリで動きタグを振るとGoogleスプレッドシートにそのデータが記録される
  5. GoogleスプレッドシートのIDを確認し、「https://spreadsheets.google.com/feeds/list/GoogleスプレッドシートのID/od6/public/basic?alt=rss」をメモしておく
  6. https://spreadsheets.google.com/feeds/list/GoogleスプレッドシートのID/od6/public/basic?alt=rss」がXMLのアドレスになるので、ProcessingやUnityなどで読み込んで使う

なぜかGoogleスプレッドシートJSONをProcessingで読み込んで使おうとするとnull(空)になってしまうので、今回はXMLでやってみました(原因追求中。Googleスプレッドシート以外のJSONはOKでした。JSON自体は読み込めているのですが、各要素にアクセスできない)。

では細かく手順を追っていきます。

1.PCからhttps://ifttt.com/にアクセスし、Email adressにメールアドレスを入力してアカウントを作成する
2.https://ifttt.com/session/new?wp_=1 から作成したアカウント名とパスワードを入力してログインする
3.MESHアプリを立ち上げ、連携タグの+をタップして出てきたIFTTT Keyをメモっておく(初回のみ)
4.PCでIFTTTにログインした状態で、Searchをクリックし「MESH」と入力してリターンキーを押す
5.Settings→Edit connectionをクリックし、メモったキーを入力する
f:id:prince9:20171026025241p:plain
6.https://ifttt.com/my_applets のNew Appletをクリックしてアプレットを作成する
7.ifの後ろの+アイコンをクリックして、Search serviceに「MESH」と入力する
8.Event from MESH~をクリックし、EventIDに英語で分かりやすいIDを入力する 例:check1 など
9.Create triggerをクリックする
10.thenの後ろの+をクリックして、Search serviceに「Google Drive」と入力する
11.Connectをクリックし、Googleのアカウントとパスワードを入力してログインする
12.許可をクリックする
13.Add row to spreadsheetをクリックし、Spreadsheet nameに英語で名前をつける。Drive Folder Pathも設定しておく

f:id:prince9:20171026025331p:plain

14.Create actionをクリックする
15.Finishをクリックする
16.Googleドライブにアクセスして新規からフォルダを作成し、Drive Folder Pathで入力したフォルダ名でフォルダを作る
17.新規からGoogleスプレッドシートを選択し、Add row to spreadsheetでつけた名前で新しいスプレッドシートを作成する

f:id:prince9:20171026032702p:plain

18.「ツール」メニュー→スクリプトエディタを選択し、下記を入力する
今回はテストなので下記
recipe.meshprj.com
を参照させて頂きました。

function myFunction() {
 
}


function onEdit(event) {
 var Spreadsheet = SpreadsheetApp.getSctiveSpreadsheet();
 var Sheet = Spreadsheet.getSheetByName("シート1");
 var LastRow = Sheet.getLastRow();
 var value = Sheet.getRange(LastRow,2).getValue();

 //openByIDはスプレッドシートのURLである「https://docs.google.com/spreadsheets/d/abcd/edit#gid=0」の abcdの部分
var MESH = SpreadsheetApp.openByID('abcd');
 var MESH_Sheet = MESH.getSheetByName("シート1");
 
 var d = new Date();
 MESH_Sheet.getRange(4,2).setValue(Utilities.formatData(d,'JST','yyyy年M月d日 HH:MM:SS'));
 MESH_Sheet.getRange(4,3).setValue(value);
  
 
}




function reset(event) {
 var sheet = SpreadsheetApp.getActiveSheet();
 sheet.clear();
 
}

19.スクリプトを保存する
20.MESHアプリを立ち上げて動きタグを準備した状態で下記のように接続する。スピーカーはセンサー動作確認用
f:id:prince9:20171026030715p:plain
21.IFTTTのアイコンをタップし、イベントIDにIFTTTで設定したEventIDを入力する
22.「送信する」を選択して「データを追加」をタップする
23.今回は「振られた強さ」をタップしてOKを押す
24.この状態で動きタグを振るとGoogleスプレッドシートにデータが書き込まれる

■ここから開発環境「Processing」の場合

25.Processingを立ち上げ、下記のコードを入力する。動きタグのデータが大きいほどスピードが上がり、色が変化します
XMLの部分はこちら
memorandums.hatenablog.com
を参考にさせて頂きました。
一定時間ごとにスプレッドシートを見に行ってます。どうも見に行った瞬間アニメーションが固まってしまうみたいなので、そこが要修正ですが・・・

float[] numberArray = {};

int acc1,acc2;
float acc3;   
float Max = 10;       
float X;             
float Spx;        
float Acx;    

void setup() {
size(600,600);
colorMode(HSB, 360, 100, 100);
  background(0,0,99);
  
  X = 0;
  Spx = 0;
  Acx =  0.25;
  
}


void draw() {

  if( frameCount%250 == 0){
        readXML();
  }
  
   fadeToWhite();

   for (int i = 0; i < numberArray.length; i++) {
Acx = numberArray[i];
}

   Spx = Spx + Acx;            


  if (Spx > Max) {
Spx = Max; 
}

  X = X + Spx;        
  
//もし、xの値が画面の幅以上になったら、xを0に戻す
  if (X >= width) {    
    X = 0;
  }
  noStroke();

fill(acc2,100,100);
  rectMode(CENTER);
  rect(X, height/2, 10, 10);
  
  
}

//list/abcd/の「abcd」はスプレッドシートのURLである「https://docs.google.com/spreadsheets/d/abcd/edit#gid=0」の abcdの部分

void readXML() {
  XML xml = loadXML("https://spreadsheets.google.com/feeds/list/abcd/od6/public/basic?alt=rss");
XML[] items = xml.getChild("channel").getChildren("item");



for (XML item : items) {
    String data = item.getChild("description").getContent();

//「data:_10」という形の文字列で出力されるので、スペースで区切る
String[] q = splitTokens(data, " ");
//「10」だけ取り出して整数に変換
acc1 = new Integer(q[1]);
acc2 = acc1 *10;
acc3 = acc1/100.0;
}

numberArray = append(numberArray,acc3);
  

println(numberArray);
}

void fadeToWhite() { 
  noStroke();
  fill(acc2,0,100);
  rectMode(CORNER);
  rect(0, 0, width, height);
}

Processingで曲線を描くときに楽できるツール

Processingで思ったような曲線を描くのがめんどいのーと検索してたところ、こんなツールがあったのでご紹介です。
Illustratorのようにハンドルを動かすと、自動的にvertexとbezierVertexの座標を出してくれます。

www.khanacademy.org

こんな感じです。

f:id:prince9:20170901053601p:plain

void setup() {
  size(600,600);
 noLoop();
}

void draw() {
  background(255);
  fill(0);
 beginShape();
vertex(150,43);
bezierVertex(220,107,224,173,156,252);
bezierVertex(204,166,200,102,150,43);
endShape();
}

Processingでイラレから出力したSVGを使う

Processingで全自動生成したいところですが、自分の気にいったパーツを使いたいというときもあるハズ。
ということで、ProcessingにSVGファイルを読み込ませて、複数個ランダムな位置・大きさ・角度にしてみました。
イラレから書き出すときに設定に気をつけないと、Processingで読み込んだときにいちばん下にあるパーツの形しか表示してくれませんでした。色も抜け落ちます。

まずはIllustrator(CC2017)から下記の設定でSVGを書き出します。
f:id:prince9:20170825022839p:plain
ファイル→書き出し→書き出し形式でSVGにすればOKです。背景というかアートボードを白の状態にしていても、Processingで読み込んだときにちゃんとオブジェクトのみ表示してくれます。
このことが分かりやすいように、Processingの背景を黒にしています。

実際読み込むSVGファイルがこれ。
f:id:prince9:20170825023324p:plain

今回の結果がこれです。
f:id:prince9:20170825023414p:plain

書き出した後はProcessingに移り、下記を入力します。

PShape s1;

int x,y; //位置ランダム
float r;//大きさランダム


void setup() {
  size(600, 600);
   background(0);
   noLoop();
 smooth();
 
//SVGファイル
  s1 = loadShape("test6.svg");
}


void draw() {
    background(0);
  

   for (int i = 0; i < 10; i++) {
     
       r = random(42.71,170.87);
    x = int(random(0, 600));
  y = int(random(0, 600));
  //回転
  s1.rotate(random(0,359));
  shape(s1,x,y,r,r);

}
}


void mousePressed() {
      redraw();// ボタンが押されたら再描画
}

Processingで集中線を描く

集中線はあまり使わないかもですが、線を一定角度回転させるということはありそうなのでメモです。
太さをランダムに、そして線の角の種類を変えることで、集中線っぽくしてます。

f:id:prince9:20170824075013p:plain

//角度。小さくすると密度が増える
int angle = 3;


void setup() {
  size(600,600);
 noLoop();
}

void draw() {
  background(255);
  translate(width/2.0, height/2.0);
  pushMatrix();
  for (int i = 0; i < 360/angle; i++) {

    //中心が原点で、角度ぶん回転させてる
  rotate(radians(angle));
  stroke(0);
  //線の太さをランダムにすることで、集中線っぽさを出す
  strokeWeight(int(random(1,6)));
  //線の角が四角になるように
  strokeCap(SQUARE);
  line(0, 0, 400, 400);

}

  noStroke();
  fill(255);
   ellipse(0, 0, 200,400);
 popMatrix();
}

Processingで紙ふぶきを描く

よくイラストで飛んでる三角形です。
色数多すぎたかも・・・完全に形までランダムだといびつになったりするので、欲しい三角形の形を拡大縮小と回転させたほうがよさげです。

f:id:prince9:20170824041659p:plain

int tx,ty;
//三角形の数
  int triangleCount = 20;
  
//最大個数分、または色のパターンの数配列を用意する
 int[] colt = new int[triangleCount];
 
 color[] colarray = 
{ 
#263716,#f16343,#9774c7,#7b6c30,#f32cd5,#e4dfb2,#17cfc8,#8bac33,#315d21,#eee9e6,#e8cb37,#f16bb4,#92cedc,#2a45e7,#720e29,#f20943,#ffffff
};

void setup() {
  size(600,600);
   background(255);
   noLoop();
    smooth(); 
}

void draw() {
  background(255);
   for(int c = 0; c < colt.length; c++){
  //色の乱数生成、小さい三角。ランダムの数値は色の種類の数
  colt[c] = int(random(17));
}



  
  //0から600の間で、triangleCountの個数分ランダムに描く。実際はtranslateでランダムに移動させている
 for (int n = 0; n < triangleCount; n++) {
   noStroke();
fill(colarray[colt[n]]);
   tx = int(random(600));
  ty = int(random(600));
  sankakuR();
}

 
 
}

void sankakuR() {
  pushMatrix();
  translate(tx,ty);
  //拡大縮小
  scale(random(0.5,3.0));
  //回転
  rotate(radians(random(359)));
  
  triangle(29,36,11,62,43,56);
   popMatrix();
  
  
 }

void mousePressed() {
      redraw();// ボタンが押されたときだけ実行
}

Processingでコロナみたいなのを描く

ロマサガ3の死食(日食)っぽい?
こちらfrilly ring - OpenProcessing
でProcessing.jsのモードになってたので、P5モードかつマウスクリックでランダムに形が切り替わるようにしました(ので変数名変えてないです)。
参考にさせて頂きました。ありがとうございます。
あまりコード変わってないですが、P5でやりたい方のお役に立てば。

f:id:prince9:20170824030110p:plain



float r1,r2,radian;
float nScale = 0.003;

PVector nOffset1,nOffset2,v1,v2;



void setup() {
 size(600, 600);
  background(255);
noLoop();
  
}

void draw() {

    background(0);



   


    nOffset1 = new PVector(random(10000), random(10000));
  nOffset2 = new PVector(random(10000), random(10000));
  
  translate(width / 2, height / 2);
  beginShape(QUAD_STRIP);
      stroke(255);
    fill(255);
  for(float angle = 0; angle <= 360; angle += 2) {
    radian = radians(angle);
    v1 = new PVector(100 * sin(radian) * nScale, 100 * cos(radian) * nScale);
    v2 = new PVector(300 * sin(radian) * nScale, 300 * cos(radian) * nScale);

//サイズを小さくしたいときは、r1とr2の50,125のあたりをいじるとOK(元は100, 250)
    r1 = map(noise(v1.x + nOffset1.x, v1.y + nOffset1.y, 30 * 0.01), 0, 1, 50, 125);
    r2 = map(noise(v2.x + nOffset2.x, v2.y + nOffset2.y, 30 * 0.01), 0, 1, 50, 125);
    vertex(r1 * sin(radian), r1 * cos(radian));
    vertex(r2 * sin(radian), r2 * cos(radian));
    

   
  

  
  }
  endShape();
  

     
}

void mousePressed() {

      redraw();// ボタンが押されたときだけ再描画
      
}

Processingで折れ線グラフみたいなのを描く

折れ線グラフ的なものが欲しかったので、作ってみました。
こちらneralt.com
を参照させて頂きました。
イメージ背景に使えそうですね。

こんな感じです。
f:id:prince9:20170823024123p:plain

三角形やらと組み合わせると、こんなのもできます。
f:id:prince9:20170823024203p:plain

  color[] colarray = 
{ 
#fdf4ac,#3de3d6,#b564c5,#f1709c,#ffbe8e,#413d79,#ffffff
};

int graphx,graphy;

void setup(){
  size( 600, 600 );
  background(255);
  smooth();
  noLoop();
}
 
 
void draw(){
   background(255);
 beginShape();
  for (graphx = 0; graphx < width; graphx+=20) {
    graphy = int(random(100,300)); 
    noFill();
    stroke(colarray[(int)random(7)]);
strokeWeight(3);
    vertex(graphx,graphy);
    
    ellipse(graphx,graphy,5,5);
ellipse(graphx,graphy,10,10);
    
  
  }
    
 endShape();
}

void mousePressed() {

      redraw();// ボタンが押されたときだけ再描画
      
}