Skip to main content

MangoTree DAQ Device SDK

Project description

MTDAQ Demo 设计思路与注意事项

环境

依赖 版本
Python 3.14.0
numpy 2.4.4
PyQt5 5.15.11
pyqtgraph 0.14.0
mtdaq 1.1.0

1. 概述

本文档描述MangoTree设备数据采集面板的设计思路,旨在与以下材料配合使用,让生成式 AI 能自主生成不同 MangoTree 设备、不同工作模式的实时采集监控面板:

输入材料 作用
本文档 设计思路、架构决策、适配方法、常见坑点
X612/AIO.py 已注释的参考实现 (MT-X612 / General AIO 模式)
X612/DI_Trigger_AI.py 已注释的参考实现 (MT-X612 / DI-Trigger-AI 模式)
D814/AIO.py 已注释的参考实现 (MT-D814 / General AIO 模式)
D814/AIO_Sync.py 已注释的参考实现 (MT-D814 / AOSyncAI 同步模式)
D814/DIO.py 已注释的参考实现 (MT-D814 / General DIO 模式)
X610/AIO.py 已注释的参考实现 (MT-X610 / General AIO 模式)
mtdaq 库 Device API、Mode 枚举、config.txt 配置模板
设备信息 来自 MangoTree 官网 Datasheet/网页的设备规格 (通道数/采样率/类型等)

技术栈: Python 3, PyQt5, pyqtgraph, numpy, threading.

现有 Demo 清单:

目录 文件 设备 模式 功能
X612/ AIO.py MT-X612 General (0) 6 AI + 2 AO + 采样率枚举下拉
X612/ DI_Trigger_AI.py MT-X612 DI-Trigger-AI (5) 6 AI (触发) + 2 AO
D814/ AIO.py MT-D814 General (0) 16 AI + 4 AO + 独立输入采样率
D814/ AIO_Sync.py MT-D814 AOSyncAI (1) 16 AI + 4 AO + 同步采样率 (125kHz max)
D814/ DIO.py MT-D814 General (0) 16 DI (指示灯) + 16 DO (翘板开关)
D814/ AIO_Test.py MT-D814 General (0) 16 AI + 4 AO 通道检测 + 分析报告
X610/ AIO.py MT-X610 General (0) 2 AI + 2 AO + 48k/96k/102.4k/192k/204.8k 采样率

文件命名规范:每个 demo 按其功能以大写驼峰命名——AIO.py(模拟输入/输出)、DIO.py(数字输入/输出)、DI_Trigger_AI.py(DI 触发 AI 采集)。历史聊天记录保留在 生成MT-X612 AIO General模式Demo.md 中供参考。


1.1 获取设备信息

生成新设备 demo 前,需要从官方渠道获取目标设备的完整规格参数。

官网产品页

产品类别 官网链接
MT-PXIe 模块 (主页面) https://www.mangotree.cn/p/19659/
MT-PXIe 模块 (列表页) https://www.mangotree.cn/p/225128/
APP-PXIe 模块产品 https://www.mangotree.cn/p/1062267/
APP-PXIe 控制器产品 https://www.mangotree.cn/p/1062266/
APP-PXIe 机箱产品 https://www.mangotree.cn/p/1062265/
PXI 机箱、控制器 https://www.mangotree.cn/app-video/hot.html
PCB-RIO https://www.mangotree.cn/product/659354/

Datasheet PDF 目录结构

所有设备 Datasheet PDF 存放在 server.mangotree.cn:9900,按设备类别分层组织:

数据手册/
├── AtomDAQ/              # 一体机 (D814, D815...)
├── AtomRIO/              # Atom RIO 系列
├── E系列采集卡/           # E 系列采集卡
├── PCB-RIO/              # PCB RIO 系列
├── PCIe DAQ模块/          # PCIe DAQ 模块
├── PXIeAll/
│   ├── PXIe-Chassis/     # PXIe 机箱
│   ├── PXIe-Controller/  # PXIe 控制器
│   └── PXIe-Module/
│       ├── DAQ/          # DAQ 模块 (X300~X776, 100+ 型号)
│       ├── RIO/          # FPGA 板卡 (X900~X971)
│       └── Switch/       # 开关模块
├── RobustRIO/            # Robust RIO 系列
├── 产品手册/              # 整体产品手册
└── 雷电模块/              # 雷电接口模块

PDF URL 模式:

# PXIe DAQ 模块
https://server.mangotree.cn:9900/WebFile/Downloads/数据手册/PXIeAll/PXIe-Module/DAQ/{型号}/MT-{型号}%20DataSheet.pdf

# PXIe RIO (FPGA) 模块
https://server.mangotree.cn:9900/WebFile/Downloads/数据手册/PXIeAll/PXIe-Module/RIO/{型号}/MT-{型号}%20DataSheet.pdf

# AtomDAQ 一体机
https://server.mangotree.cn:9900/WebFile/Downloads/数据手册/AtomDAQ/{型号}/MT-{型号}%20DataSheet.pdf

已知 Datasheet 链接:

型号 类别 路径
MT-D814 AtomDAQ 一体机 AtomDAQ/D814/MT-D814%20DataSheet.pdf
MT-D815 AtomDAQ 一体机 AtomDAQ/D815/MT-D815%20DataSheet.pdf
MT-X590 32bit 高精度 8AI PXIeAll/PXIe-Module/DAQ/X590/
MT-X591 32bit 高精度 6AI+2AO PXIeAll/PXIe-Module/DAQ/X591/
MT-X596 32bit 高精度 34AI+4AO PXIeAll/PXIe-Module/DAQ/X596/
MT-X606 热电偶采集 PXIeAll/PXIe-Module/DAQ/X606/
MT-X610 声音振动 2AI+2AO PXIeAll/PXIe-Module/DAQ/X610/
MT-X612 声音振动 6AI+2AO PXIeAll/PXIe-Module/DAQ/X612/
MT-X613 声音振动 4AI+IEPE PXIeAll/PXIe-Module/DAQ/X613/
MT-X614 声音振动 PXIeAll/PXIe-Module/DAQ/X614/
MT-X900 FPGA 纯数字 DIO 128ch PXIeAll/PXIe-Module/RIO/X900/
MT-X920 FPGA DIO+AI/AO 混合 PXIeAll/PXIe-Module/RIO/X920/

提示: server.mangotree.cn:9900 的目录页可直接浏览, 点击进入子目录即可查看所有型号列表。

PDF 文本提取方法

Datasheet PDF 可通过 pdftotext 或 Python (PyPDF2/pdfplumber) 提取文本:

# 方法1: pdftotext (poppler-utils)
pdftotext -layout MT-X610_DataSheet.pdf output.txt

# 方法2: Python pdfplumber
python -c "import pdfplumber; pdf=pdfplumber.open('MT-X610_DataSheet.pdf'); [print(p.extract_text()) for p in pdf.pages]"

提取后重点查看: 首页标题行 (通道数/分辨率/采样率)、AI/AO 章节的 "Support Sample rate" 行、Idle Channel Noise 表。

第三方信息源

当官网 PDF 无法直接获取时,以下渠道可获取设备规格:

来源 说明
elecfans.com 电子发烧友,有 MangoTree 32bit 精度实测系列文章
eepw.com.cn 电子产品世界,有 MangoTree 新品发布和技术文章
red-hb.com MangoTree 代理商/合作伙伴,部分产品页有详细规格表
Web Search 搜索 MT-X{型号} PXIe 规格 采样率 可找到分散在多个平台的产品信息

适配 demo 需要提取的关键规格

从 Datasheet/产品页中提取以下信息用于 SAMPLE_RATESDEFAULT_CONFIGinfo_groupsetup_ui 的填写:

参数 用途
AI 通道数 DEFAULT_CONFIG["ai_channels"]、动态曲线数量
AO 通道数 DEFAULT_CONFIG["ao_channels"]、AO 控件数量
支持的采样率 SAMPLE_RATES 字典
电压范围 plot_widget.setYRange()QDoubleSpinBox.setRange()
分辨率 (bit) info_group 设备信息文本
耦合方式 info_group 设备信息文本
总线类型 (PXIe/USB) info_group 设备信息文本
特殊功能 (IEPE/触发等) info_group 设备信息文本、Config 附加段

2. 架构设计

2.1 三层结构

DAQManager (设备管理层)
  ├── _ai_loop 线程: 循环 dev.analogRead() → 共享缓冲区
  ├── _ao_loop 线程: 循环生成波形 → dev.analogWrite()
  └── _data_version: 单调递增, 标记新数据

MainWindow (UI 层)
  ├── QTimer(33ms) → update_ui(): 版本号比对, 拷贝新数据
  ├── _render_latest(): 更新 pyqtgraph 曲线
  └── 暂停: 快照 pausing_data, 切换可见性只操作快照

UI 布局 (QSplitter 左右分栏)
  ├── 左侧: 设备信息/配置/启停/暂停/AO控制
  └── 右侧: pyqtgraph 波形图 + 右上角半透明图例浮层

2.2 数据流 (版本号驱动刷新)

_ai_loop 线程:
  analogRead(samples) 阻塞等待
    → reshape 为 (samples, channels)
    → lock(_data_lock):
        _latest_data = arr.copy()
        _data_version += 1

UI 定时器 (33ms 轮询):
  if paused: return
  if _data_version == _last_data_version: return  // 无新数据, 跳过
  _last_data_version = version
  lock(_data_lock): pending_data = _latest_data.copy()
  _render_latest()

为什么不用 Queue: analogRead 在 General 模式下每次阻塞约 1 秒才返回数据,Queue 会让定时器每 33ms 空转检查、暂停时积压数据。版本号方案只在有新数据时才做一次拷贝+渲染。

2.3 暂停/继续机制

暂停: _paused_data = pending_data.copy()   // 快照
      update_ui 中 if paused: return        // 不接触新数据
      _render_latest 中 从 _paused_data 读取 // 复选框操作快照

继续: _last_data_version = -1              // 强制下次刷新
      _paused_data = empty
      _render_latest()                      // 立即渲染最新数据

2.4 DIO 模式的架构差异

DIO demo 不含 AI/AO,架构更简洁:

DAQManager
  ├── _di_loop 线程: digitalRead() → uint64 写入共享缓冲区 + 版本号
  └── digitalWrite(dodata): 由 UI 线程通过信号直接调用

MainWindow (UI 层)
  ├── QTimer(33ms) → update_ui(): 版本号比对, 逐 bit 更新 DI 指示灯颜色
  ├── DO 翘板开关: QPushButton(checkable) → on_do_toggled() → digitalWrite()
  └── DI 指示灯: QFrame 圆形, 绿色=1, 灰色=0

关键 API 差异:

  • digitalRead() 返回 ctypes.c_uint64,通过 .value 获取 int,每 bit 对应一个通道
  • digitalWrite(dodata) 写入 int,每 bit 对应一个通道,低位先
  • DI 轮询间隔:stop_event.wait(0.03) 控制 ~33Hz 读取频率
  • 无需 Queue 或版本号:DI 数据只有 64bit,直接状态比对

3. Config 配置系统

3.1 配置模板来源

配置模板定义在 mtdaq 库源码目录下的 config.txt 文件中 (与 mtdaq.py 同级)。

所有 MTDAQ 设备通过一个 XML-like 字符串进行配置。关键段:

<Device>        <!-- 设备标识: 型号/IP/ID/Slot (ID和Slot可用*) -->
<Advance>       <!-- Reset-Device=Auto/Force; Clock-From=Onboard/MT-Chassis -->
<DAQMode>       <!-- 工作模式: 0~7 (见 Mode 枚举), Path 仅 Mode=7 有效 -->
<AI>            <!-- AI-Channel 通道列表; AI-SampleRate -->
<AO>            <!-- AO-Channel 通道列表; AO-SampleRate -->
<DITrigger>     <!-- 仅 Mode=4/5/6: DITrigger-Channel/SampleClock/Direction/AIOSamplePerTrigger -->
<TC>            <!-- 热电偶: TC-Channel/SampleRate/Type/CJC-Type -->
<RTD>           <!-- 热电阻: RTD-Channel/4wire或3wire -->
<DI>/<DO>       <!-- 低速数字IO -->
<DigitalWaveformInput>  <!-- 高速数字波形输入 -->
<DigitalWaveformOutput> <!-- 高速数字波形输出 -->
<Counter>       <!-- 计数器 -->
<PWM>           <!-- 脉宽调制 -->
<Encoder>       <!-- 编码器 -->

3.2 工作模式 (Mode 枚举)

DAQMode 枚举值 含义 需要的额外配置段
0 General AI/AO 独立运行
1 AOSyncAI AO 同步 AI
2 AISyncEncoder AI 同步 Encoder <Encoder>
3 EncoderSyncAI Encoder 同步 AI <Encoder>
4 DITrigerAISyncAO DI 触发, AI/AO 同步 <DITrigger>
5 DITrigerAI DI 触发 AI, AO 独立 <DITrigger>
6 DITrigerAO DI 触发 AO <DITrigger>

3.3 Config 字符串生成模式

各 demo 中 build_config() 用 Python f-string 模板生成 Config。生成新 demo 时:

  • 修改 Device-Model 为目标设备型号 (如 X614, X550, X920 等)
  • 修改 DAQMode 为目标工作模式
  • 根据模式添加/删除配置段: 如触发模式需添加 <DITrigger>
  • 通道号和采样率 用参数字典占位符 {cfg["key"]} 动态替换

3.4 通道范围语法

Config 中通道字段支持 范围写法,用尖括号 <m-n> 表示从 m 到 n(含两端)的所有连续通道号:

写法 等价展开
<0-5> 0,1,2,3,4,5
<0-2>,4 0,1,2,4
<0-7>,<12-15> 0,1,2,3,4,5,6,7,12,13,14,15

范围与单独通道可混用,仍以逗号 , 分隔。Demo 中通道数较多时(如 D814 的 16 通道),应优先使用范围写法以提高可读性:

"di_channels": "<0-15>"   # ✅ 清晰
"di_channels": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15"  # ❌ 冗长

4. DAQManager — 设备管理层的设计

4.1 职责边界

DAQManager 只负责设备和数据,不持有任何 UI 引用。它通过以下接口与 UI 层交互:

方向 接口
UI → Manager start() / stop() / update_ao_param() / set_chunk_samples()
Manager → UI running / error / num_channels / num_ao_channels / _data_version / _latest_data

4.2 AI 采集线程

def _ai_loop(self):
    while not self.stop_event.is_set():
        data_raw = self.dev.analogRead(samples=samples)
        arr = np.ctypeslib.as_array(data_raw)      # ctypes → numpy
        arr = arr.reshape(samples, self.num_channels)
        with self._data_lock:
            self._latest_data = arr.copy()
            self._data_version += 1

关键点

  • analogRead 返回 ctypes float 数组,数据交错存储: [ch0_s0, ch1_s0, ch0_s1, ch1_s1, ...]
  • reshape(samples, channels) 将其转为便于按列索引的二维数组
  • .copy() 必须调用,因为下一次 analogRead 可能覆写 ctypes 缓冲区
  • _data_version 递增告知 UI 有新数据

4.3 AO 输出线程

def _ao_loop(self):
    t_base = 0.0  # 全局时间基准, 保证相位连续
    while not self.stop_event.is_set():
        t = np.linspace(t_base, t_base + CHUNK_SECONDS, samples, endpoint=False)
        t_base += CHUNK_SECONDS
        for each channel:
            wave = amp * sin(2π * freq * t)
            full_ao_data[ch_idx::num_channels] = wave  # 交错写入
        self.dev.analogWrite(full_ao_data.tolist())

关键点

  • 输出格式与输入相同:交错存储 [ch0_s0, ch1_s0, ...]
  • t_base 必须跨循环累积,否则每次输出开头会有相位跳变
  • 通过 ao_lock 保护 ao_params,UI 线程可安全修改参数

4.4 通道数查询

self.num_channels = self.dev._get_cached_channel_num("AI")

支持查询的通道类型: "AI", "AO", "HSDI", "HSDO", "CI", "CO", "Encoder", "TC"

4.5 低速数字 I/O (LDI/LDO)

# 读取 DI: 返回 ct.c_uint64, 每 bit 对应一个通道 (低位先)
ldi = self.dev.digitalRead()
di_value = ldi.value  # int

# 写入 DO: 传入 int, 每 bit 对应一个通道 (低位先)
self.dev.digitalWrite(do_value)

DI 轮询线程:使用 stop_event.wait(0.03) 替代 time.sleep,可以被 stop_event.set() 立即中断退出。

def _di_loop(self):
    while not self.stop_event.is_set():
        raw = self.dev.digitalRead()
        with self._di_lock:
            self._latest_di = raw.value
            self._di_version += 1
        self.stop_event.wait(0.03)  # ~33Hz 轮询

DO 写入:直接由 UI 线程调用,无需后台线程。通过 QPushButton(checkable)clicked 信号触发,更新内部 _do_state 位掩码后调用 digitalWrite


5. 生成不同设备/模式 Demo 的适配清单

5.1 必须修改的位置

位置 修改内容 示例
SAMPLE_RATES 设备支持的采样率 X550: {"48kHz":48000,"96kHz":96000,"200kHz":200000}
DEFAULT_CONFIG 默认 IP/通道/采样率 改为目标设备的默认值
build_config() 设备型号和 DAQMode Device-Model=X550; + DAQMode=5;
setup_ui()info_group 设备信息文本 型号/模式说明/通道规格
__init__ 中的 setWindowTitle 窗口标题 "MT-X550 DI-Trigger-AI"

5.2 按需修改的位置

场景 修改内容
触发模式 (Mode=4/5/6) build_config() 添加 <DITrigger> 段;_ai_loopanalogRead 行为变为阻塞等待触发
无 AO 的设备 DAQManager 中 num_ao_channels 为 0 时自动隐藏 AO 控件,无需额外处理
通道数不同的设备 无需修改代码,setup_curves() 根据实际通道数动态创建
其他 I/O 类型 (计数器/编码器/DIO) 1) build_config() 添加对应段 2) DAQManager 新增采集线程 3) UI 新增控制面板
DIO 专用 (DI+DO) 1) build_config() 不需要 <AI>/<AO> 2) 参考 D814/DIO.py 的 DI 轮询 + DO 翘板开关模式 3) UI 用 QGridLayout 排列指示灯和开关
不同电压范围 修改 plot_widget.setYRange()QDoubleSpinBox.setRange()
采样率输入方式 X61 系列 (声音振动): 采样率为固定枚举值, 用 QComboBox 下拉框; 其余设备: 采样率可自由输入, 用 QLineEdit 输入框. 不要使用预设按钮

5.3 触发模式注意事项

  • Mode=5 (DITrigerAI): analogRead 阻塞等待 DI 触发,触发后一次性返回指定采样点
  • <DITrigger> 段字段名严格遵循 config.txt:
    • DITrigger-Channel=0;
    • DITrigger-SampleClock=500000Hz; (触发检测时钟,最大 1MHz)
    • DITrigger-Direction=0; (0=RisingEdge, 1=FallingEdge, 2=EitherEdge)
    • DITrigger-AIOSamplePerTrigger=-1; (-1=连续采样, N=每次触发采N点)
  • 触发模式下 _data_version 更新频率取决于触发频率,定时器需保持轮询

6. PyQt5 UI 设计要点

6.1 布局结构

  • QSplitter(Qt.Horizontal) 左右分栏,stretch 比例 1:4
  • 左侧控制面板用 QVBoxLayout 垂直排列各控件组
  • 右侧图表用 QVBoxLayout 填满 pyqtgraph PlotWidget

6.2 图例浮层

图例面板是 QFrame,parent 设为 plot_container 而非 plot_widget。原因:PlotWidget 内部的 ViewBox 有坐标变换,子控件的绝对定位会受影响。使用外层容器配合 move(x, y) 精确定位。

self.legend_panel = QFrame(plot_container)  # 非 plot_widget
self.legend_panel.move(x, y)                # 绝对定位到右上角

编辑框宽度自适应:通过 QFontMetrics.horizontalAdvance() 计算所有编辑框中最长文本的像素宽度,统一设置;文字变化时通过 textChanged 信号自动重新同步。

6.3 启动/停止时的 UI 状态管理

状态 配置控件 启动按钮 停止按钮 暂停按钮 定时器 曲线
初始 enabled enabled disabled disabled 停止
运行中 disabled disabled enabled enabled 运行 动态创建
已停止 enabled enabled disabled disabled 停止 已清除

暂停按钮仅在运行中可用。文本在"暂停"/"继续"之间切换。

6.4 AO 控件闭包

def make_update(idx, a=amp_spin, f=freq_spin):
    def update():
        if self.manager:
            self.manager.update_ao_param(idx, a.value(), f.value())
    return update

update_fn = make_update(i)
amp_spin.editingFinished.connect(update_fn)

为什么用闭包而不是 lambda: Python 的 lambda 在循环中会产生延迟求值问题——所有 lambda 会捕获同一个变量 i,最终都是循环终止时的值。闭包通过默认参数 a=amp_spin, f=freq_spin 在定义时绑定当前值。

6.5 DIO 控件设计

DI 指示灯: QFrame 固定尺寸 (14×14px),圆角样式 (border-radius: 6px)。绿色 (#00ff00) 表示高电平,深灰 (#333333) 表示低电平。

DO 翘板开关: QPushButton(checkable=True) 配合样式表模拟翘板开关。checked 伪状态切换背景色:未选中深灰 (#444),选中绿色 (#228B22)。

btn = QPushButton()
btn.setCheckable(True)
btn.setFixedSize(48, 24)
btn.setStyleSheet("""
    QPushButton { background-color: #444; border: 1px solid #777; border-radius: 10px; }
    QPushButton:checked { background-color: #228B22; border: 1px solid #00ff00; }
""")
# 闭包捕获通道索引, 避免循环变量延迟求值
btn.clicked.connect(lambda checked, c=ch: self.on_do_toggled(c))

位掩码管理: DO 状态用一个 _do_state int 表示,on_do_toggled(ch) 通过 bit = 1 << ch 翻转对应位后调用 digitalWrite(_do_state)

布局: DI/DO 各 16 通道用 QGridLayout 排列,每行 8 列(每个通道占 2 列:控件+标签)。


7. 关键约束与注意事项

7.1 线程安全

资源 保护方式
_latest_data + _data_version threading.Lock() (_data_lock)
ao_params threading.Lock() (ao_lock)
Qt 控件 只能主线程访问 (通过信号/槽和 QTimer)

禁止在后台线程直接操作 Qt 控件。后台线程只更新 DAQManager 的数据字段,UI 线程通过 QTimer 回调读取。

7.2 设备生命周期

  • mtdaq.Device(config_str) — 创建但不启动
  • dev.start() — 调用 DLL MTDAQ_Start,获取设备引用
  • dev.close() — 调用 DLL MTDAQ_Close,释放设备
  • 必须在 start() 后调用 _get_cached_channel_num() 才能获取通道数
  • close()stop() 中调用,stop() 需等待线程退出后再 close

7.3 资源清理

  • closeEvent 中必须调用 stop_device()
  • stop_device() 的清理顺序: manager.stop()timer.stop()clear_curves()
  • clear_curves() 中: 移除 pyqtgraph items → clear 列表 → 递归清空布局 → 调用 deleteLater()
  • _clear_layout 是递归的: 子布局也需要递归清空

7.4 numpy 内存

  • ctypes 数组通过 np.ctypeslib.as_array() 创建的是视图 (view),需 .copy() 确保独立所有权
  • pending_data_latest_data 是独立的 numpy 数组,不会互扰

7.5 采样率与采样点数的联动

  • 切换采样率时 (QComboBox currentTextChanged) → 同步更新 chunk_spin 的值
  • 修改采样点数时 (QSpinBox valueChanged) → 运行时通过 set_chunk_samples() 同步到 DAQManager
  • blockSignals(True/False) 防止修改 spinbox 值时再次触发 valueChanged

7.6 设备 IP 和 ID/Slot 通配符

  • Device-ID=*Device-Slot=* 使用通配符匹配任意设备
  • 只有在多设备环境需要区分时才需指定具体 ID/Slot

7.7 DIO 注意事项

  • digitalRead() 返回 ctypes.c_uint64不是 int,需通过 .value 获取 Python int
  • DI 轮询用 stop_event.wait(0.03) 而非 time.sleep,可立即响应停止信号
  • DO 的 digitalWrite() 无需后台线程,UI 线程直接调用是安全的
  • 位掩码翻转: _do_state ^= (1 << ch)if _do_state & bit: clear else: set

8. 文件结构速查

8.1 X612/AIO.py (General AIO)

行 1-37     文件头注释 (架构概述 / Config 结构 / 适配方法)
行 39-48    import
行 50-60    可配置常量 (SAMPLE_RATES, DEFAULT_CONFIG)
行 70-101   build_config() — Config 字符串生成
行 110-260  class DAQManager — 设备管理层
行 270-890  class MainWindow — UI 层
            行 304-326   配置相关
            行 328-342   UI 控件回调
            行 344-411   启停/暂停
            行 413-427   UI 辅助
            行 429-588   曲线与图例管理
            行 590-768   UI 构建
            行 770-810   图例面板辅助
            行 812-882   数据刷新与渲染
行 890-897  入口

8.2 D814/DIO.py (General DIO)

行 1-37     文件头注释 (架构概述 / 设备规格)
行 39-47    import
行 50-58    可配置常量 (DI_COUNT, DO_COUNT, DEFAULT_CONFIG)
行 60-85    build_config() — 仅 <DI> + <DO> 段
行 88-135   class DAQManager — DI 轮询 + DO 直写
行 138-310  class MainWindow — UI 层
            行 138-160   __init__ / get_config / set_config_fields_enabled
            行 162-185   启停 (start_device, stop_device)
            行 187-194   on_do_toggled (位掩码翻转)
            行 196-215   update_ui + _render_di (指示灯刷新)
            行 217-240   控件工厂 (_make_di_indicator, _make_do_toggle)
            行 242-305   setup_ui (QGridLayout DI+DO)
            行 307-310   closeEvent
行 313-318  入口

8.3 D814/AIO.py (General AIO, 自由采样率)

行 1-53     文件头注释 (架构概述 / 设备规格 / Config 结构 / 适配方法)
行 55-62    import
行 64-70    可配置常量 (DEFAULT_AI_SR, DEFAULT_AO_SR, DEFAULT_CONFIG)
行 72-95    build_config() + _parse_sr()
行 97-215   class DAQManager — AI 循环 + AO 循环, 版本号驱动
行 217-713  class MainWindow — UI 层
            行 220-240   __init__ / get_config / set_config_fields_enabled
            行 242-260   启停/暂停 (start_device, stop_device, toggle_pause)
            行 262-275   曲线清理 (clear_curves, _clear_layout)
            行 277-328   setup_curves — 动态曲线 + 图例浮层
            行 330-370   setup_ao_controls — AO 幅值/频率控件
            行 372-660   setup_ui — 完整 UI 构建 (左右分栏)
            行 662-680   图例自适应 (_sync_edit_widths, _update_legend_pos)
            行 682-710   数据刷新与渲染 (update_ui, _render_latest)

8.4 D814/AIO_Sync.py (AOSyncAI, 同步采样率)

行 1-28     文件头注释 (设备规格 / 同步模式说明 / 架构概述)
行 30-38    import
行 42-49    可配置常量 (DEFAULT_SYNC_SR, DEFAULT_CONFIG)
行 53-76    build_config() — DAQMode=1, AI/AO 共用 sync_sample_rate
行 78-84    _parse_sr() — 采样率字符串解析
行 88-185   class DAQManager — _sync_sr 统一驱动 AI 和 AO
            行 96-98    __init__ 接收 sync_sr 而非 ai_sr, ao_sr
            行 141-157  _ai_loop: analogRead 采集
            行 159-179  _ao_loop: 使用 _sync_sr 计算 chunk 时长
行 189-440  class MainWindow — UI 层
            行 209-219   get_config / set_config_fields_enabled
            行 223-233   on_sync_sr_changed — 同步采样点数默认值
            行 237-265   启停/暂停
            行 278-326   setup_curves — 动态曲线 + 图例浮层
            行 328-368   setup_ao_controls — AO 幅值/频率控件
            行 372-530   setup_ui — QLineEdit 输入同步采样率 (无预设按钮)
            行 547-566   数据刷新与渲染 — 使用 _sync_sr 计算 X 轴时间

与 D814/AIO.py (General) 的关键差异:

  • DAQMode=1 替代 DAQMode=0
  • 单个 sync_sample_rate (QLineEdit) 替代独立的 ai_sample_rate / ao_sample_rate
  • DAQManager.__init__ 接收 sync_sr 而非 ai_sr, ao_sr
  • _ao_loop 使用 _sync_sr 计算 chunk 时长
  • _render_latest 使用 _sync_sr 计算 X 轴时间
  • 硬件层面 AO 生成主时钟, AI 相位锁定跟随; Python API 调用方式不变

8.5 X612/DI_Trigger_AI.py (DI-Trigger-AI)

行 1-47     CONFIG 静态配置 (DITrigger 段含触发通道/时钟/方向/每次采样数)
行 49-51    常量 (SAMPLE_RATE, TRIGGER_SAMPLES, PLOT_SECONDS)
行 54-70    class DAQManager — Queue 驱动模式, trigger_count 计数器
            行 62-70    _ai_loop: analogRead 阻塞等待 DI 上升沿触发
行 73-405   class MainWindow — UI 层
            行 73-100   __init__ / 数据初始化
            行 102-180  setup_ui — 设备信息/配置/启停/参数控件
            行 182-395  setup_curves_dynamic — 启动后动态创建图表+图例+AO
            行 397-405  _render_checked / closeEvent

9. 配置模板速查 (config.txt 节选)

以下字段名必须严格匹配,大小写敏感:

<DITrigger>
DITrigger-Channel=0;
DITrigger-SampleClock=500000Hz;    // 最大 1MHz
DITrigger-Direction=0;             // 0:Rising 1:Falling 2:Either
DITrigger-AIOSamplePerTrigger=-1;  // -1:连续 N:每次触发采N点
</DITrigger>

<Counter>
Counter-Channel=0;
Counter-Direction=0;        // 0:RisingEdge 1:FallingEdge
Counter-SampleRate=1000Hz;
Counter-PusleSamples=10;
</Counter>

<PWM>
PWM-Channel=0;
PWM-Frequency=1000Hz;
PWM-DutyCycle=50%;
</PWM>

<Encoder>
Encoder-Channel=0;
Encoder-SampleRate=1000Hz;
Encoder-Resolution=2000P/R;  // 每圈脉冲数
</Encoder>

<TC>
TC-Channel=0;
TC-SampleRate=20Hz;
TC-Type=K;             // B/E/J/K/N/R/S/T
TC-CJC-Type=0;         // 0:Internal 1:External
</TC>

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mtdaq-1.1.1-py3-none-any.whl (21.4 kB view details)

Uploaded Python 3

File details

Details for the file mtdaq-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: mtdaq-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 21.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for mtdaq-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 09b7c2eece8f11a46950bcd19d3e9028c39a6e64c17b7a74ecdf67a3b11a8884
MD5 f7a185fd38ea0bdad39e07708d472f64
BLAKE2b-256 171c0363a7446d59de3644e956427fc84314385c14e2826313b381a09f752026

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page