PynectDirect Python 交互式光谱例程使用说明
适用文件:
python_ctypes_example.py
运行环境:64 位 Windows、64 位 Python 3
示例用途:读取设备信息并完成一次指定波长范围的光谱测量
1. 示例功能
python_ctypes_example.py 是一个可以直接运行的交互式 Python 示例。程序会按照提示完成以下操作:
- 搜索并打开 PynectDirect 光谱仪。
- 读取设备序列号。
- 读取并显示设备完整波长范围。
- 读取当前积分时间和平均次数。
- 让用户输入本次测量使用的积分时间和平均次数。
- 让用户输入准备读取的起始波长和结束波长。
- 显示设备实际选择的波长范围。
- 读取所选范围内的全部波长值和对应的强度值。
- 说明实际读取的总点数,并等间隔打印最多 10 组代表数据。
- 恢复运行前的积分时间和平均次数,并关闭设备。
本例程设置的是本次运行期间使用的临时测量参数,不会写入设备的默认固化配置。
2. 运行环境和文件布局
2.1 Python 要求
必须使用 64 位 Python。可以执行以下命令检查:
python -c "import struct; print(struct.calcsize('P') * 8)"
正确输出为:
64
本例程只使用 Python 标准库,不需要执行 pip install。
2.2 推荐的交付包布局
在完整 SDK 交付包中,文件布局如下:
PynectDirect_SDK/
|-- bin/
| |-- PynectDirect.dll
| `-- ftd2xx.dll
`-- examples/
|-- python_ctypes_example.py
`-- python_ctypes_example_guide.md
PynectDirect.dll 和 ftd2xx.dll 必须放在同一个目录中。程序可以从交付包的 bin 目录自动找到它们。
2.3 单独复制例程时的布局
如果只复制 Python 例程,建议使用同级 dll 目录:
my_spectrum_demo/
|-- python_ctypes_example.py
|-- python_ctypes_example_guide.md
`-- dll/
|-- PynectDirect.dll
`-- ftd2xx.dll
程序也支持把两个 DLL 直接放在 python_ctypes_example.py 同级目录。
3. 运行例程
打开 PowerShell,进入 SDK 交付包目录后执行:
python .\examples\python_ctypes_example.py
如果已经进入 examples 目录,也可以执行:
python .\python_ctypes_example.py
程序会扫描设备。只连接一台设备时自动使用设备索引 0;连接多台设备时,会先提示选择设备索引。
4. 逐项输入说明
程序会先读取设备当前状态,再提示输入本次测量参数。方括号中的数值是默认值,直接按 Enter 即采用该值。
| 提示项目 | 输入类型 | 单位或范围 | 直接按 Enter | 作用 |
|---|---|---|---|---|
| 设备索引 | 整数 | 扫描结果中的 0 至最大索引 |
使用 0 |
选择要打开的设备;仅多设备时出现 |
| 积分时间 | 正整数 | 微秒(us),不超过设备允许范围 | 保留当前积分时间 | 设置本次测量的临时积分时间 |
| 平均次数 | 整数 | 1-255 次 |
保留当前平均次数 | 设置本次测量的临时平均次数 |
| 起始波长 | 数字 | nm,位于完整波长范围内 | 使用完整范围起点 | 选择本次读取范围的起点 |
| 结束波长 | 数字 | nm,位于完整波长范围内 | 使用完整范围终点 | 选择本次读取范围的终点 |
起始波长必须小于结束波长。输入文字、超出范围的数值或无效组合时,程序会说明问题并重新提示,不需要重新启动。
4.1 输入提示示例
假设设备当前积分时间为 50000 us,平均次数为 1,完整波长范围为 350-850 nm:
Device serial number: PYN-TEST-001
Full wavelength range: 350.000-850.000 nm
Current integration time: 50000 us
Current average count: 1
Integration time in us [50000]: 100000
Average count [1]: 3
Start wavelength in nm [350.000]: 400
End wavelength in nm [850.000]: 600
以上输入表示:
- 本次测量使用
100000 us的积分时间。 - 每个输出光谱点使用
3次平均。 - 只读取请求范围
400-600 nm内的光谱数据。
4.2 全部采用默认值
如果希望保留当前积分时间和平均次数,并读取完整波长范围,在四个参数提示处直接按 Enter 即可。
5. 输出内容说明
5.1 测量摘要
采集完成后,程序首先输出:
| 输出项目 | 含义 |
|---|---|
Device serial number |
设备序列号 |
Full wavelength range |
设备支持的完整波长范围 |
Integration time |
本次测量实际使用的积分时间,单位 us |
Average count |
本次测量实际使用的平均次数 |
Requested wavelength range |
用户输入的起始波长和结束波长 |
Actual wavelength range |
设备按实际像素位置匹配后的范围 |
Actual wavelength points read |
所选范围内实际读取的数据点总数 |
请求范围和实际范围可能存在很小差异。这是因为设备只能选择实际存在的像素和标定波长点。处理数据时应以 Actual wavelength range 和实际返回数组为准。
5.2 波长值和强度值
例程会读取所选范围内的全部光谱点,但为了让控制台输出便于查看,只打印最多 10 组代表数据。实际点数不少于 10 时,程序按原始索引等间隔选取 10 组,并保留首点和尾点;实际点数少于 10 时,程序打印全部数据。
例如,某次测量实际读取 810 个点时,输出开头如下:
Actual wavelength points read: 810
Showing 10 evenly spaced points:
Index Wavelength (nm) Intensity
0 800.090000 1200
90 811.197000 1380
...
809 899.911000 1760
三列含义如下:
Index:所选范围内的数据序号,从0开始。Wavelength (nm):该点的波长值,单位 nm。Intensity:相同索引位置对应的原始光谱强度值,范围为0-65535。
波长值与强度值按索引一一对应。例如,索引 1 的 500.000000 nm 对应强度值 2300。不要对两个数组分别排序,否则会破坏这种对应关系。
控制台只省略显示,不会丢弃测量数据。run_interactive_measurement() 返回的 result.wavelengths 和 result.intensities 仍包含本次实际读取的全部数据;上例中两个列表都包含 810 个元素。
6. 在自己的程序中复用
6.1 读取完整光谱
原有 read_full_spectrum(device_index=0) 函数继续保留。它不进行交互输入,返回两个普通 Python 列表:
from python_ctypes_example import read_full_spectrum
wavelengths, intensities = read_full_spectrum(device_index=0)
print("Point count:", len(wavelengths))
print("First pair:", wavelengths[0], intensities[0])
6.2 执行交互式选择波段测量
run_interactive_measurement() 会显示逐项提示,并返回 SelectedSpectrumResult:
from python_ctypes_example import run_interactive_measurement
result = run_interactive_measurement()
for wavelength, intensity in zip(
result.wavelengths, result.intensities
):
print(wavelength, intensity)
结果对象的主要字段如下:
| 字段 | 类型 | 含义 |
|---|---|---|
serial_number |
str |
设备序列号 |
full_start_nm、full_end_nm |
float |
完整波长范围 |
integration_us |
int |
本次积分时间,单位 us |
average_count |
int |
本次平均次数 |
request_start_nm、request_end_nm |
float |
用户请求范围 |
actual_start_nm、actual_end_nm |
float |
设备实际匹配范围 |
start_pixel、end_pixel |
int |
实际起止像素 |
wavelengths |
list |
所选范围的波长列表 |
intensities |
list |
与波长列表对应的强度列表 |
正常返回时,len(result.wavelengths) 与 len(result.intensities) 始终相同。
7. 参数恢复和设备关闭
程序会在修改前保存原积分时间和平均次数。完成采集或遇到采集错误时,程序都会尝试:
- 恢复原平均次数。
- 恢复原积分时间。
- 关闭设备。
如果恢复失败,程序会输出以 WARNING: 开头的提示。此时不要继续测量,应关闭其他可能使用设备的软件,重新打开设备并检查参数。
程序正常结束后,选择波长范围不会写入设备的长期配置。下次运行仍会重新读取完整范围并提示输入。
8. 常见错误
8.1 找不到 PynectDirect.dll
可能看到:
ERROR: PynectDirect.dll not found
检查:
- 文件名是否严格为
PynectDirect.dll。 PynectDirect.dll和ftd2xx.dll是否位于同一个目录。- DLL 是否位于脚本同级目录、同级
dll目录或交付包bin目录。
8.2 Python 位数不正确
如果使用 32 位 Python,会看到需要 64 位 Python 的提示。安装并使用 64 位 Python 后重新运行。
8.3 没有发现设备
可能看到:
ERROR: No PynectDirect device found
检查 USB 连接和设备供电,并关闭其他正在占用光谱仪的软件。
8.4 输入值无效
- 积分时间必须是正整数,单位为微秒。
- 平均次数必须在
1-255之间。 - 起始波长和结束波长必须位于显示的完整范围内。
- 起始波长必须小于结束波长。
程序会重新提示,按要求输入即可。
8.5 API 返回负错误码
错误信息会包含操作名称和返回码,例如:
ERROR: Get selected spectrum data failed, return code=-9
常见返回码包括:
| 返回码 | 含义 |
|---|---|
-3 |
设备未打开 |
-4 |
设备通信或返回数据异常 |
-5 |
参数或数组容量无效 |
-7/-8 |
数据校验或数据包异常 |
-9 |
设备响应超时 |
-11 |
当前设备不支持该功能 |
完整错误码和 API 参数说明请查阅 docs/PynectDirect_API_Guide.md。
9. 安全说明
- 本例程只修改当前测量使用的临时积分时间和平均次数。
- 本例程不会调用 Flash、固化配置、氙灯、DAC 或设备复位功能。
- 不要在设备采集过程中拔出 USB 线。
- 较长积分时间和较大平均次数会增加等待时间,并不表示程序失去响应。
- 使用自己的程序调用时,也应保证异常路径最终关闭设备。