Arduino与LabVIEW互动应用02-基于Arduino+LabVIEW的多路数据采集系统

nust_奔跑 于 2013-5-22 19:03 编辑


摘要:针对低速、低成本、快速搭建的特点,采用Arduino与LabVIEW来实现低成本上下位机数据采集系统。Arduino作为下位机,负责A/D转换以及数据传输;LabVIEW编写的数据采集软件作为上位机;上下位机利用RS-232串行接口实现通讯。
【注】一般认为上位机为主机,下位机为从机,上位机领导下位机按照上位机机的意愿工作为上位机服务;同时下位机也可以主动向上位机发出请求,上位机响应下位机并配合完成某个请求。

数据采集,是指从传感器和其它待测设备等模拟和数字被测单元中自动采集信息的过程。相应能够完成数据采集的系统被称为数据采集系统。
数据采集系统的任务,就是采集传感器输出的模拟信号转换成计算机能识别的信号,并送入计算机,然后将计算得到的数据进行显示或打印,以便实现对某些物理量的监测,其中一些数据还将被生产过程中的计算机控制系统用来控制某些物理量。 【文献1】

一、Arduino下位机部分
数据采集系统中的Arduino下位机部分采用Arduino Leonardo实验板,如图1所示。

13-120h4191645915.jpg

2013-5-22 18:50 上传
(66.95 KB)



图1 Arduino Leonardo控制板

Arduino下位机部分需要完成两个功能:数据采集和数据传输,Arduino Leonardo控制板通过串口接受上位机命令,完成相应的数据采集,并将数据回传至上位机。
数据采集分为模拟量采集和数字量采集,设置采集路数各为2路,分别采用Arduino UNO上具有模拟量输入的管脚A0、A1和具有数字量输入的管脚2、3来实现。模拟量采用接至GND、3.3V和5V来实现不同电压值,数字量采用接至5V和GND实现高电平与低电平。【注】

【注】如果有电位器,可以用来测量分压值。由于手头没有电位器,我这里只是简单的实现。

Arduino Leonardo代码清单:
ARDUINO 代码复制打印
#define A0_COMMAND0x10 //A0采集命令字#define A1_COMMAND0x11 //A1采集命令字#define D0_COMMAND0x20 //D0采集命令字#define D1_COMMAND0x21 //D1采集命令字byte comdata[3]={0};  //定义数组数据,存放串口接收数据int LED = 13;     //定义LED连接的管脚int A0_mark=0;    //定义A0的标志位int A1_mark=0;    //定义A1的标志位int D0_mark=0;    //定义D0的标志位int D1_mark=0;    //定义D1的标志位int AD_Value=0;    //AD转换后的数字量float float_AD_Value;  //数字量换算成浮点电压量int D_Value=0;   //数字量测量的数据void receive_data(void);  //接受串口数据void test_data(void);   //测试串口数据是否正确,并更新数据void do_command(void);  //执行更新的数据void setup(){Serial.begin(9600);  pinMode(LED, OUTPUT);}void loop(){while (Serial.available() > 0) //不断检测串口是否有数据 {  receive_data();    //接受串口数据  test_data();     //测试数据是否正确并更新标志位  do_command();    //执行更新的数据 }}void receive_data(void)   { int i ; for(i=0;i<3;i++) {  comdata =Serial.read();  //延时一会,让串口缓存准备好下一个字节,不延时可能会导致数据丢失,   delay(2); }}void test_data(void){if(comdata[0] == 0x55)    //0x55和0xAA均为判断是否为有效命令 { if(comdata[1] == 0xAA) {  if(comdata[2] == A0_COMMAND)    {     A0_mark=2;      //A0更新位置位    }  if(comdata[2] == A1_COMMAND)    {     A1_mark=2;      //A1更新位置位    }  if(comdata[2] == D0_COMMAND)    {     D0_mark=2;      //D0更新位置位    }  if(comdata[2] == D1_COMMAND)    {     D1_mark=2;     //D1更新位置位    }  } }}void do_command(void){if(A0_mark==2){  A0_mark=0;           //复位A0更新位  digitalWrite(LED, HIGH);       //打开LED灯  AD_Value = analogRead(A0);     //读取A0电压值  float_AD_Value=(float)AD_Value/1023*5.00;//换算为浮点电压值  Serial.println(float_AD_Value,2);    //保留两位小数发送数据  delay(500);  digitalWrite(LED, LOW);       //关闭LED灯}if(A1_mark==2){  A1_mark=0;           //复位A1更新位  digitalWrite(LED, HIGH);       //打开LED灯  AD_Value = analogRead(A1);     //读取A1电压值  float_AD_Value=(float)AD_Value/1023*5.00;//换算为浮点电压值  Serial.println(float_AD_Value,2);    //保留两位小数发送数据  delay(500);  digitalWrite(LED, LOW);       //关闭LED灯}if(D0_mark==2){  D0_mark=0;           //复位D0更新位  digitalWrite(LED, HIGH);       //打开LED灯  D_Value = digitalRead(2);      //读取D2数字量  Serial.println(D_Value);      //发送数字量测量数据  delay(500);  digitalWrite(LED, LOW);       //关闭LED灯}if(D1_mark==2){  D1_mark=0;            //复位D1更新位  digitalWrite(LED, HIGH);      //打开LED灯  D_Value = digitalRead(3);       //读取D1数字量  Serial.println(D_Value);       //发送数据量测量数据  delay(500);  digitalWrite(LED, LOW);        //关闭LED灯}}
#define A0_COMMAND0x10 //A0采集命令字
#define A1_COMMAND0x11 //A1采集命令字
#define D0_COMMAND0x20 //D0采集命令字
#define D1_COMMAND0x21 //D1采集命令字
byte comdata[3]={0}; //定义数组数据,存放串口接收数据
int LED = 13; //定义LED连接的管脚
int A0_mark=0; //定义A0的标志位
int A1_mark=0; //定义A1的标志位
int D0_mark=0; //定义D0的标志位
int D1_mark=0; //定义D1的标志位
int AD_Value=0; //AD转换后的数字量
float float_AD_Value; //数字量换算成浮点电压量
int D_Value=0; //数字量测量的数据void receive_data(void); //接受串口数据
void test_data(void); //测试串口数据是否正确,并更新数据
void do_command(void); //执行更新的数据void setup()
{
Serial.begin(9600);
pinMode(LED, OUTPUT);

}
void loop()
{
while (Serial.available() > 0) //不断检测串口是否有数据
{
receive_data(); //接受串口数据
test_data(); //测试数据是否正确并更新标志位
do_command(); //执行更新的数据
}
}
void receive_data(void)
{
int i ;
for(i=0;i<3;i++)
{
comdata =Serial.read();
//延时一会,让串口缓存准备好下一个字节,不延时可能会导致数据丢失,
delay(2);
}
}void test_data(void)
{
if(comdata[0] == 0x55) //0x55和0xAA均为判断是否为有效命令
{
if(comdata[1] == 0xAA)
{
if(comdata[2] == A0_COMMAND)
{
A0_mark=2; //A0更新位置位
}
if(comdata[2] == A1_COMMAND)
{
A1_mark=2; //A1更新位置位
}
if(comdata[2] == D0_COMMAND)
{
D0_mark=2; //D0更新位置位
}
if(comdata[2] == D1_COMMAND)
{
D1_mark=2; //D1更新位置位
}
}
}
}void do_command(void)
{
if(A0_mark==2)
{
A0_mark=0; //复位A0更新位
digitalWrite(LED, HIGH); //打开LED灯
AD_Value = analogRead(A0); //读取A0电压值
float_AD_Value=(float)AD_Value/1023*5.00;//换算为浮点电压值
Serial.println(float_AD_Value,2); //保留两位小数发送数据
delay(500);
digitalWrite(LED, LOW); //关闭LED灯
}
if(A1_mark==2)
{
A1_mark=0; //复位A1更新位
digitalWrite(LED, HIGH); //打开LED灯
AD_Value = analogRead(A1); //读取A1电压值
float_AD_Value=(float)AD_Value/1023*5.00;//换算为浮点电压值
Serial.println(float_AD_Value,2); //保留两位小数发送数据
delay(500);
digitalWrite(LED, LOW); //关闭LED灯
}
if(D0_mark==2)
{
D0_mark=0; //复位D0更新位
digitalWrite(LED, HIGH); //打开LED灯
D_Value = digitalRead(2); //读取D2数字量
Serial.println(D_Value); //发送数字量测量数据
delay(500);
digitalWrite(LED, LOW); //关闭LED灯
}
if(D1_mark==2)
{
D1_mark=0; //复位D1更新位
digitalWrite(LED, HIGH); //打开LED灯
D_Value = digitalRead(3); //读取D1数字量
Serial.println(D_Value); //发送数据量测量数据
delay(500);
digitalWrite(LED, LOW); //关闭LED灯
}
}

二、LabVIEW上位机部分

LabVIEW与Arduino通讯已在《Arduino与LabVIEW互动应用01-串口控制LED亮灭》一文中作了简单的介绍,此处在上次的基础上修改实现。串口读写的程序框图如图2所示。首先,对选择的通道的串口进行配置,然后串口写入所需要测量的通道号,等待100ms,从串口中读取Arduino下位机返回数据,最后对数据进行适当的转换并显示出来。


图片1.png

2013-5-22 18:50 上传
(5.76 KB)



图2 LabVIEW串口通讯最小部分

LabVIEW上位机前面板设计如图3所示。


未命名2.jpg

2013-5-22 18:50 上传
(82.23 KB)


图3 LabVIEW上位机前面板

LabVIEW上位机程序框图如图4和图5所示,由于有2路模拟量和2路数字量,此处仅给出一路模拟量和一路数字量的程序框图。不同通道的模拟量或数字量的发送数据帧中,通道号不同;数字量与模拟量采集的发送数据帧中,命令号不同。发送数据帧中,具体的命令号和通道可以自己定义,不过需要上下位机的对应起来。

图片3.png

2013-5-22 18:50 上传
(12.47 KB)

图4 模拟量采集程序框图

4.png

2013-5-22 18:50 上传
(11.89 KB)



图5 数字量采集程序框图

三、实验与演示

通过将模拟量输入A0依次接入GND、3.3V和5V,然后点击“测量”按钮,观察面板上的仪表盘和数显框中数值的变化。

通过将数字量输入2依次接入GND和5V,然后点击“测量”按钮,观察面板上的LED灯的变化,LED亮代表高电平、LED灭代表低电平。


演示视频,请看我的博客:基于Arduino与LabVIEW的数据采集系统

四、总结
在传感器等领域经常需要用到数据采集的功能,此应用实现了命令发送与数据回传功能,可以在此基础上扩展功能,对相关传感器的数据采集有一定的参考价值。

参考文献:

文献1:基于单片机的数据采集系统的控制器设计
文献2:http://arduino.cc/

via - 极客工坊

标签: Arduino教程