谈到Processing与Arduino互动,上下位机的串口通讯是一个重要问题,这篇文章也重点强调串口通讯话题,以前的几篇关于Processing与Arduino互动的文章,上位机每次接受Arduino控制器传来的数据只有一个字节,而这篇文章由于所用到的DFrobot公司出品的URM37 V3.2超声波传感器的应用特点所致,Arduino一次传来的数据是6个,而且要在6个字节找到表示超声波测距值那个字节。
这篇文章的串口通讯的编程思想与我上篇关于超声波测距的文章是一样,《动手制作超声波测距仪》网址:http://blog.chinaaet.com/detail/23378.html,文章里有这个超声波传感器的说明书供下载。《动手制作超声波测距仪》文章里介绍的上位机软件是Labview,所制作的人际交互界面是虚拟仪器面板,而这篇文章的上位机软件是数位艺术软件Processing,它可以与人际物理世界互动,通过Arduino装置,让人的各种物理感官与电脑屏幕的数位艺术作品产生交流。
这个作品的说明:当超声波传感器测量与由人手推动的盒子之间的距离,距离越近,Processing画布上的彩圈阵列的彩圈直径越小,感觉像是彩圈离观众越远。距离越远,则彩圈直径越大,并彩圈之间相互融合。开始设计这个作品方案时,我还没预测到彩圈不断融合过程中,会出现如视频所示,这样奇妙的图案,这可能也是Processing与Arduino互动给我们带来的惊喜吧。
点击视频网址,看全屏精彩视频: http://player.youku.com/player.php/sid/XMzM2NzU5MTE2/v.swf
URM37V3.2超声波测距传感器与Arduino控制器的串口连线,可通过4根杜邦线一端插在传感器的引针上,另一端插在层叠在Arduino控制器的传感器扩展板的引针上。如图所示:
URM37 V3.2超声波传感器地址:http://item.taobao.com/item.htm?spm=1101*r1F.3-1mJ7Y.h-1MYgS*&id=227289059&
Arduino程序说明:先向URM37 V3.2超声波传感器“写”四个字节的测距命令,由于超声波传感器和PC机的Processing程序,与Arduino控制器的串口通讯都是COM3端口,所以这四个字节的测距命令也“写”到了Processing程序,然后传感器又回馈了四个测距信息字节,Arduino要“读”这四个测距信息字节,其中有两个字节是所测距离的高字节和低字节,然后对这两个字节进行运算处理,再“写”两个字节到Processing,这两个字节,一个字节是标志,标志字节为10,紧跟的字节才是距离值。看蓝色的“写”,每次Arduino向串口发送了6个字节,其中只有最后那个字节有用。看看下面的Processing程序是如何读取这个有用“距离值”字节的程序段(蓝色字体标注)。
下面给出Arduino和Processing的程序, 我用蓝色字体标注了两者串口通讯的程序段。
注意:当通过USB,下载Arduino程序,传感器的RXD和TXD这两根杜邦线的其中一根要拔掉,否则无法下载程序。另外如果Processing与Arduino第一次联机不成功,可以先拔掉Arduino控制器的电源线,再插上电源,Arduino重启,再运行Processing程序,就可以了。
Arduino程序:
int USValue = 0;//定义存放超声波测量距离
boolean flag=true;
//向URM37V3.2超声波传感器发送测距命令
byte DMcmd[4] = {0x22, 0x00, 0x00, 0x22};
byte header; //0x22开始接收距离数
byte highbyte;//距离数据高8位
byte lowbyte;//距离数据低8位
byte sum;//sum校验和
//初始化
void setup() {
Serial.begin(9600); //串口波特率设置
delay(200);
}
void loop( )
{
flag=true;
for(int i=0;i<4;i++)
{
Serial.print(DMcmd[i],BYTE);//发送超声波测距命令
}
while(flag)
{
if(Serial.available()>3) //查询串口有4个字节了
{
byte header=Serial.read(); //0x22开始接收距离数据
byte highbyte=Serial.read();//距离数据高8位
byte lowbyte=Serial.read();//距离数据低8位
byte sum=Serial.read();//sum校验和
if(highbyte>0) //如果超声波测距值大于255
{
USValue=255; //则超声波测距值限制在255
}
//如果超声波测距值小于等于255
else
{
USValue = lowbyte;//则超声波测距值为实测值
}
Serial.print(10,BYTE);//上传“即将发送距离值”的标志
//向上位机LABVIEW软件输出距离值
Serial.print(USValue,BYTE);
flag=false;
}
}
delay(100); //延时,不让通讯太忙
}
Processing程序:
import processing.serial.*;//导入serial通信库
Serial duankou;//创建对象duankou
float data;//变量存储Arduino传来数据
int val;//暂存变量作为Arduino上传的超声波测距值
float a;//
int d;//彩圈直径
void setup()
{
//设定通讯端口为COM3,波特率为9600
duankou = new Serial(this,"COM3",9600);
size(600,600);//画布尺寸
background(0);//背景为黑色
stroke(128);//圆圈线条为灰色
smooth();
}
//主程序
void draw()
{
background(0);
//当串口缓冲区接受的字节为6个字节时
if(duankou.available()>5)
{
//逐个读取串口缓冲区的字节数据
for(int i= 0;i<4;i++)
{
//把Arduino传来的字节存入变量data
data=duankou.read();
//当读到“即将读取超声波距离字节”的标志
if(data==10)
//读取“即将读取超声波距离字节”
val=duankou.read();
}
//如果超声波距离小于等于5cm,则
//超声波距离变量val设为5
if(val<=5)
val=5;
//如果超声波距离大于等于20cm,则
//超声波距离变量val设为20
if(val>=20)
val=20;
//对超声波距离值正比变换
a=map(val,5,20,5,140);
d=int(a);
//把超声波距离值转换为彩圈直径
//距离值越大,圆圈直径越小,反之,直径越大
d=145-d;
println(d);
}
//生成彩圈阵列
for(float x1=0;x1<=600;x1+=100)
{
for(float y1=0;y1<=600;y1+=100)
{
//fill(174,221,60,160);
fill(242,204,47,160);
ellipse(x1,y1,d,d);
}
}
for(float x1=50;x1<=550;x1+=100)
{
for(float y1=50;y1<=600;y1+=100)
{fill(116, 193, 206, 160);
//fill(174,221,60,160);
ellipse(x1,y1,d,d);
}
}
}