上一篇,我们经过摸索已经掌握了示波器的静态图形绘制的方法,这里我们继续前行,将其动态波形的功能实现。
从现实情况来看,动态波形一定是数字一边产生一边绘制到屏幕上,而不是一开始就有一堆的数据等着我们用。

这里估计就要用到类似线程之类的概念来操作了《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();
 }

}

运行效果如下:

processOn 有没有曲线_processOn 有没有曲线


上述代码分别实现了模拟数据的产生gendata函数以及读取arduino串口函数readdata,这里需要注意的是在arduino端的波特率不能设置太高,否则依靠中断实现的串口通讯不能及时把数据送到processing中,那么独到的数据就会为0,也就不会有图像显示。

以下是实际串口读取的数据显示的图像(这里是依靠一个光敏电阻从A0口获得的数据):

processOn 有没有曲线_Processing绘图_02


其中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);
}