3. 工业相机接口与触发模式配置

任务目标

完成工业相机(以海康威视MV-CA系列GigE接口相机为例)的接口初始化与三种触发模式配置:连续采集模式、软件触发模式、硬件外触发模式。通过代码实现相机的连接、参数配置、取流启停,并验证每种模式下图像采集是否按预期工作。

环境依赖

  • 海康威视MVS SDK(含MvCameraControl.h与链接库)
  • GigE接口工业相机一台(或MVS虚拟相机用于调试)
  • 千兆网口、网线(或虚拟网卡)
  • Visual Studio 2019+ / GCC,C++11及以上

关键完整代码

#include <stdio.h>
#include <string.h>
#include <chrono>
#include <thread>
#include "MvCameraControl.h"

// 错误码打印
#define CHECK(expr) do { \
    int ret = (expr); \
    if (ret != MV_OK) { \
        printf("Error at %s:%d - ret=0x%X\n", __FILE__, __LINE__, ret); \
        return ret; \
    } \
} while(0)

// 枚举并连接第一个GigE相机
int ConnectCamera(MV_CC_DEVICE_INFO_HANDLE* deviceHandle) {
    MV_CC_DEVICE_INFO_LIST deviceList;
    memset(&deviceList, 0, sizeof(deviceList));
    CHECK(MV_CC_EnumDevices(MV_GIGE_DEVICE, &deviceList));
    if (deviceList.nDeviceNum == 0) {
        printf("No GigE camera found.\n");
        return MV_E_NODATA;
    }
    // 打印设备信息
    MV_CC_DEVICE_INFO* pInfo = deviceList.pDeviceInfo[0];
    printf("Connecting to: %s\n", pInfo->SpecialInfo.stGigEInfo.chModelName);
    CHECK(MV_CC_CreateHandle(deviceHandle, pInfo));
    CHECK(MV_CC_OpenDevice(*deviceHandle));
    return MV_OK;
}

// 配置触发模式: 0=连续, 1=软件触发, 2=硬件外触发(Line0)
int SetTriggerMode(MV_CC_DEVICE_INFO_HANDLE handle, int mode) {
    MVCC_ENUMVALUE trigMode = {0};
    CHECK(MV_CC_GetEnumValue(handle, "TriggerMode", &trigMode));
    trigMode.nCurValue = (mode == 0) ? MV_TRIGGER_MODE_OFF : MV_TRIGGER_MODE_ON;
    CHECK(MV_CC_SetEnumValue(handle, "TriggerMode", trigMode.nCurValue));

    if (mode == 0) {
        // 连续模式:关闭触发源
        CHECK(MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE));
        printf("Trigger: Continuous mode\n");
    } else if (mode == 1) {
        // 软件触发
        CHECK(MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE));
        printf("Trigger: Software mode\n");
    } else if (mode == 2) {
        // 硬件外触发:Line0上升沿
        CHECK(MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0));
        CHECK(MV_CC_SetEnumValue(handle, "TriggerActivation", MV_TRIGGER_ACTIVATION_RISINGEDGE));
        printf("Trigger: Hardware Line0 rising edge\n");
    }
    return MV_OK;
}

// 采集一帧图像(带超时)
int GrabOneFrame(MV_CC_DEVICE_INFO_HANDLE handle, unsigned char* buf, int bufSize, MV_FRAME_OUT_INFO_EX* frameInfo) {
    memset(frameInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
    CHECK(MV_CC_StartGrabbing(handle));
    CHECK(MV_CC_GetOneFrameTimeout(handle, buf, bufSize, frameInfo, 1000));
    CHECK(MV_CC_StopGrabbing(handle));
    return MV_OK;
}

int main() {
    MV_CC_DEVICE_INFO_HANDLE handle = NULL;
    CHECK(ConnectCamera(&handle));

    // 设置像素格式为Mono8以减小数据量(可选)
    CHECK(MV_CC_SetEnumValue(handle, "PixelFormat", MV_PIXEL_FORMAT_MONO8));

    unsigned char* frameBuf = new unsigned char[2048 * 2048]; // 预留足够空间
    MV_FRAME_OUT_INFO_EX frameInfo;

    // ---- 模式1: 连续采集 ----
    CHECK(SetTriggerMode(handle, 0));
    CHECK(GrabOneFrame(handle, frameBuf, 2048 * 2048, &frameInfo));
    printf("Continuous: got frame %d x %d, size=%d\n",
           frameInfo.nWidth, frameInfo.nHeight, frameInfo.nFrameLen);

    // ---- 模式2: 软件触发 ----
    CHECK(SetTriggerMode(handle, 1));
    CHECK(MV_CC_StartGrabbing(handle));
    CHECK(MV_CC_SetCommandValue(handle, "TriggerSoftware")); // 软触发命令
    CHECK(MV_CC_GetOneFrameTimeout(handle, frameBuf, 2048 * 2048, &frameInfo, 1000));
    CHECK(MV_CC_StopGrabbing(handle));
    printf("Software trigger: got frame %d x %d\n", frameInfo.nWidth, frameInfo.nHeight);

    // ---- 模式3: 硬件外触发 ----
    CHECK(SetTriggerMode(handle, 2));
    printf("Hardware trigger: waiting for external signal on Line0...\n");
    CHECK(GrabOneFrame(handle, frameBuf, 2048 * 2048, &frameInfo));
    printf("Hardware trigger: got frame %d x %d\n", frameInfo.nWidth, frameInfo.nHeight);

    delete[] frameBuf;
    CHECK(MV_CC_CloseDevice(handle));
    CHECK(MV_CC_DestroyHandle(handle));
    printf("All trigger modes verified successfully.\n");
    return 0;
}

编译与运行

  1. 在MVS SDK安装目录下,将Development\Includes加入头文件路径,Development\Libraries\win64加入库路径,链接MvCameraControl.lib。
  2. 编译:g++ -o trigger_demo trigger_demo.cpp -I"$(MVS_ROOT)/Development/Includes" -L"$(MVS_ROOT)/Development/Libraries/win64" -lMvCameraControl(Windows下使用MSVC对应命令)。
  3. 运行前确保相机已连接且IP配置正确(可用MVS客户端工具确认相机可见)。
  4. 硬件触发模式需将信号发生器或PLC输出接至相机Line0引脚(建议3.3V TTL电平)。

验证方法与判定标准

  • 连续模式:程序启动后应立即打印一帧图像的宽高与大小,无需外部信号。
  • 软件触发:程序调用TriggerSoftware命令后1秒内应收到图像,打印尺寸信息。
  • 硬件触发:程序运行至该阶段后阻塞等待,此时向Line0输入一个上升沿脉冲(如按下按钮或由信号发生器输出),应能收到一帧图像并打印。
  • 三种模式均打印出正确的图像尺寸(与相机分辨率一致)且无错误码,即判定通过。

常见问题

  • 枚举不到相机:检查网线连接、关闭防火墙、使用MVS工具配置相机IP与主机IP在同一网段。
  • 硬件触发无响应:确认Line0接线正确,触发源选择与相机硬件版本匹配(部分型号需用Line2或光耦输入)。
  • 取流超时:连续模式下若曝光时间过长,可先减小曝光值;硬件触发时确认信号脉宽大于相机最小触发脉宽(通常>10μs)。