チーム1364

課題名

距離センサーを使った動的なデジタルアート

研究者名

2年14組52番 保坂駿
2年14組51番 藤原理奈

解説

使用機材

基盤
PSoCMiniPrag
距離センサー
シリアル通信ケーブル
ジャンパー線

概要

プロジェクトその1は距離センサーに手が近づくと線を外に向かってだんだんと描き、手を離すと線が周りから消えていくものである。
一番外側まで線が描かれると全部消え、最初からまた描かれ始める。

・手をかざしているとき
processing2_1.PNG

・手を離したとき
processing2_2.PNG


プロジェクトその2は距離センサーに手が近づくと絵を描き、手を素早く振りかざすと絵も素早く描かれる。また、手を離すと描かれた絵はだんだんと消えていく。

・手を普通にかざしたとき
processing1_1.PNG

・手を素早く振りかざしたとき
processing1_2.PNG



PSoCでの処理

距離センサーでかざした手の位置を把握し、その情報を送信する。

・手をかざしてないとき
PSoC1.jpg

・手をかざしたとき
PSoC2.jpg

・ブロック図
PSoC3.png





ソースコード

PSoC


#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#include <stdlib.h>


void main(void)
{
  // M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts
   // Insert your main routine code here.
   
   //analog data register
   unsigned int adc_data;
   char buff[10];
   int i;
   PGA_Start(PGA_HIGHPOWER);
   LCD_Start();
   LCD_InitBG(LCD_SOLID_BG);
   M8C_EnableGInt;
   ADCINC_Start(ADCINC_HIGHPOWER);
   ADCINC_GetSamples(0);
   
   Counter8_WritePeriod(155);
    Counter8_WriteCompareValue(77);
    Counter8_Start();
   UART_CmdReset();
   UART_Start(UART_PARITY_NONE);
   UART_CPutString("\r\nUART start\r\n");
   
   while(1){
           while(ADCINC_fIsDataAvailable()==0);
           adc_data=ADCINC_wClearFlagGetData();
           LCD_Position(0,0);
           //LCD_PrHexInt(adc_data);
           
           if(adc_data < 1479){//LEDがついていないときLED OFFとLCDに表示させる
              LCD_PrCString("LED OFF");
              UART_PutChar('F');
           }else{//LEDがついている間LCDにLED ONと表示させる
              LCD_PrCString("LED ON!");
              UART_PutChar('T');
           }
           LCD_DrawBG(1,0,16,(adc_data/50));
   }
}

processing その1

import processing.serial.*;
Serial myPort;
boolean flg=false;

final int width=640;
final int height=640;

int dataCountT=0;
int dataCountF=0;

int s=0;
int r=100;

void setup(){
size(width,height);
myPort = new Serial(this,"COM4",38400);
frameRate(10);
 background(255);
}

void draw(){
noFill();
 if(flg){
   s++;
   //stroke(0);
   //stroke((dataCountT)%250,0,255-(dataCountT%250),100);
   //stroke((s*5)%250,0,255-((s*5)%250),100);
   dataCountT=dataCountT%300;
   //red
   if(dataCountT<100){
     stroke(dataCountT*2+50,0,0,100);
   }
   //blue
   else if(dataCountT<200){
     stroke(0,(dataCountT-100)*2+50,0,100);
   }
   //green
   else{
     stroke(0,0,(dataCountT-200)*2+50,100);
   }
   strokeWeight(1);
 }else{
   if(s<0)s=0;
   stroke(255);
   strokeWeight(3);
 }
 int x,y;
 int dx,dy;
 r=s*3;
 x=(int)(r*cos(s))+width/2;
 y=(int)(r*sin(s))+height/2;
 dx=(int)(r*cos(s+PI/2))+width/2;
 dy=(int)(r*sin(s+PI/2))+height/2;
 line(x,y,dx,dy);
 if(width<x| |height<y){
   background(255);
   s=0;
 }
 if(!flg){
   s--;
 }
 
}

void serialEvent(Serial p){
char str = 'N';
 str = myPort.readChar();
 //println(str);
 if(str=='T'){
   if(flg){
     dataCountT++;
   }else{
     dataCountT=1;
   }
   flg=true;
 }else{
   if(!flg){
     dataCountF++;
   }else{
     dataCountF=1;
   }
   flg=false;
 }
 println("dataCountT:"+dataCountT);
 println("dataCountF:"+dataCountF);
 
}


processing その2

import processing.serial.*;
Serial myPort;

int num,cnt,fadeInterval;
Particle[] particles;
boolean initialised=false,doClear=false;
float lastRelease=-1,scMod,fadeAmount;
boolean flg=false;
int dataCountT=0;
int dataCountF=0;

void setup() {
size(1024,600);
 background(255);
 smooth();
 myPort = new Serial(this,"COM4",38400);
 rectMode(CENTER);
 ellipseMode(CENTER);
 
 cnt=0;
 num=150;
 particles=new Particle[num];
 for(int i=0; i<num; i++) particles[i]=new Particle();

reinit();
 
}

void draw() {
 if(flg| |dataCountF<30){
   if(doClear) {
     background(255);
     doClear=false;
   }
   noStroke();
   if(frameCount%fadeInterval==0) {
     fill(255,255,255, fadeAmount);
     rect(width/2,height/2, width,height);
   }  
   updateAuto();
   
   for(int i=0; i<num; i++) 
     if(particles[i].age>0) particles[i].update();
 }else{
   if(!flg&&dataCountF%15==0){
     fill(255,255,255, fadeAmount);
     rect(width/2,height/2, width,height);
   }
 }
}

void serialEvent(Serial p){
 char str = 'N';
 str = myPort.readChar();
 //println(str);
 if(str=='T'){
   if(flg){
     dataCountT++;
   }else{
     dataCountT=1;
   }
   flg=true;
 }else{
   if(!flg){
     dataCountF++;
   }else{
     dataCountF=1;
   }
   flg=false;
 }
 println("dataCountT:"+dataCountT);
 println("dataCountF:"+dataCountF);
 
}

void reinit() {
doClear=true;
 scMod=random(1,1.4);
 fadeInterval=(int)random(220,300);
 fadeAmount=random(30,60);
for(int i=0; i<num; i++) particles[i].age=-1;
 initAuto();
}

void mousePressed() {
//reinit();
}

AutoMover auto[];
int autoN;

void initAuto() {
autoN=(int)random(3,6);
 auto=new AutoMover[autoN];
 for(int i=0; i<autoN; i++) auto[i]=new AutoMover();
 
}

void updateAuto() {
for(int i=0; i<autoN; i++) auto[i].update();
}

class AutoMover {
Vec2D pos,posOld;
 float dir,dirD,speed,sc,dirCnt;
 int type,age,ageGoal,interval;

 
 AutoMover() {
   reinit();
 }
 
 void reinit() {
   ageGoal=(int)random(150,350);
   //if(random(100)>95) ageGoal*=1.25;
   if(ageGoal<100)ageGoal*=1.50;
   age=-(int)random(50,150);
   pos=new Vec2D(random(width-100)+50,random(height-100)+50);
   
   dir=(int)random(36)*10;
   type=0;
   if(random(100)>60) type=1;
   
   interval=(int)random(2,5);    
   if(type==1) {
     interval=1;
     dir=degrees(atan2(-(pos.y-height/2),pos.x-width/2));
   }
   
   dirD=random(1,2);
   if(random(100)<50) dirD=-dirD;
   speed=random(3,6);
   if(dataCountT<200&&dataCountF<200){
      speed*=1.5;
   }
   if(dataCountT<100&&dataCountF<100){
      speed*=2;
   }
   if(dataCountT<30&&dataCountF<30){
      speed*=2.5;
   }
   
   sc=random(0.5,1);
   if(random(100)>90) sc=random(1.2,1.6);
   dirCnt=random(20,35);

  if(type==0) {
     if(random(100)>95) sc=random(1.5,2.25);
     else sc=random(0.8,1.2);
   }
   sc*=scMod;
   speed*=sc;
 }
 
 void update() {
   age++;
   if(age<0) return;
   else if(age>ageGoal) reinit();
   else {
     if(type==1) {
       pos.add(
         cos(radians(dir))*speed,sin(radians(dir))*speed);
                  
       dir+=dirD;
       dirD+=random(-0.2,0.2);
       dirCnt--;
       if(dirCnt<0) {
         dirD=random(1,5);
         if(random(100)<50) dirD=-dirD;
         dirCnt=random(20,35);
       }
     }
     if(age%interval==0) newParticle();   
     if(pos.x<-50 | | pos.x>width+50 | |
       pos.y<-50 | | pos.y>height+50) reinit();
   }
 }
 
 void newParticle() {
   int partNum,i;

  if(type==0) dir=int(random(36))*10;
   
   i=0;
   while(i<num) {
     if(particles[i].age<1) {
       float offs=random(30,90);
       if(random(100)>50) offs=-offs;
       particles[i].init(dir+offs,pos.x,pos.y,sc);
       
       break;
     }
     i++;
   }
   
 }
}

class Particle {
Vec2D v,vD;
 float dir,dirMod,speed,sc;
 int col,age,stateCnt;
 int type;
 
 Particle() {
   v=new Vec2D(0,0);
   vD=new Vec2D(0,0);
   age=0;
 }

void init(float _dir,float mx,float my,float _sc) {
   dir=_dir;
   sc=_sc;

  float prob=random(100);
   if(prob<80) age=15+int(random(30));
   else if(prob<99) age=45+int(random(50));
   else age=100+int(random(100));
   
   if(random(100)<80) speed=random(2)+0.5;
   else speed=random(2)+2;
   if(dataCountT<200 && dataCountF<200){
      speed*=1.5;
   }
   if(dataCountT<100 && dataCountF<100){
      speed*=2;
   }
   if(dataCountT<30 && dataCountF<30){
      speed*=2.5;
   }

  if(random(100)<80) dirMod=20;
   else dirMod=60;
   
   v.set(mx,my);
   initMove();
   dir=_dir;
   stateCnt=10;
   if(random(100)>50) col=0;
   else col=1;
   
   type=(int)random(30000)%2;
 }
   
 void initMove() {
   if(random(100)>50) dirMod=-dirMod;
   dir+=dirMod;
   
   vD.set(speed,0);
   vD.rotate(radians(dir+90));

  stateCnt=10+int(random(5));
   if(random(100)>90) stateCnt+=30;
 }
 
 void update() {
   age--;
   
   if(age>=30) {
     vD.rotate(radians(1));
     vD.mult(1.01f);
   }
   
   v.add(vD);
   if(col==0) fill(255-age,0,100,150);
   else fill(100,200-(age/2),255-age,150);
   
   if(type==1) {
     if(col==0) fill(255-age,100,0,150);
     else fill(255,200-(age/2),0,150);
   }
     
   pushMatrix();
   scale(sc);
   translate(v.x,v.y);
   rotate(radians(dir));
   rect(0,0,1,16);
   popMatrix();
   
   if(age==0) {
     if(random(100)>50) fill(200,0,0,200);
     else fill(00,200,255,200);
     float size=2+random(4);
     if(random(100)>95) size+=5;
     size*=sc;
     ellipse(v.x*sc,v.y*sc,size,size);
   }
   if(v.x<0 | | v.x>width | | v.y<0 | | v.y>height) age=0;
   
   if(age<30) {
     stateCnt--;
     if(stateCnt==0) {
       initMove();
     }
   }
  } 
 
}

class Vec2D {
float x,y;

Vec2D(float _x,float _y) {
   x=_x;
   y=_y;
 }

Vec2D(Vec2D v) {
   x=v.x;
   y=v.y;
 }

void set(float _x,float _y) {
   x=_x;
   y=_y;
 }

void set(Vec2D v) {
   x=v.x;
   y=v.y;
 }

void add(float _x,float _y) {
   x+=_x;
   y+=_y;
 }

void add(Vec2D v) {
   x+=v.x;
   y+=v.y;
 }

void sub(float _x,float _y) {
   x-=_x;
   y-=_y;
 }

void sub(Vec2D v) {
   x-=v.x;
   y-=v.y;
 }

void mult(float m) {
   x*=m;
   y*=m;
 }

void div(float m) {
   x/=m;
   y/=m;
 }

float length() {
   return sqrt(x*x+y*y);
 }

float angle() {
   return atan2(y,x);
 }

void normalise() {
   float l=length();
   if(l!=0) {
     x/=l;
     y/=l;
   }
 }

Vec2D tangent() {
   return new Vec2D(-y,x);
 }

void rotate(float val) {
   // Due to float not being precise enough, double is used for the calculations
   double cosval=Math.cos(val);
   double sinval=Math.sin(val);
   double tmpx=x*cosval - y*sinval;
   double tmpy=x*sinval + y*cosval;

  x=(float)tmpx;
   y=(float)tmpy;
 }
}

import processing.serial.*;
Serial myPort;

int num,cnt,fadeInterval;
Particle[] particles;
boolean initialised=false,doClear=false;
float lastRelease=-1,scMod,fadeAmount;
boolean flg=false;
int dataCountT=0;
int dataCountF=0;

void setup() {
size(1024,600);
 background(255);
 smooth();
 myPort = new Serial(this,"COM4",38400);
 rectMode(CENTER);
 ellipseMode(CENTER);
 
 cnt=0;
 num=150;
 particles=new Particle[num];
 for(int i=0; i<num; i++) particles[i]=new Particle();

reinit();
 
}

void draw() {
 if(flg| |dataCountF<30){
   if(doClear) {
     background(255);
     doClear=false;
   }
   noStroke();
   if(frameCount%fadeInterval==0) {
     fill(255,255,255, fadeAmount);
     rect(width/2,height/2, width,height);
   }  
   updateAuto();
   
   for(int i=0; i<num; i++) 
     if(particles[i].age>0) particles[i].update();
 }else{
   if(!flg&&dataCountF%15==0){
     fill(255,255,255, fadeAmount);
     rect(width/2,height/2, width,height);
   }
 }
}

void serialEvent(Serial p){
 char str = 'N';
 str = myPort.readChar();
 //println(str);
 if(str=='T'){
   if(flg){
     dataCountT++;
   }else{
     dataCountT=1;
   }
   flg=true;
 }else{
   if(!flg){
     dataCountF++;
   }else{
     dataCountF=1;
   }
   flg=false;
 }
 println("dataCountT:"+dataCountT);
 println("dataCountF:"+dataCountF);
 
}

void reinit() {
doClear=true;
 scMod=random(1,1.4);
 fadeInterval=(int)random(220,300);
 fadeAmount=random(30,60);
for(int i=0; i<num; i++) particles[i].age=-1;
 initAuto();
}

void mousePressed() {
//reinit();
}

AutoMover auto[];
int autoN;

void initAuto() {
autoN=(int)random(3,6);
 auto=new AutoMover[autoN];
 for(int i=0; i<autoN; i++) auto[i]=new AutoMover();
 
}

void updateAuto() {
for(int i=0; i<autoN; i++) auto[i].update();
}

class AutoMover {
Vec2D pos,posOld;
 float dir,dirD,speed,sc,dirCnt;
 int type,age,ageGoal,interval;

 
 AutoMover() {
   reinit();
 }
 
 void reinit() {
   ageGoal=(int)random(150,350);
   //if(random(100)>95) ageGoal*=1.25;
   if(ageGoal<100)ageGoal*=1.50;
   age=-(int)random(50,150);
   pos=new Vec2D(random(width-100)+50,random(height-100)+50);
   
   dir=(int)random(36)*10;
   type=0;
   if(random(100)>60) type=1;
   
   interval=(int)random(2,5);    
   if(type==1) {
     interval=1;
     dir=degrees(atan2(-(pos.y-height/2),pos.x-width/2));
   }
   
   dirD=random(1,2);
   if(random(100)<50) dirD=-dirD;
   speed=random(3,6);
   if(dataCountT<200&&dataCountF<200){
      speed*=1.5;
   }
   if(dataCountT<100&&dataCountF<100){
      speed*=2;
   }
   if(dataCountT<30&&dataCountF<30){
      speed*=2.5;
   }
   
   sc=random(0.5,1);
   if(random(100)>90) sc=random(1.2,1.6);
   dirCnt=random(20,35);

  if(type==0) {
     if(random(100)>95) sc=random(1.5,2.25);
     else sc=random(0.8,1.2);
   }
   sc*=scMod;
   speed*=sc;
 }
 
 void update() {
   age++;
   if(age<0) return;
   else if(age>ageGoal) reinit();
   else {
     if(type==1) {
       pos.add(
         cos(radians(dir))*speed,sin(radians(dir))*speed);
                  
       dir+=dirD;
       dirD+=random(-0.2,0.2);
       dirCnt--;
       if(dirCnt<0) {
         dirD=random(1,5);
         if(random(100)<50) dirD=-dirD;
         dirCnt=random(20,35);
       }
     }
     if(age%interval==0) newParticle();   
     if(pos.x<-50 | | pos.x>width+50 | |
       pos.y<-50 | | pos.y>height+50) reinit();
   }
 }
 
 void newParticle() {
   int partNum,i;

  if(type==0) dir=int(random(36))*10;
   
   i=0;
   while(i<num) {
     if(particles[i].age<1) {
       float offs=random(30,90);
       if(random(100)>50) offs=-offs;
       particles[i].init(dir+offs,pos.x,pos.y,sc);
       
       break;
     }
     i++;
   }
   
 }
}

class Particle {
Vec2D v,vD;
 float dir,dirMod,speed,sc;
 int col,age,stateCnt;
 int type;
 
 Particle() {
   v=new Vec2D(0,0);
   vD=new Vec2D(0,0);
   age=0;
 }

void init(float _dir,float mx,float my,float _sc) {
   dir=_dir;
   sc=_sc;

  float prob=random(100);
   if(prob<80) age=15+int(random(30));
   else if(prob<99) age=45+int(random(50));
   else age=100+int(random(100));
   
   if(random(100)<80) speed=random(2)+0.5;
   else speed=random(2)+2;
   if(dataCountT<200 && dataCountF<200){
      speed*=1.5;
   }
   if(dataCountT<100 && dataCountF<100){
      speed*=2;
   }
   if(dataCountT<30 && dataCountF<30){
      speed*=2.5;
   }

  if(random(100)<80) dirMod=20;
   else dirMod=60;
   
   v.set(mx,my);
   initMove();
   dir=_dir;
   stateCnt=10;
   if(random(100)>50) col=0;
   else col=1;
   
   type=(int)random(30000)%2;
 }
   
 void initMove() {
   if(random(100)>50) dirMod=-dirMod;
   dir+=dirMod;
   
   vD.set(speed,0);
   vD.rotate(radians(dir+90));

  stateCnt=10+int(random(5));
   if(random(100)>90) stateCnt+=30;
 }
 
 void update() {
   age--;
   
   if(age>=30) {
     vD.rotate(radians(1));
     vD.mult(1.01f);
   }
   
   v.add(vD);
   if(col==0) fill(255-age,0,100,150);
   else fill(100,200-(age/2),255-age,150);
   
   if(type==1) {
     if(col==0) fill(255-age,100,0,150);
     else fill(255,200-(age/2),0,150);
   }
     
   pushMatrix();
   scale(sc);
   translate(v.x,v.y);
   rotate(radians(dir));
   rect(0,0,1,16);
   popMatrix();
   
   if(age==0) {
     if(random(100)>50) fill(200,0,0,200);
     else fill(00,200,255,200);
     float size=2+random(4);
     if(random(100)>95) size+=5;
     size*=sc;
     ellipse(v.x*sc,v.y*sc,size,size);
   }
   if(v.x<0 | | v.x>width | | v.y<0 | | v.y>height) age=0;
   
   if(age<30) {
     stateCnt--;
     if(stateCnt==0) {
       initMove();
     }
   }
  } 
 
}

class Vec2D {
float x,y;

Vec2D(float _x,float _y) {
   x=_x;
   y=_y;
 }

Vec2D(Vec2D v) {
   x=v.x;
   y=v.y;
 }

void set(float _x,float _y) {
   x=_x;
   y=_y;
 }

void set(Vec2D v) {
   x=v.x;
   y=v.y;
 }

void add(float _x,float _y) {
   x+=_x;
   y+=_y;
 }

void add(Vec2D v) {
   x+=v.x;
   y+=v.y;
 }

void sub(float _x,float _y) {
   x-=_x;
   y-=_y;
 }

void sub(Vec2D v) {
   x-=v.x;
   y-=v.y;
 }

void mult(float m) {
   x*=m;
   y*=m;
 }

void div(float m) {
   x/=m;
   y/=m;
 }

float length() {
   return sqrt(x*x+y*y);
 }

float angle() {
   return atan2(y,x);
 }

void normalise() {
   float l=length();
   if(l!=0) {
     x/=l;
     y/=l;
   }
 }

Vec2D tangent() {
   return new Vec2D(-y,x);
 }

void rotate(float val) {
   // Due to float not being precise enough, double is used for the calculations
   double cosval=Math.cos(val);
   double sinval=Math.sin(val);
   double tmpx=x*cosval - y*sinval;
   double tmpy=x*sinval + y*cosval;

  x=(float)tmpx;
   y=(float)tmpy;
 }
}

import processing.serial.*;
Serial myPort;

int num,cnt,fadeInterval;
Particle[] particles;
boolean initialised=false,doClear=false;
float lastRelease=-1,scMod,fadeAmount;
boolean flg=false;
int dataCountT=0;
int dataCountF=0;

void setup() {
size(1024,600);
 background(255);
 smooth();
 myPort = new Serial(this,"COM4",38400);
 rectMode(CENTER);
 ellipseMode(CENTER);
 
 cnt=0;
 num=150;
 particles=new Particle[num];
 for(int i=0; i<num; i++) particles[i]=new Particle();

reinit();
 
}

void draw() {
 if(flg| |dataCountF<30){
   if(doClear) {
     background(255);
     doClear=false;
   }
   noStroke();
   if(frameCount%fadeInterval==0) {
     fill(255,255,255, fadeAmount);
     rect(width/2,height/2, width,height);
   }  
   updateAuto();
   
   for(int i=0; i<num; i++) 
     if(particles[i].age>0) particles[i].update();
 }else{
   if(!flg&&dataCountF%15==0){
     fill(255,255,255, fadeAmount);
     rect(width/2,height/2, width,height);
   }
 }
}

void serialEvent(Serial p){
 char str = 'N';
 str = myPort.readChar();
 //println(str);
 if(str=='T'){
   if(flg){
     dataCountT++;
   }else{
     dataCountT=1;
   }
   flg=true;
 }else{
   if(!flg){
     dataCountF++;
   }else{
     dataCountF=1;
   }
   flg=false;
 }
 println("dataCountT:"+dataCountT);
 println("dataCountF:"+dataCountF);
 
}

void reinit() {
doClear=true;
 scMod=random(1,1.4);
 fadeInterval=(int)random(220,300);
 fadeAmount=random(30,60);
for(int i=0; i<num; i++) particles[i].age=-1;
 initAuto();
}

void mousePressed() {
//reinit();
}

AutoMover auto[];
int autoN;

void initAuto() {
autoN=(int)random(3,6);
 auto=new AutoMover[autoN];
 for(int i=0; i<autoN; i++) auto[i]=new AutoMover();
 
}

void updateAuto() {
for(int i=0; i<autoN; i++) auto[i].update();
}

class AutoMover {
Vec2D pos,posOld;
 float dir,dirD,speed,sc,dirCnt;
 int type,age,ageGoal,interval;

 
 AutoMover() {
   reinit();
 }
 
 void reinit() {
   ageGoal=(int)random(150,350);
   //if(random(100)>95) ageGoal*=1.25;
   if(ageGoal<100)ageGoal*=1.50;
   age=-(int)random(50,150);
   pos=new Vec2D(random(width-100)+50,random(height-100)+50);
   
   dir=(int)random(36)*10;
   type=0;
   if(random(100)>60) type=1;
   
   interval=(int)random(2,5);    
   if(type==1) {
     interval=1;
     dir=degrees(atan2(-(pos.y-height/2),pos.x-width/2));
   }
   
   dirD=random(1,2);
   if(random(100)<50) dirD=-dirD;
   speed=random(3,6);
   if(dataCountT<200&&dataCountF<200){
      speed*=1.5;
   }
   if(dataCountT<100&&dataCountF<100){
      speed*=2;
   }
   if(dataCountT<30&&dataCountF<30){
      speed*=2.5;
   }
   
   sc=random(0.5,1);
   if(random(100)>90) sc=random(1.2,1.6);
   dirCnt=random(20,35);

  if(type==0) {
     if(random(100)>95) sc=random(1.5,2.25);
     else sc=random(0.8,1.2);
   }
   sc*=scMod;
   speed*=sc;
 }
 
 void update() {
   age++;
   if(age<0) return;
   else if(age>ageGoal) reinit();
   else {
     if(type==1) {
       pos.add(
         cos(radians(dir))*speed,sin(radians(dir))*speed);
                  
       dir+=dirD;
       dirD+=random(-0.2,0.2);
       dirCnt--;
       if(dirCnt<0) {
         dirD=random(1,5);
         if(random(100)<50) dirD=-dirD;
         dirCnt=random(20,35);
       }
     }
     if(age%interval==0) newParticle();   
     if(pos.x<-50 | | pos.x>width+50 | |
       pos.y<-50 | | pos.y>height+50) reinit();
   }
 }
 
 void newParticle() {
   int partNum,i;

  if(type==0) dir=int(random(36))*10;
   
   i=0;
   while(i<num) {
     if(particles[i].age<1) {
       float offs=random(30,90);
       if(random(100)>50) offs=-offs;
       particles[i].init(dir+offs,pos.x,pos.y,sc);
       
       break;
     }
     i++;
   }
   
 }
}

class Particle {
Vec2D v,vD;
 float dir,dirMod,speed,sc;
 int col,age,stateCnt;
 int type;
 
 Particle() {
   v=new Vec2D(0,0);
   vD=new Vec2D(0,0);
   age=0;
 }

void init(float _dir,float mx,float my,float _sc) {
   dir=_dir;
   sc=_sc;

  float prob=random(100);
   if(prob<80) age=15+int(random(30));
   else if(prob<99) age=45+int(random(50));
   else age=100+int(random(100));
   
   if(random(100)<80) speed=random(2)+0.5;
   else speed=random(2)+2;
   if(dataCountT<200 && dataCountF<200){
      speed*=1.5;
   }
   if(dataCountT<100 && dataCountF<100){
      speed*=2;
   }
   if(dataCountT<30 && dataCountF<30){
      speed*=2.5;
   }

  if(random(100)<80) dirMod=20;
   else dirMod=60;
   
   v.set(mx,my);
   initMove();
   dir=_dir;
   stateCnt=10;
   if(random(100)>50) col=0;
   else col=1;
   
   type=(int)random(30000)%2;
 }
   
 void initMove() {
   if(random(100)>50) dirMod=-dirMod;
   dir+=dirMod;
   
   vD.set(speed,0);
   vD.rotate(radians(dir+90));

  stateCnt=10+int(random(5));
   if(random(100)>90) stateCnt+=30;
 }
 
 void update() {
   age--;
   
   if(age>=30) {
     vD.rotate(radians(1));
     vD.mult(1.01f);
   }
   
   v.add(vD);
   if(col==0) fill(255-age,0,100,150);
   else fill(100,200-(age/2),255-age,150);
   
   if(type==1) {
     if(col==0) fill(255-age,100,0,150);
     else fill(255,200-(age/2),0,150);
   }
     
   pushMatrix();
   scale(sc);
   translate(v.x,v.y);
   rotate(radians(dir));
   rect(0,0,1,16);
   popMatrix();
   
   if(age==0) {
     if(random(100)>50) fill(200,0,0,200);
     else fill(00,200,255,200);
     float size=2+random(4);
     if(random(100)>95) size+=5;
     size*=sc;
     ellipse(v.x*sc,v.y*sc,size,size);
   }
   if(v.x<0 | | v.x>width | | v.y<0 | | v.y>height) age=0;
   
   if(age<30) {
     stateCnt--;
     if(stateCnt==0) {
       initMove();
     }
   }
  } 
 
}

class Vec2D {
float x,y;

Vec2D(float _x,float _y) {
   x=_x;
   y=_y;
 }

Vec2D(Vec2D v) {
   x=v.x;
   y=v.y;
 }

void set(float _x,float _y) {
   x=_x;
   y=_y;
 }

void set(Vec2D v) {
   x=v.x;
   y=v.y;
 }

void add(float _x,float _y) {
   x+=_x;
   y+=_y;
 }

void add(Vec2D v) {
   x+=v.x;
   y+=v.y;
 }

void sub(float _x,float _y) {
   x-=_x;
   y-=_y;
 }

void sub(Vec2D v) {
   x-=v.x;
   y-=v.y;
 }

void mult(float m) {
   x*=m;
   y*=m;
 }

void div(float m) {
   x/=m;
   y/=m;
 }

float length() {
   return sqrt(x*x+y*y);
 }

float angle() {
   return atan2(y,x);
 }

void normalise() {
   float l=length();
   if(l!=0) {
     x/=l;
     y/=l;
   }
 }

Vec2D tangent() {
   return new Vec2D(-y,x);
 }

void rotate(float val) {
   // Due to float not being precise enough, double is used for the calculations
   double cosval=Math.cos(val);
   double sinval=Math.sin(val);
   double tmpx=x*cosval - y*sinval;
   double tmpy=x*sinval + y*cosval;

  x=(float)tmpx;
   y=(float)tmpy;
 }
}


考察

 今回のプログラムは、PSoC側で距離センサの値に閾値を設け、その閾値以上であればTを、そうでなければFを渡すようなプログラムの作成を行った。データ通信において、観測した複数バイトのアナログ値を送るのは通信に遅延を起こす可能性があるため、このような形を利用した。
 そのため、データを受け取る側のProcessingの方の処理として、どれくらいの間センサーに手が反応していたかをカウントし、疑似のアナログデータとして変換する手法を用いた。
 今回のProcessingのプログラムのどこにその値が利用されているかというと、Processingプログラムの1では、色の指定にこの値を使用し、手がずっとかざされていた場合は、赤→緑→青という風に変化する。これは、かざされていた状態の回数のため、一度手を離すと線が消えていき、このカウントも0に戻る。
 次のProcessingのプログラムでは、手をセンサーの前で素早くかざしているときに、その素早さに応じて線が描かれるスピードが早くなるというものです。こちらは、センサーに手がかざされいてた回数と、手がかざされていなかった回数との2つの値が少ないほど素早く手が振られているという判断に利用しました。
 このように、距離の値をそのまま受け取るのではなく、その値を加工したものをうけとり、それを再度PC側で加工して使用することで、通信を軽くしユーザーにストレスを与えないプログラムが組める。
 また、Precessingはフレームワークの構造からframelateによりdrawメソッドの呼び出しの頻度を変えられる。Processing1のプログラムはフレームレートを10まで下げたが、PSoCから値を受け取るシリアル通信のイベントメソッドは、このフレームレイトの値にはよらずに呼ばれていることがデバッグからわかった。

  • 最終更新:2013-12-17 16:49:50

このWIKIを編集するにはパスワード入力が必要です

認証パスワード