摘 要:在简要介绍基于USB接口激光粒度仪的工作原理的基础上,着重讲述线程方法在此系统中的应用。
关键词:激光粒度仪;USB总线;线程;数据采集
Application of Threads in Laser Particle Sizer Based on USB??
LU Yumin, ZHENG Gang, SUN Hao
(College of Optics and Electronics, University of Shanghai for Science and Technology, Shanghai 200093, China)
Abstract: The paper introduces the principle of laser particle sizer and the application of threads in laser particle sizer based on USB.
Key words: laser particle sizer; USB; threads; data collection
1系统原理结构与数据采集卡
1.1系统原理与结构
系统原理结构图如图1所示。由激光器发出的光束经空间滤波器扩束成平行单色光。当该平行光照射在测量区中的颗粒群时便产生光的衍射现象。衍射散射光的强度分布与测量区中被照射的颗粒直径、颗粒数有关。衍射光被接收透镜聚焦在半圆多元光电探测器上。此探测器将含有颗粒直径和颗粒数信息的衍射光信号转换成相应的电信号,经信号前置处理电路及USB数据采集卡转换成数字信号送入PC机计算处理,得到颗粒的粒度分布和浓度情况。
1.2数据采集卡简介
本系统采用某公司的USB2002型数据采集卡。主要性能指标如下:(a)模拟电压输入范围:±5V,±10V;(b)A/D转换分辨率:14Bit,32K字FIFO存储器;(c)32路单端模拟信号输入;16路双端模拟信号输入;(d)转换速率:400kHz;(c)程控增益(×1、2、4、8)。
2系统的软件实现
2.1线程
线程指的是程序代码的执行途径外加一组操作系统分配的资源(堆栈、寄存器状态等等)。线程一般分为用户界面线程和工作者线程两类,用户界面线程可以创建窗口并处理发送给这些窗口的消息;工作者线程执行后台任务,因其不接受用户的直接输入,所以不需要窗口和消息循环。线程的应用可以提高CPU的利用率,提高程序的响应能力,降低系统对数据采集速度的影响。
2.2系统软件实现
2.2.1软件组成
程序主要由两部分组成,一是数据采集部分,另一部分为数据处理部分(见图2)。数据采集部分对USB数据采集卡进行系统初始化、数据读取并存入数据缓冲区及释放系统资源停止数据采集等工作。数据处理部分进行原始数据的存储、数据计算、各个通道数据的数值和直方图实时显示以及获取各通道中的最大值为采集卡程控增益的设置提供依据。由于后者进行的数据计算和图形操作,需消耗CPU很多时间,在单线程的情况下将会阻塞主线程运行,出现采集数据溢出丢失的现象。
为此采用基于线程的多任务编程方法。
2.2.2数据采集线程
将数据采集部分定义为工作者线程(数据采集线程)。USB设备与AD转换进度同步完全由硬件和驱动程序自动完成。用户若要用程序方式实现连续数据采集,对其软件实现就显得极为容易。数据采集线程每次用ReadDeviceAD函数(USB采集卡接口函数)读取AD数据时,设备驱动程序会按照AD转换进度将AD数据一一放进用户数据缓冲区;当完成该次所指定的采样点数时,便会返回;当再次用这个函数读取数据时,会接着上一次的位置传递数据到用户数据缓冲区。高速数据采集要求每两次调用ReadDeviceAD之间的时间间隔越短越好。由图3数据采集线程流程图可知,为保证每两次ReadDeviceAD之间较小的时间间隔,应尽量减少USB设备AD初始化的次数。为此,采用了一次性设置增益的方法。即根据所采信号大小和对应的原增益计算出原始信号大小,然后根据信号应放大的数值换算出合适的增益进行一次设置。另外,设置了一个布尔控制变量(ParaChange)来记录增益是否被刚刚改变,如果刚刚改变就跳过增益是否应该改变(ADPARA)的判断直接读取采集数据从而减少读取采集数据时间间隔,以利于高速采集。图3中Runstatus为数据采集线程运行控制布尔变量。
2.2.3数据处理线程
将数据处理部分定义为数据处理线程,以便处理图形操作及数据处理等较耗时的工作。最初,数据处理线程不做任何工作,而是在Win32API函数WaitForSingleObject的作用下进入睡眠状态(见图2),此时它不消耗CPU任何时间,可保证数据采集线程代码有充分的运行机会。当数据采集线程取得指定长度的数据到用户空间时,再用Win32API函数SetEvent将指定事件消息发送给数据处理线程,则数据处理线程即刻恢复运行状态,迅速对这批数据进行处理。
2.2.4数据缓冲队列
数据处理线程可能处理花费CPU过多时间的工作,从而导致数据处理线程阻塞;而数据采集线程则在不停地采集数据,这样数据处理线程很有可能因此而丢失数据采集线程发来的某一段数据。为避免这个问题,建立了数据缓冲队列。即假设数据采集线程每一次从设备上取出8K数据,那么就创建一个缓冲队列,在用户程序中开辟一个两维数组,如Buffe(Count??1,DataLen??1),将DataLen视为数据采集线程每次采集的数据长度(DataLen必须等于采集通道数的整数倍),从而保证采集数据与各通道的一一对应关系。另外,也要注意在USB采集卡每次增益改变时要保证数据采集线程和数据处理线程从第一个缓冲队列的第一数据存储和读取。这可以保证采集数据与各通道的一一对应关系,以防止数据错位。Count则为缓冲队列的成员个数。应根据计算机物理内存大小和总体使用情况来设定。假如设成32,则这个缓冲队列实际上就是数组Buffer(31,8191)的形式,共32个缓冲队列(数组各维的基为0)。它跟一个普通的缓冲区,如一维数组差不多,唯一不同是,两个线程首先要通过改变Count字段的值,即Count的索引值(ReadIndex或ProcIndex)来填充和引用某一段DataLen长度的数据缓冲区。需要注意的是,两个线程不共用一个Count的索引值。具体情况(见图4)是当数据采集线程在AD部件被初始化之后,首次采集数据时,则将自己的ReadIndex下标置为0,即用第一个缓冲区采集AD数据。当采集完后,则向数据处理线程发送消息,且两个线程的公共变量Segments加1(Segments变量记录当前时刻缓冲队列中有多少个已被数据采集线程使用了,但是却没被数据处理线程处理掉的缓冲区数量。)然后再接着将ReadIndex偏移至1,再用第二个缓冲区采集数据。再将Segments加1,至到Readlndex等于32为止,然后再回到0位置,重新开始。而数据处理线程则在每次接受到消息时判断有多少由于自己被堵塞而没有被处理的缓冲区个数,然后逐一进行处理,最后再从Segments变量中减去在所接受到的当前事件下所处理的缓冲区个数。因此,即便是数据处理线程由于系统的偶尔繁忙而被堵塞,也很难使数据丢失。而且,通过这种方案,用户还可以在数据采集线程中对Segments加以判断,观察其值是否大于32,如果大于,则缓冲区队列肯定因数据处理线程的堵塞而被溢出;如果溢出则报警。因此,具有强大的容错处理能力。
3结束语
本文介绍了线程编程方法在激光粒度仪数据采集中的应用。经实验验证,采集速度能满足设计要求,而且,获得了理想的测量标准粒子的测量结果。
关键词:激光粒度仪;USB总线;线程;数据采集
Application of Threads in Laser Particle Sizer Based on USB??
LU Yumin, ZHENG Gang, SUN Hao
(College of Optics and Electronics, University of Shanghai for Science and Technology, Shanghai 200093, China)
Abstract: The paper introduces the principle of laser particle sizer and the application of threads in laser particle sizer based on USB.
Key words: laser particle sizer; USB; threads; data collection
1系统原理结构与数据采集卡
1.1系统原理与结构
系统原理结构图如图1所示。由激光器发出的光束经空间滤波器扩束成平行单色光。当该平行光照射在测量区中的颗粒群时便产生光的衍射现象。衍射散射光的强度分布与测量区中被照射的颗粒直径、颗粒数有关。衍射光被接收透镜聚焦在半圆多元光电探测器上。此探测器将含有颗粒直径和颗粒数信息的衍射光信号转换成相应的电信号,经信号前置处理电路及USB数据采集卡转换成数字信号送入PC机计算处理,得到颗粒的粒度分布和浓度情况。
1.2数据采集卡简介
本系统采用某公司的USB2002型数据采集卡。主要性能指标如下:(a)模拟电压输入范围:±5V,±10V;(b)A/D转换分辨率:14Bit,32K字FIFO存储器;(c)32路单端模拟信号输入;16路双端模拟信号输入;(d)转换速率:400kHz;(c)程控增益(×1、2、4、8)。
2系统的软件实现
2.1线程
线程指的是程序代码的执行途径外加一组操作系统分配的资源(堆栈、寄存器状态等等)。线程一般分为用户界面线程和工作者线程两类,用户界面线程可以创建窗口并处理发送给这些窗口的消息;工作者线程执行后台任务,因其不接受用户的直接输入,所以不需要窗口和消息循环。线程的应用可以提高CPU的利用率,提高程序的响应能力,降低系统对数据采集速度的影响。
2.2系统软件实现
2.2.1软件组成
程序主要由两部分组成,一是数据采集部分,另一部分为数据处理部分(见图2)。数据采集部分对USB数据采集卡进行系统初始化、数据读取并存入数据缓冲区及释放系统资源停止数据采集等工作。数据处理部分进行原始数据的存储、数据计算、各个通道数据的数值和直方图实时显示以及获取各通道中的最大值为采集卡程控增益的设置提供依据。由于后者进行的数据计算和图形操作,需消耗CPU很多时间,在单线程的情况下将会阻塞主线程运行,出现采集数据溢出丢失的现象。
为此采用基于线程的多任务编程方法。
2.2.2数据采集线程
将数据采集部分定义为工作者线程(数据采集线程)。USB设备与AD转换进度同步完全由硬件和驱动程序自动完成。用户若要用程序方式实现连续数据采集,对其软件实现就显得极为容易。数据采集线程每次用ReadDeviceAD函数(USB采集卡接口函数)读取AD数据时,设备驱动程序会按照AD转换进度将AD数据一一放进用户数据缓冲区;当完成该次所指定的采样点数时,便会返回;当再次用这个函数读取数据时,会接着上一次的位置传递数据到用户数据缓冲区。高速数据采集要求每两次调用ReadDeviceAD之间的时间间隔越短越好。由图3数据采集线程流程图可知,为保证每两次ReadDeviceAD之间较小的时间间隔,应尽量减少USB设备AD初始化的次数。为此,采用了一次性设置增益的方法。即根据所采信号大小和对应的原增益计算出原始信号大小,然后根据信号应放大的数值换算出合适的增益进行一次设置。另外,设置了一个布尔控制变量(ParaChange)来记录增益是否被刚刚改变,如果刚刚改变就跳过增益是否应该改变(ADPARA)的判断直接读取采集数据从而减少读取采集数据时间间隔,以利于高速采集。图3中Runstatus为数据采集线程运行控制布尔变量。
2.2.3数据处理线程
将数据处理部分定义为数据处理线程,以便处理图形操作及数据处理等较耗时的工作。最初,数据处理线程不做任何工作,而是在Win32API函数WaitForSingleObject的作用下进入睡眠状态(见图2),此时它不消耗CPU任何时间,可保证数据采集线程代码有充分的运行机会。当数据采集线程取得指定长度的数据到用户空间时,再用Win32API函数SetEvent将指定事件消息发送给数据处理线程,则数据处理线程即刻恢复运行状态,迅速对这批数据进行处理。
2.2.4数据缓冲队列
数据处理线程可能处理花费CPU过多时间的工作,从而导致数据处理线程阻塞;而数据采集线程则在不停地采集数据,这样数据处理线程很有可能因此而丢失数据采集线程发来的某一段数据。为避免这个问题,建立了数据缓冲队列。即假设数据采集线程每一次从设备上取出8K数据,那么就创建一个缓冲队列,在用户程序中开辟一个两维数组,如Buffe(Count??1,DataLen??1),将DataLen视为数据采集线程每次采集的数据长度(DataLen必须等于采集通道数的整数倍),从而保证采集数据与各通道的一一对应关系。另外,也要注意在USB采集卡每次增益改变时要保证数据采集线程和数据处理线程从第一个缓冲队列的第一数据存储和读取。这可以保证采集数据与各通道的一一对应关系,以防止数据错位。Count则为缓冲队列的成员个数。应根据计算机物理内存大小和总体使用情况来设定。假如设成32,则这个缓冲队列实际上就是数组Buffer(31,8191)的形式,共32个缓冲队列(数组各维的基为0)。它跟一个普通的缓冲区,如一维数组差不多,唯一不同是,两个线程首先要通过改变Count字段的值,即Count的索引值(ReadIndex或ProcIndex)来填充和引用某一段DataLen长度的数据缓冲区。需要注意的是,两个线程不共用一个Count的索引值。具体情况(见图4)是当数据采集线程在AD部件被初始化之后,首次采集数据时,则将自己的ReadIndex下标置为0,即用第一个缓冲区采集AD数据。当采集完后,则向数据处理线程发送消息,且两个线程的公共变量Segments加1(Segments变量记录当前时刻缓冲队列中有多少个已被数据采集线程使用了,但是却没被数据处理线程处理掉的缓冲区数量。)然后再接着将ReadIndex偏移至1,再用第二个缓冲区采集数据。再将Segments加1,至到Readlndex等于32为止,然后再回到0位置,重新开始。而数据处理线程则在每次接受到消息时判断有多少由于自己被堵塞而没有被处理的缓冲区个数,然后逐一进行处理,最后再从Segments变量中减去在所接受到的当前事件下所处理的缓冲区个数。因此,即便是数据处理线程由于系统的偶尔繁忙而被堵塞,也很难使数据丢失。而且,通过这种方案,用户还可以在数据采集线程中对Segments加以判断,观察其值是否大于32,如果大于,则缓冲区队列肯定因数据处理线程的堵塞而被溢出;如果溢出则报警。因此,具有强大的容错处理能力。
3结束语
本文介绍了线程编程方法在激光粒度仪数据采集中的应用。经实验验证,采集速度能满足设计要求,而且,获得了理想的测量标准粒子的测量结果。