恒凯USB数据采集卡在国产麒麟操作系统下的应用(二)Python环境设置及数据采集实验
一、Python环境设置
ubuntukilin系统默认安装了Python3版本,没有安装Python2版本,在这里直接使用Python3,并配置Python3的环境,为了可以使用相关数组、数学计算、波形显示等功能,我们需要安装Python3的numpy、matplotli、tkinter等依赖库。
终端输入:
udo apt-get install python3-numpy python3-matplotlib python3-nose
sudo apt-get install python3-scipy python3-tk
二、实验准备
这里我们仍然以恒凯数据采集卡HK_USB DAQ V1.2这款采集卡产品为例
(链接:恒凯多功能数据采集卡USBDAQV12-Labview树莓派教程 工控学习板),
产品实物如下图:
1.首先将板卡通过USB数据线连接至计算机的USB口,
这里需要注意的是:如果没有按照前一章的说明编译并安装驱动,必须先按前一章的说明,先设置相关系统编译器环境,安装相关插件,编译数据采集卡的驱动,并安装.
2.然后将采集卡的DA1输出使用导线连接至AD1,一会我们将使用python程序通过DA1输出一个固定模拟电压,然后使用AD1通道采集功能采集DA1输出的电压。
3.之后打开一个信号发生器,设置信号发生器输出的频率为50Hz,峰值为正负2.5V的一个正弦波信号波形,我们将信号发生器输出的信号接采集卡的AD2通道,信号地接采集卡的AGND。
4.按采集卡的说明书将量程调整到正负10V量程档。
这样准备工作完成了。
三、编写python代码
以下是测试代码及相关解释:
from ctypes import *
#该行代码导入Ctypes数据类型,因为数据采集卡的驱动库是C语言编写的,所以这里需要导入C相关数据类型库,我们才可以使用C的数据类型,同时调用库函数
mport numpy as np
#导入numpy库,后续可以使用数组等
import matplotlib.pyplot as plt
#导入matlplotlib库,后续可以打印波形输出
CDLL('libusb-1.0.so',RTLD_GLOBAL)
#加载系统通用USB插件库
DAQdll=cdll.LoadLibrary('/usr/local/lib/libusbdaq_v12.so')
#使用cdll的LoadLibrary功能加载动态库,这里我们使用绝对路径的加载方法,不需要编译器去系统目录里查找库的位置,直接写库路径/usr/local/lib/libusbdaq_v12.so找到驱动库,并将驱动库加载到DAQdll这个对象里。
erro=DAQdll.OpenUsb()
#在对采集卡进行任何操作之前,我们应当先打开采集卡,获得采集卡的使用权,计算机当中所有的硬件设备都是由操作系统统一管理的,用户程序必须先调用打开设备函数向操作系统申请控制使用这个设备,才可以进行后续的操作,如果这个设备已经被其他用户程序申请并占用,那么当前用户程序就无法获取控制权,那么函数返回赋值给error变量的值为-1,表面或者设备失败,正常返回为0
da=2048
erro=DAQdll.DASingleOutV12(0,1,da)
#该段代码,我们调用一个DA单次输出函数,并设置一个da值等于2048输出,这里我们看以下DASingleOutV12函数的说明:
函数:int DASingleOutV12(int dev,int chan,int value);
功能:DA模拟输出,该函数模拟DA通道1或者2的输出电压,一旦设定后,对应DA输出通道将保持不变,直到下次设置或者改变对应DA通道的输出模式为扫描模式。正常返回0,失败返回-1
dev 32位有符号整型参数,设备号,由计算机自动分配设备号,从0开始,第一个设备的设备号为0,第二个设备设备号为1
chan 32位有符号整型参数,要设置的DA通道号,只有1或者2,其他值无效
value 32位有符号整型参数,要设置的输出值,由于DA输出范围为0—10V,DA的精度为12位,因此要输出的电压V= value/4095*10。
由上述说明可以推出,我们是在采集卡的DA1输出端输出一个5V左右的模拟电压。
advalue=c_float()
erro=DAQdll.ADSingleV12(0,1,0,1,byref(advalue))
print(advalue.value)
#该段代码首先使用c_float数据类型定义了一个单精度浮点型数据advalue,然后调用ADSingleV12函数采集模拟输入通道AD1的电压值,函数返回值赋给advalue,这里的关键点是要使用byref的传地址方式,就是把advalue所在的内存地址做为参数值传给ADSingleV12函数,函数内部将采集到的电压写入这个内存地址,这样函数退出之后,advalue也就获得了采集到的电压值。
同时我们看一下这个单次采集函数ADSingleV12的说明:
功能:指定任意通道,设定差分或单端模式、增益倍数,采集一个数并返回
函数:int ADSingleV12(int dev,int ad_mod,int chan,int gain,float* adResult);
dev 32位有符号整型参数,设备号,由计算机自动分配设备号,从0开始,第一个设备的设备号为0,第二个设备设备号为1
ad_mod: 32位有符号整型参数,设定采集时模拟输入模式,0—差分采集模式,1—单端采集模式。
chan :32位有符号整型参数,设置要读取的AD通道。对于单端模式:最小0,最大15;对于差分模式:最小0,最大7。
gain :32位有符号整型参数,根据外部硬件设置的量程代码,0返回AD采样结果数据,1-14返回对应量程的电压值,可参考3.4章节量程设置说明部分。
*adResult: 32 位单精度浮点数据,用于返回采集结果(注意返回的数据值跟gain值有关,gain为0,则返回数据为AD测量结果(0-4096),gain为外部量程代码则返回外部实际输入电压值)。
函数返回: =0操作成功/-1失败。
根据函数说明,我们已经将DA1输出的电压连接到了AD1通道,所以我们选择单端采样模式,通道号为0,量程代码为1对应之前设置好的正负10V量程,采集返回电压通过float* adResult指针指向的地址写入到变量advalue,然后使用print(advalue.value)打印出电压值。
addata=(c_float*1024)()
erro=DAQdll.ADContinuV12(0,1, 0, 1, 1024, 20000, byref(addata))
addata1=(c_float*1024)()
erro=DAQdll.ADContinuV12(0,1, 1, 1, 1024, 20000, byref(addata1))
#以上代码分别定义了两个c_float的单精度数组addata和addata1,数组的大小都为1024个。
#这里我们要实现连续等间隔,即按固定频率高速采集一段波形的功能,由于计算机的分时操作系统,计算机系统的基本原理是1mS切换一个程序运行,所以如果我们使用单次采样函数,前后两次采集的时间是无法确定的,因为计算机可能在运行第一次单次采集函数后,将当前程序挂起,去运行其他软件了,然后再回来继续采集,这样我们就无法采集周期的波形,所以为了能够采集波形,我们需要使用连续采样函数,我们先看一下函数说明:
函数:int ADContinuV12(int dev,int ad_mod,int chan,int gain,int Num_Sample,int Rate_Sample,float databuf);
dev 32位有符号整型参数,设备号,由计算机自动分配设备号,从0开始,第一个设备的设备号为0,第二个设备设备号为1
ad_mod: 32位有符号整型参数,设定采集时模拟输入模式,0—差分采集模式,1—单端采集模式。
chan: 32位有符号整型参数,设置要读取的AD通道。对于单端模式:最小0,最大15;对于差分模式:最小0,最大7。
gain: 32位有符号整型参数,设为0直接返回AD采集结果(0-4096),根据外部硬件设置填入相应的量程代码就可以在Read_AdBuff时直接以float型数据输出实际电压值,量程代码与外部的对应关系参照3.4章节板卡量程设置说明部分。
Num_Sample:32位整型数,设定要连续采集的数据个数;
freq: 32位有符号整型参数,设置连续采样频率,设置范围100—100000;
databuf:32位单精度浮点数据,用于返回采集结果,指向一个32位单精度浮点型数据数组,数组大小必须大于等于num,用于返回采集到的数据(注意返回的数据值跟gain值有关,gain为0,则返回数据为AD测量结果(0-4096),gain为外部量程代码则返回外部实际输入电压值)。
函数返回:=0表示操作有效/-1失败。
根据上述的函数说明,我们使用单端采样模式分别调用了两次连续采集函数,分别对AD1和AD2两个模拟输入通道,按 20000Hz的采样率(即一秒采集20000次,每50微秒采集一次),连续等间隔采集1024个数据一会停止采集,并把数据返回到数组addata和addata1,这样两个数组当中就保存了两个通道采集的波形数据。
plt.figure()
#初始画波形显示框
plt.plot(addata,'b')
#将addata波形打印到波形显示框,并显示波形为蓝色
plt.plot(addata1,'r')
将addata1波形打印到波形显示框,并显示波形为红色
plt.xlabel("sample point")
#设置显示属性
plt.ylabel("vol/V")
plt.show()
#显示
erro=DAQdll.CloseUsb()
#程序退出前关闭采集卡,释放控制权
四、运行代码测试
运行代码时需要注意权限问题,Linux操作系统默认不会将硬件设备的操作权限给普通用户,只有root用户有所有硬件设备的使用权限,如果我们直接在python环境中运行代码,需要首先退出系统,重新登陆root用户,才可以直接在python环境运行操作数据采集卡;如果我们不想重新登陆系统,我们可以在终端使用命令带sudo权限运行,输入命令:
sudo python3 test.py
如图:
最后显示出波形如图:
我们可以看到蓝色波形是DA1输出的直流电压信号,红色波形是由信号发生器输出的50hz、正负2.5V的正弦波,由于我们设定的采样率为20000hz,因此可以看到一个周期波形的采样点数有400个数据点。
五、总结
在国产的麒麟Ubuntukilin系统下使用恒凯科技的数据采集卡编写python程序采集数据,主要的几个关键点是:
(1)编译驱动并放置在系统目录,以备python程序调用驱动库来操作采集卡采集数据;
(2)安装python相应的依赖库;
(3)Python调用C库,需要使用C语言的相关数据类型,需要注意python数据类型与C语言数据类型的区别,以及如何在python下调用C函数的相关问题,详细的知识可以参考python官网,调用C库相关帮助文档;
(4)特别需要理解一下传地址与传值的区别,在C语言当中我们称之为地址为指针;
(5)在运行程序时需要注意设备权限问题,Linux系统普通用户没有操作硬件设备的权限;
(6)理解计算机操作系统的基本原理,即可以理解单次采集与连续采集的模式的区别与作用,单次采集一般用于采集慢速变化的信号,连续采集用于采集快速变化的波形,特别是周期波形;
(7)理解信号周期(或者信号频率)与采样周期(或者采样频率的关系),一般来说采样频率要大于信号频率的10倍以上才可以清楚的看到一个信号周期的波形,一个信号周期内采样点的个数=采样频率÷信号频率。