SmartDriver 二次开发用户手册

概述

SmartDriver 是用于操作光纤光谱仪的 SDK 动态库,提供 C 语言接口,支持 Windows 和 Linux 双平台。通过调用 SmartDriver 提供的 API 函数,用户可以在自有软件中集成光谱仪控制与数据采集功能,实现从设备枚举到光谱读取的完整工作流。本文档介绍 SmartDriver 的基本操作流程、函数详解,并提供 C 语言和 Python 的完整调用例程。


一、基本操作流程

以下 8 个步骤涵盖了从光谱仪初始化到读取光谱数据的基础流程,可满足绝大部分常规测量需求:

  1. 枚举设备int Init(int commType) — 获取已连接的光谱仪数量
  2. 打开设备int Open(int index) — 以指定通讯方式打开光谱仪
  3. 获取序列号int GetSerialNumber(int index, char *serialNumber) — 读取设备唯一标识
  4. 设置积分时间int SetIntegrationTime(int index, double integrationTimeMs) — 单位 ms
  5. 设置平均次数int SetAverageTime(int index, int averageTime) — 多次平均提升信噪比
  6. 获取波长数量int GetWavelengthsNumber(int index, int *number) — 默认 2048 个像素
  7. 获取波长值int GetWavelengths(int index, float *wls) — 读取 2048 个波长点
  8. 获取光谱强度int GetScopes(int index, unsigned short *scopes) — 读取对应强度值

如果需要配合闪烁氙灯使用,还需额外执行以下两个步骤(SmartDriver v2.2.2 起支持):

  1. 配置氙灯触发脉冲int SetXenonPulse(int index, int period, int discharge)。参数 period 为脉冲周期,默认值为 1,510,000 个 10 ns(即 15.1 ms);discharge 为放电时间(高电平持续时间),默认值 10,000 个 10 ns(即 0.1 ms)。如不理解参数含义,使用默认值即可。

  2. 配置氙灯触发模式int SetXenonModel(int index, int mode)mode = 0,不开启触发(默认);mode = 1,单次脉冲模式;mode = 2,连续脉冲模式。

单次脉冲模式:积分时间大于一个脉冲周期时,仅触发一次,配合平均次数可实现高频触发。此为最常用模式。

连续脉冲模式:积分时间为脉冲周期的整数倍时,氙灯按周期连续触发,适用于氙灯强度不足需累积光强的场景。

注意:设置氙灯触发模式后,只要光谱仪不断电,该模式会一直保存在寄存器中。断电后需重新配置。


二、函数详解

2.1 初始化与枚举

int Init(int commType);
  • 描述:初始化光谱仪,获取已连接光谱仪数量
  • 参数 commType:通讯类型,0 为启用 USB 通讯
  • 返回>0 为已连接设备数量;<0 为错误码

2.2 打开与关闭

int Open(int index);
int Close(int index);
  • 参数 index:光谱仪索引,从 0 开始
  • 返回0 成功,<0 为错误码

2.3 获取序列号

int GetSerialNumber(int index, char *serialNumber);
  • 参数 serialNumber:用于存储序列号的字符串指针,长度 ≥ 8

2.4 设置积分时间与平均次数

int SetIntegrationTime(int index, double integrationTimeMs);
int SetAverageTime(int index, int averageTime);
  • 积分时间单位为 ms;增加平均次数可提升信噪比但延长测量耗时

2.5 获取波长与强度

int GetWavelengthsNumber(int index, int *number);
int GetWavelengths(int index, float *wls);
int GetScopes(int index, unsigned short *scopes);
  • 波长数组长度默认 2048;强度值类型为 unsigned short(16 位)

2.6 氙灯控制

int SetXenonPulse(int index, int period, int discharge);
int SetXenonModel(int index, int mode);
  • 配置氙灯脉冲前需先配置触发脉冲;关闭软件前建议先关闭光谱仪再退出

三、C 语言例程

以下例程 C 和 C++ 通用,Windows 和 Linux 通用:

#include "wrapper.h"
#include <stdio.h>

int main()
{
    int index = 0;
    int ret = 0;
    char deviceSerail[13];
    float wls[2048];
    unsigned short scopes[2048];

    // 枚举设备
    int deviceNum = Init(0);
    printf("Device number: %d\n", deviceNum);

    // 打开设备
    ret = Open(index);
    if (ret < 0) printf("Open error code: %d\n", ret);
    else printf("Open successfully.\n");

    // 获取序列号
    ret = GetSerialNumber(index, deviceSerail);
    if (ret >= 0) printf("Serial: %s\n", deviceSerail);

    // 设置积分时间 100 ms,平均 5 次
    SetIntegrationTime(index, 100);
    SetAverageTime(index, 5);

    // 获取波长
    GetWavelengths(index, wls);

    // 获取强度
    GetScopes(index, scopes);

    // 打印前 5 个像素的波长和强度
    for (int i = 0; i < 5; i++)
        printf("%.3f: %d\n", wls[i], scopes[i]);

    // 关闭设备
    Close(index);
    return 0;
}

Linux 注意:运行程序需管理员权限,如 sudo ./main


四、Python 例程

Python 通过 ctypes 模块调用 C 动态库 libwrapper.so(Linux)/ libwrapper.dll(Windows):

import ctypes

# 加载动态库(Linux 使用绝对路径)
libwrapper = ctypes.CDLL('/usr/local/lib/libwrapper.so', mode=ctypes.RTLD_GLOBAL)

# 定义函数原型
libwrapper.Init.argtypes = [ctypes.c_int]
libwrapper.Init.restype = ctypes.c_int

libwrapper.Open.argtypes = [ctypes.c_int]
libwrapper.Open.restype = ctypes.c_int

libwrapper.GetSerialNumber.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char)]
libwrapper.GetSerialNumber.restype = ctypes.c_int

libwrapper.SetIntegrationTime.argtypes = [ctypes.c_int, ctypes.c_double]
libwrapper.SetIntegrationTime.restype = ctypes.c_int

libwrapper.SetAverageTime.argtypes = [ctypes.c_int, ctypes.c_int]
libwrapper.SetAverageTime.restype = ctypes.c_int

libwrapper.GetWavelengths.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_float)]
libwrapper.GetWavelengths.restype = ctypes.c_int

libwrapper.GetScopes.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_ushort)]
libwrapper.GetScopes.restype = ctypes.c_int

# 封装为 Python 类
class Wrapper:
    def __init__(self):
        pass

    def init(self, commType):
        return libwrapper.Init(commType)

    def open(self, index):
        return libwrapper.Open(index)

    def get_serial_number(self, index):
        serial = ctypes.create_string_buffer(8)
        ret = libwrapper.GetSerialNumber(index, serial)
        return ret, serial.value.decode()

    def set_integration_time(self, index, ms):
        return libwrapper.SetIntegrationTime(index, ms)

    def set_average_time(self, index, n):
        return libwrapper.SetAverageTime(index, n)

    def get_wavelengths(self, index):
        wls = (ctypes.c_float * 2048)()
        ret = libwrapper.GetWavelengths(index, wls)
        return ret, [wls[i] for i in range(2048)]

    def get_scopes(self, index):
        scopes = (ctypes.c_ushort * 2048)()
        ret = libwrapper.GetScopes(index, scopes)
        return ret, [scopes[i] for i in range(2048)]

# 使用示例
wrapper = Wrapper()
index = 0

ret = wrapper.init(0)
print(f"Connected devices: {ret}")

wrapper.open(index)
wrapper.set_integration_time(index, 100)
wrapper.set_average_time(index, 5)

ret, wavelengths = wrapper.get_wavelengths(index)
ret, scopes = wrapper.get_scopes(index)

for i in range(500, 505):
    print(f"{wavelengths[i]:.2f}: {scopes[i]}")

五、Linux 系统注意事项

5.1 依赖库

使用光纤光谱仪 SDK 需要两个依赖库:FTDI 通信芯片库 libftd2xx.so 和光谱仪操作库 libwrapper.so。可将其复制到 /usr/local/lib 并添加环境变量:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

5.2 卸载 VCP 驱动

Linux 系统中 VCP(Virtual COM Port)与 D2XX 驱动不兼容。使用 USB 通信前需卸载 VCP 驱动:

sudo rmmod ftdi_sio
sudo rmmod usbserial

特别注意:每次插入光谱仪时 VCP 驱动都会自动安装,因此每次使用前都需卸载。建议在软件启动脚本中自动执行上述卸载命令。


本文由谱研互联整理编写