ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

LabVIEW DAQmx 实现 USB-6009 模拟电压生成与采集

LabVIEW DAQmx 实现 USB-6009 模拟电压生成与采集 简介这份PDF面向LabVIEW数据采集初学者与测控、电子类专业学生围绕NI USB6009数据采集卡与DAQmx底层VI讲解如何在同一程序中完成模拟电压的生成与采集。资源共1个PDF文件压缩包约845KB以图文并排的方式编排正文含前面板虚拟界面、程序框图以及各VI接线端子的截图便于对照理解。目前已有150人学习下载。内容覆盖总体方案与界面使用方法、条件结构与while循环的架构关系、运行状态指示灯的实现、模拟电压生成与采集两个主体模块的程序设计涉及DAQmx通道创建、开始任务、写入、读取、停止与清除任务等VI的搭配以及通道选择USB-6009/ao0、ai0、0-5V输出伏值、输出速率、每周期点数、1-1024通道采样数等参数配置和越限报错的处理思路。对需要动手搭建模拟电压测试、信号处理实验的读者而言可直接参照其接线与参数说明复现设计并借鉴其排错与结构组织方式。1. 从 AO0 到 AI0 短接那一刻USB-6009 上的 DAQmx 电压生成与回采一根杜邦线把 NI USB-6009 的 AO0 和 AI0 接在一起前面板上生成电压波形和采集电压波形两个波形图表就会画出两条几乎重合的正弦曲线。看起来平平无奇但做课程设计的人翻车的地方从来不在画正弦是 DAQmx 任务的状态没管住是物理通道名和 MAX 里的任务对不上是每通道采样数填了 2000 被对话框拦下来是布尔控件按下之后弹不回默认值导致启动第二次失效。这套基于 DAQmx 的模拟电压生成与采集系统选的是 LabVIEW 底层 DAQmx VI 而不是 Express VI先在 MAXMeasurement Automation Explorer里把 AO/AI 任务配好再用程序框图里的条件结构和双层 while 循环把生成与采集拼成一个可反复启停的闭环。适合三类人正在啃虚拟仪器课程设计的学生、第一次接数据采集卡不知道 RSE 是什么的工程师、以及想把 DAQ Assistant 换成底层 VI 却卡在任务句柄传递上的开发者。2. Express VI 与底层 DAQmx VI 的选型边界任务状态机与缓冲区语义2.1 快速 VI 替使用者省掉了什么DAQ Assistant 这类 Express VI 把通道配置、定时、触发、缓冲区管理全部塞进一个对话框勾选几下就能出数据功能单一的采集任务用它最省事。代价藏在三个地方其一一次调用内部就走完配置—采集—释放的完整链路没法在同一个任务生命周期里反复写入不同数据其二采样率、采样模式被限制在预设档位想做非整数的输出速率只能绕路其三出错时统一弹一个泛化对话框通道名写错和缓冲区溢出长得一模一样。底层 DAQmx VI 把这些拆成独立节点任务句柄通过 task out / task in 端子在线与线之间传递谁在哪一步出错一眼能看出来。原设计明确选底层 VI理由就是灵活性和执行效率——Express VI 每轮循环都要重新解析配置循环一快开销就上来了。2.2 DAQmx 任务的五态模型理解底层 VI 的前提是把任务当成一个有状态的对象而不是一次函数调用。创建、开始、读写、停止、清除这五步的顺序不能乱尤其停止和清除是两个不同动作混用会留下没释放的资源。阶段调用 VI内部动作跳过或顺序错误的后果创建通道DAQmx 创建通道 VI向任务注册物理通道、量程、接线端配置后续读写报无效通道开始任务DAQmx 开始任务 VI预留硬件资源、启动采样时钟写入的数据进不了硬件 FIFO读 / 写DAQmx 读取 / 写入 VI与设备缓冲区交换数据任务未开始则直接报错停止任务DAQmx 停止任务 VI结束采样任务回到未启动态再次开始前必须先停止清除任务DAQmx 清除任务 VI隐式停止并释放全部资源不清除则句柄泄漏设备被占用生成回路和采集回路在这里有个细节差别写入侧收尾用的是 DAQmx 清除任务 VI读取侧收尾用的是 DAQmx 停止任务 VI。清除是把任务整个销毁下次循环还得重新建通道停止只是让它退回未开始状态通道定义还在。原设计之所以这么分是因为写入任务通常在停止循环后就不再复用而读取任务在某些改法下需要保留配置。提示任务句柄的线必须从创建 VI 的 task out 一路拉到清除 VI 的 task in中间任何一次断裂都会让 DAQmx 在运行期报任务无效。2.3 单采样写入与 N 采样读取的语义差别写入侧选的多态实例是模拟 DBL 1 通道 1 采样即每调用一次 write只向 ao0 推一个双精度电压值。这意味着波形的时序完全由 while 循环的节奏决定循环里加的等待时间就是采样间隔DAQmx 本身不提供硬件定时——USB-6009 的模拟输出本来就是软件定时的按需更新。import math import time import nidaqmx from nidaqmx.constants import TerminalConfiguration V_MIN, V_MAX 0.0, 5.0 # USB-6009 模拟输出允许区间超出会报错 POINTS_PER_CYCLE 100 # 每周期点数越大波形越接近理想正弦 UPDATE_MS 1.0 # 相邻两个输出点之间的间隔单位毫秒 def build_sine(n): mid (V_MAX V_MIN) / 2.0 amp (V_MAX - V_MIN) / 2.0 return [mid amp * math.sin(2 * math.pi * i / n) for i in range(n)] samples build_sine(POINTS_PER_CYCLE) freq 1000.0 / (UPDATE_MS * POINTS_PER_CYCLE) # 由参数推导出的输出频率 print(f输出频率约 {freq:.2f} Hz) with nidaqmx.Task() as ao_task: ao_task.ao_channels.add_ao_voltage_chan( Dev1/ao0, min_valV_MIN, max_valV_MAX, terminal_configTerminalConfiguration.RSE) ao_task.start() while not stop_flag: for v in samples: ao_task.write(v, auto_startFalse) # 单通道单采样写入 time.sleep(UPDATE_MS / 1000.0) if stop_flag: break这段代码对应程序框图里创建通道—开始任务—写入—清除任务的连线。add_ao_voltage_chan的两个量程参数必须落在 0 到 5 之间和 MAX 里配的最大最小伏值保持一致sleep的时间就是前面板上输出速率控件填的毫秒数build_sine把 sin 的 -1 到 1 映射到 0 到 5这样波形整体抬升到正电压区间不需要额外偏置电路。频率不是直接设的而是由输出速率和每周期点数算出来的——这也解释了为什么原设计用数值显示控件实时显示生成电压频率而不是让用户直接填频率。读取侧的多态实例是模拟 1D 波形 N 通道 N 采样一次调用返回一整块带时间信息的波形数据t0 和 dt 由 DAQmx 填好直接喂给波形图表就能正确显示横轴时间。with nidaqmx.Task() as ai_task: ai_task.ai_channels.add_ai_voltage_chan( Dev1/ai0, min_val0.0, max_val5.0, terminal_configTerminalConfiguration.RSE) ai_task.timing.cfg_samp_clk_timing( rate1000.0, sample_modenidaqmx.constants.AcquisitionType.CONTINUOUS) ai_task.start() while not stop_flag: data ai_task.read(number_of_samples_per_channelSAMPLES_PER_CHANNEL) plot(data) # 每通道采样数决定单次读取的点数number_of_samples_per_channel就是前面板上的通道采样数输入控件USB-6009 只接受 1 到 1024超限时 DAQmx 会抛出带原因说明的错误程序里用简易错误处理器把它转成对话框。这里没有做硬件触发对齐生成和采集各自独立循环两条曲线在时间轴上会有微小错位这是软件定时方案的固有代价。3. MAX 中创建 AO/AI 任务USB-6009 通道参数与 RSE 接线配置3.1 先把 USB-6009 的模拟量边界记住接线和配置之前先看硬件能干什么否则参数填得再漂亮也跑不出波形。USB-6009 属于低成本多功能采集卡模拟输出的量程固定模拟输入的分辨率和采样率也有上限这些数字直接决定前面板控件的合法区间。项目USB-6009 参数对前面板控件的约束AO 通道数2 路ao0、ao1通道选择下拉框只有 ao0/ao1 可选AO 输出电压范围0 至 5 V最大/最小伏值控件必须落在此区间AO 更新方式软件定时按需更新输出速率由循环等待时间决定AI 通道数8 路单端 / 4 路差分单端接法选 ai0 到 ai7AI 分辨率14 位波形台阶感来自这一项每通道采样数1 至 1024超限直接报错不会截断注意AO 的量程是 0 到 5 V不是 ±5 V。前面板如果把最小值填成 -2DAQmx 会在创建通道阶段就拒绝而不是等到写入时才提醒。3.2 在 MAX 里建一个模拟输出任务在计算机上插好 USB-6009等设备被识别出来后打开 MAX左侧配置树里能看到设备和接口下的 NI USB-6009。右键数据邻居新建任务选生成信号下的模拟输出再选电压。通道列表里勾选 ao0给任务起个能看懂的名字比如 ao_sine_task。建完任务立刻做参数配置最大伏值填 5最小伏值填 0接线端配置选 RSE参考单端模式以系统地作为参考进行测量生成模式选1 采样。生成模式这一项容易被忽略——选成 N 采样会让 MAX 按缓冲区方式驱动与后面 LabVIEW 里逐点写入的单采样模式对不上表现就是波形时快时慢。模拟输入任务用同样的流程再建一遍新建任务、生成信号里的模拟输入、电压、勾选 ai0最大最小伏值同样填 5 和 0接线端配置也是 RSE。两个任务都建好后建议在 MAX 里先点一次测试看输出电压能不能手动改、输入读数有没有跟随变化确认硬件和驱动都正常再回到 LabVIEW。如果习惯用脚本化方式核对配置可以用 nidaqmx 直接列出设备与通道确认物理通道名和 MAX 里看到的一致# 列出系统识别到的 NI 设备与产品类型 python -c import nidaqmx; print(nidaqmx.system.System.local().devices) # 查看 Dev1 上可用的模拟输入/输出通道名 python -c import nidaqmx; dnidaqmx.system.Device(Dev1); \ print([c.name for c in d.ai_physical_chans]); \ print([c.name for c in d.ao_physical_chans])第一行确认设备有没有被驱动正确接管如果列表为空说明 USB 连接或驱动安装有问题跟 LabVIEW 程序无关。后两行打印出的通道名就是前面板下拉框里该出现的字符串比如Dev1/ao0、Dev1/ai0MAX 里显示成USB-6009/ao0的写法本质是同一路通道的别名。3.3 接线AI0 与 AO0 之间的那根线硬件连线只有一步用导线把 AI0 和 AO0 短接。这样 ao0 上推出去的电压直接落在 ai0 的输入端形成自发自收的回路。地线不需要额外接因为 RSE 模式下测量参考的是系统地两个通道共用同一块板卡的参考电位。提示生成和采集用了同一块卡的同一组地所以不需要考虑共模电压问题如果换成两块独立设备互连RSE 接法就会引入地环流误差。通道必须成对匹配。硬件上接的是 AI0 和 AO0MAX 里任务里勾的是 ao0 和 ai0LabVIEW 前面板的下拉框里就得选USB-6009/ao0和USB-6009/ai0。这三处任何一处错位现象都一样波形图表是空的或者是一根直线但错误对话框不一定弹——因为程序逻辑完全跑通了只是物理上取不到信号。3.4 通道创建 VI 上该建哪些输入控件DAQmx 创建通道 VI 在 AI 电压和 AO 电压两种模式下接线端子并不完全相同。读取侧用到的是物理通道、最小值和最大值其中物理通道建一个输入控件挂到前面板让用户自己选写入侧除了物理通道还要把最大值和最小值也做成数值输入控件因为输出电压的上下限是随任务变的写死就没有灵活性了。这与物理通道必须和实际接线及 MAX 任务配置一致的约束配合构成了整个系统最容易出错也最该显式暴露的地方。4. 程序框图落地条件结构 双层 while 循环里的 DAQmx 写入与读取4.1 三层嵌套结构各自负责什么程序框图的骨架是三层最外层一个 while 循环终止条件是退出系统按钮里面套一个顺序结构第一帧专门用来把布尔控件恢复默认值顺序结构之后是条件结构触发条件是启动按钮按下条件为真时执行模拟电压生成和采集的主体程序。最外层循环的存在意义是让启动停止能无限次交替。主体条件结构内部的 while 循环用停止按钮或退出系统按钮终止一旦停止本次顺序执行结束回到最外层循环顺序结构重跑一遍第一帧里的调用节点把状态指示灯和按钮值全部复位然后条件结构再次等待启动。如果没有最外层这圈循环程序按一次停止就彻底结束了。4.2 布尔控件的属性节点与机械动作复位这里有个不写清楚就会被坑的细节使用了属性节点值改变的布尔输入控件机械动作只兼容前三种——也就是说控件按下后不会自动弹回默认状态。启动按下之后一直保持按下态条件结构就会一直停在真分支第二次按停止再按启动时行为就乱了。所以在主体程序运行之前必须用这些控件的调用节点把它们全部恢复默认值。顺序结构的第一帧正是干这件事把启动停止控件的值写回假系统运行状态指示灯也置为关闭。指示灯的状态切换则分布在两处条件结构真分支里给布尔显示控件赋真值让灯变绿顺序结构第一帧里的调用节点把它关掉变红。外层 while终止退出系统 真 ├── 顺序结构 第0帧恢复启动/停止控件默认值运行状态灯置假 └── 条件结构选择器启动 真 ├── 真分支AI0 采集 while 循环 AO0 生成 while 循环 │ 终止条件 停止 或 退出系统 或 通道出错 └── 假分支空注意属性节点和调用节点的区别要分清。属性节点改的是控件在界面上的值调用节点执行的是控件的方法例如恢复默认值。混用会出现界面上按钮已经弹回但程序读到的还是真值这种诡异现象。4.3 DAQmx 写入 VI 的多态实例与错误处理生成部分的节点顺序是DAQmx 创建通道 VI 选模拟电压输出模式接 DAQmx 开始任务 VI再接 DAQmx 写入 VI循环结束后接 DAQmx 清除任务 VI错误线一路串到简易错误处理器 VI。写入 VI 的多态实例选模拟、单通道、单采样、DBL任务/通道输入端与开始任务的任务输出端相连数据端接数学运算生成的正弦波形值。整个写入过程包在 while 循环里停止条件有三条按了停止、退出系统或者通道写入出错。三条条件是或关系任意一条成立就跳出。跳出后清除任务VI 会先停止任务必要时释放任务保留的资源。出错时简易错误处理器把错误转成对话框对话框类型常量选的是OK message warnings所以弹出的是带警告文字和确定按钮的框不会直接中断程序。4.4 DAQmx 读取 VI 的 1D 波形输出与采样数控件采集部分的节点顺序是创建通道 VI 选模拟电压输入模式接开始任务 VI接 DAQmx 读取 VI循环结束后接 DAQmx 停止任务 VI错误线同样接到简易错误处理器。读取 VI 的多态实例选模拟、多通道、多采样、1D 波形在每通道采样数端建一个输入控件前面板就能改这个值。数据端接一个标签为采集电压波形的波形图表读取回来的波形直接送进去显示。这里停止任务和清除任务的选择值得说一句读取侧用停止任务任务只是回到未开始状态通道定义保留。如果改写成用清除任务收尾下一次进入循环时创建通道 VI 会重新注册一遍功能上没问题但每次启停都要重新枚举设备资源启停响应会明显变慢。两个模块的循环是各自独立的没有做数据依赖同步。想让生成和采集在时间上更贴合常见做法是把写入的循环号或时间戳通过局部变量传给采集侧做对齐标记但这会引入额外的耦合课程设计阶段一般不做。5. 采样数越界、初期停止异常与波形毛刺几个能被复现的排错手法5.1 采样数超限与参数生效时机通道采样数填到 1024 以上系统会弹对话框报错并说明原因这是 DAQmx 在读取 VI 里抛出的错误被简易错误处理器接住的结果不是自己写的校验。想更早拦截可以在参数配置阶段加一次范围判断把 1 到 1024 的边界显式写进程序省得用户按一次启动才发现问题。参数生效时机是另一个高频疑问运行状态下改配置界面上的值立刻变了但波形不变。原因是写入循环读的数据来自循环内的常量或已生成的数组新参数要等条件结构重新进真分支才被采一次。所以正确操作顺序是先按停止回到停止状态改参数再按启动。想做到实时生效就得把参数读取放进 while 循环内部代价是每个点都要重算波形采样率会被拖下来。5.2 启动初期立刻停止导致整个程序退出原设计自己也记了一处待优化系统在启动初期立即停止运行时有时会终止整个程序而不是只停主体程序。从结构上推问题出在停止和退出系统两个按钮的终止条件被接到了同一层循环上——如果停止的按下沿恰好落在最外层循环判断的那一瞬最外层循环也会被误判终止。常见做法是把最外层循环的终止条件严格限定为退出系统一个布尔量用独立的局部变量或移位寄存器传递状态不让停止参与最外层的判断。5.3 波形毛刺与回读偏差的验证手法生成的正弦看起来有台阶或者偶尔跳变按下面顺序查现象优先排查项验证方法波形呈阶梯状每周期点数偏少从 20 加到 100 以上再看波形频率偏低输出速率毫秒数偏大频率 1000 /(速率 × 每周期点数)曲线整体偏移AI 端量程与 AO 不匹配两端都设 0 到 5 V读数偶尔跳变循环内做了耗时运算把运算挪到循环外预计算图表完全空白通道名与接线不一致核对 ao0/ai0 三处配置最直接的验证是把数据导出后做一次频域检查用最小二乘拟合确认幅值和频率import numpy as np rate 1000.0 # 采集端配置的采样率(Hz) data np.asarray(acquired) # 波形图表背后的那串采样点 n len(data) freqs np.fft.rfftfreq(n, d1.0 / rate) peak freqs[np.argmax(np.abs(np.fft.rfft(data - data.mean())))] print(f实测主频 {peak:.2f} Hz峰峰值 {data.max() - data.min():.3f} V)rfftfreq给出正频率轴rfft做实数快速傅里叶变换减均值是为了去掉直流偏置的影响——正弦被抬升到 0 到 5 V 后均值约 2.5 V不减掉的话谱峰会被直流分量淹没。实测主频和用1000/(速率×点数)算出来的理论值差在几个百分点以内就算正常差得离谱就回去看采集端采样率是不是写成了别的值。峰峰值明显小于 5 V通常是 RSE 接线端配置在某一侧没设对或者输出量程被限制在了一个更窄的区间。本文还有配套的精品资源点击获取
返回列表