上一篇,我们经过摸索已经掌握了示波器的静态图形绘制的方法,这里我们继续前行,将其动态波形的功能实现。
从现实情况来看,动态波形一定是数字一边产生一边绘制到屏幕上,而不是一开始就有一堆的数据等着我们用。
这里估计就要用到类似线程之类的概念来操作了《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);
}