Processing摸索前行(7)
阿新 • • 發佈:2018-12-22
上一篇,我們經過摸索已經掌握了示波器的靜態圖形繪製的方法,這裡我們繼續前行,將其動態波形的功能實現。
從現實情況來看,動態波形一定是數字一邊產生一邊繪製到螢幕上,而不是一開始就有一堆的資料等著我們用。
這裡估計就要用到類似執行緒之類的概念來操作了《Processing摸索前行(6)-在processing中實現多執行緒》,而我們在Processing中沒有thread的概念,沒有類,所以我們不得不另求他法了,經過反覆摸索,發現有一個封裝的函式可以說實現這樣的功能,這個函式的名稱就是registerMethod,這是一個註冊方法的函式,我們就利用他註冊一個post函式,熟悉VC執行緒的人一定看到它就知道大概意思了,它是負責推送訊息的。這個註冊函式在Processing的官方reference中沒有提到,但實際是可以用的。
有了它,我們的事情就好辦多了,可以理解為我們用它來產生資料也可以理解為用它來獲取資料,下面我們來看看程式碼的實現:
import processing.serial.*; Serial sp; int x1,x2; int w=720; int h=380; int woff=80; int hoff=80; FloatList wav1data; FloatList wav2data; int rate=1; float tempdata=0; void settings() { size(w,h); } void setup() { sp=new Serial(this,"COM5",9600); frameRate(rate); registerMethod("post", this); wav1data= new FloatList(); wav2data= new FloatList(); x1=0; x2=-80; } void draw() { // 繪製背景 drawBg(); //繪製波形 drawWave(); } void post() { readData(); //genData(); //println(wav1data.size()); println("--------------------"+x1+"-------------------");
}
void readData() { while(sp.available()>0) { tempdata=sp.read(); //if(tempdata!=0) //{ wav1data.append(tempdata); println("value :"+tempdata); //} println(wav1data.size()); if(wav2data.size()>1440) { wav1data.remove(0); } } } void genData() { //獲取資料並存儲,每次產生或者清除1個周波 for(int i=0;i<360;i++) { if(wav1data.size()<720) { if(random(-20,8)>7) wav1data.append(h/2+80*sin(i*PI/180)-random(10)); else if(random(0,50)<1) wav1data.append(h/2+80*sin(i*PI/180)+random(10)); else wav1data.append(h/2+80*sin(i*PI/180)); wav2data.append(h/2+80*sin(i*PI/180)); } if(wav1data.size()>720) { wav1data.remove(i); wav2data.remove(i); } } } void drawBg() { background(0); Pline ln1=new Pline(0,40,w,40); for(int i=0;i<w/woff;i++) ln1.offsetLine(0,woff); Pline ln2=new Pline(40,0,40,h); for(int i=0;i<w/hoff;i++) ln2.offsetLine(hoff,0); //水平標尺 Pline ln3=new Pline(0,h/2+2,0,h/2+8); Pline ln4=new Pline(0,h/2+10,0,h/2+4); ln3.changeColor(color(20,220,20)); ln4.changeColor(color(20,220,20)); for(int i=0;i<w/40;i++) { ln3.offsetLine(40,0); for(int j=0;j<10;j++) ln4.offsetLine(4,0); } //垂直標尺 Pline ln5=new Pline(w/2,0,w/2+8,0); Pline ln6=new Pline(w/2,0,w/2+4,0); ln3.changeColor(color(20,220,20)); ln4.changeColor(color(20,220,20)); for(int i=0;i<w/40;i++) { ln5.offsetLine(0,40); for(int j=0;j<10;j++) ln6.offsetLine(0,4); } } void drawWave() { println("*************start drawing*******************"+wav1data.size()); stroke(60,60,150); for(int a=0;a<wav1data.size()-1;a++) { line(x1,wav1data.get(a),x1-1,wav1data.get(a+1)); println(x1+" :"+wav1data.get(a)+" "+(x1+1)+" :"+wav1data.get(a+1)); x1=x1%w+1; } stroke(150,10,10); for(int a=0;a<wav2data.size()-1;a++) { line(x2,wav2data.get(a),x2+1,wav2data.get(a+1)); println(x2+" :"+wav2data.get(a)+" "+(x2+1)+" :"+wav2data.get(a+1)); x2=x2%w+1; }
}
class Pline
{
float StartX,StartY,EndX,EndY;
float Alf=254;
color Color= color(0,180,0);
Pline(float sx,float sy,float ex,float ey)
{
StartX=sx;
StartY=sy;
EndX=ex;
EndY=ey;
drawline();
}
Pline(float sx,float sy,float ex,float ey,float alf )
{
StartX=sx;
StartY=sy;
EndX=ex;
EndY=ey;
Alf=alf;
drawline();
}
Pline(float sx,float sy,float ex,float ey,color clr )
{
StartX=sx;
StartY=sy;
EndX=ex;
EndY=ey;
Color=clr;
drawline();
}
Pline(Pline ln,color clr)
{
StartX=ln.StartX+20;
StartY=ln.StartY+20;
EndX=ln.EndX+20;
EndY=ln.EndY+20;
Color=clr;
drawline();
}
Pline(float sx,float sy,float ex,float ey,color clr,float alf )
{
StartX=sx;
StartY=sy;
EndX=ex;
EndY=ey;
Color=clr;
Alf=alf;
drawline();
}
Pline(Pline ln,color clr,float alf )
{
StartX=ln.StartX+20;
StartY=ln.StartY+20;
EndX=ln.EndX+20;
EndY=ln.EndY+20;
Color=clr;
Alf=alf;
drawline();
}
void changeColor(color cl)
{
Color=cl;
}
void drawline()
{
stroke(Color,Alf);
line(StartX,StartY,EndX,EndY);
noStroke();
}
void offsetLine(float offsetX,float offsetY)
{
StartX=StartX+offsetX;
StartY=StartY+offsetY;
EndX=EndX+offsetX;
EndY=EndY+offsetY;
drawline();
}
}
執行效果如下:
上述程式碼分別實現了模擬資料的產生gendata函式以及讀取arduino串列埠函式readdata,這裡需要注意的是在arduino端的波特率不能設定太高,否則依靠中斷實現的串列埠通訊不能及時把資料送到processing中,那麼獨到的資料就會為0,也就不會有影象顯示。
以下是實際串列埠讀取的資料顯示的影象(這裡是依靠一個光敏電阻從A0口獲得的資料):
其中arduino端的程式相當的簡單,就一個串列埠傳送資料:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.write(analogRead(A0));
delay(10);
}