大恒相机硬触发说明文档

相机硬触发是区别于软触发,利用IO或者光耦等外部控制信号触发相机快门的技术。

大恒相机有IO触发和光耦触发两种硬触发方式,其中光耦触发隔离了光电回路,对于相机更加安全,但是由于存在光电转换过程所以触发时间延迟了30us左右。硬触发方式只有单次触发,也就是说想要连续获得图片必须向相机发射多次发射方波信号。

硬触发只能通过回调函数获得图片,对于大恒相机只能通过已经定义的回调函数获得图片,回调的数据类型已经确定。

利用IO信号控制相机硬触发

在IO控制线中有line0,line1,line2,line3三根线,前两根是光耦触发线,后两根是IO输入/输出线。注意使用IO控制时还应连接IO地线GND。

这里我接了line2(5)和GND(2)然后line2接到一个单片机上的GPIO口上,推挽输出,输出电压为5V,然后完成以下设置之后,只要单片机的IO口输出一个高电平,相机就会采集一张图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
````
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include "time.h"
#include "opencv2/opencv.hpp"
#include "stdio.h"
#include "GxIAPI.h"

//定义全局变量,用来存图和计时
cv::Mat empty(1024, 1280, CV_8UC3, cv::Scalar::all(0));
timeval tv;
long time_end;
long time_start;
//图 像 回 调 处 理 函 数
//传回来的GX_FRAME_CALLBACK_PARAM *pFrame包含了图像所在指针,大小,长度等一系列信息,需要解码之后变成RGB图片
static void GX_STDC OnFrameCallbackFun(GX_FRAME_CALLBACK_PARAM *pFrame)
{
if (pFrame->status == 0)
{
gettimeofday(&tv, NULL);
time_end = tv.tv_sec * 1000000 + tv.tv_usec;
std::cout << 1000000 / (time_end - time_start) << "fps"
<< "get an image" << std::endl;
time_start = time_end;
void *rgb_buffer = malloc(3 * pFrame->nImgSize);
DxRaw8toRGB24((void *)pFrame->pImgBuf, rgb_buffer, pFrame->nWidth, pFrame->nHeight, RAW2RGB_NEIGHBOUR, BAYERRG, false);
cv::Mat result = cv::Mat(pFrame->nHeight, pFrame->nWidth, CV_8UC3, rgb_buffer);
result.copyTo(empty);
}
else
{
std::cout << "fuck,trigger is failed" << std::endl;
}
return;
}

//打开设备和打开库方式相同,关键在于设置触发
int main(int argc, char *argv[])
{
GX_STATUS status = GX_STATUS_SUCCESS;
GX_DEV_HANDLE hDevice = NULL;
GX_OPEN_PARAM stOpenParam;
uint32_t nDeviceNum = 0;
gettimeofday(&tv, NULL);
time_end = tv.tv_sec * 1000000 + tv.tv_usec;
time_start = tv.tv_sec * 1000000 + tv.tv_usec;
//初 始 化 库
status = GXInitLib();
//枚 举 设 备 列 表
status = GXUpdateDeviceList(&nDeviceNum, 1000);
if ((status != GX_STATUS_SUCCESS) || (nDeviceNum <= 0))
{
return 0;
}
//打 开 设 备
stOpenParam.accessMode = GX_ACCESS_EXCLUSIVE;
stOpenParam.openMode = GX_OPEN_INDEX;
stOpenParam.pszContent = "1";
status = GXOpenDevice(&stOpenParam, &hDevice);
if (status == GX_STATUS_SUCCESS)
{
//设 置 触 发 模 式 为 ON
status = GXSetEnum(hDevice, GX_ENUM_TRIGGER_MODE, GX_TRIGGER_MODE_ON);
//设 置 触 发 激 活 方 式 为 上 升 沿,还可以设置下降沿触发,指电平上升或下降时为一次触发
status = GXSetEnum(hDevice, GX_ENUM_TRIGGER_ACTIVATION, GX_TRIGGER_ACTIVATION_RISINGEDGE);
//设置触发开关为line2
status = GXSetEnum(hDevice, GX_ENUM_TRIGGER_SOURCE, GX_TRIGGER_SOURCE_LINE2);
//Selects the physical line (or pin) of the external device connector to configure,我也不知道是啥反正加去了
status = GXSetEnum(hDevice, GX_ENUM_LINE_SELECTOR, GX_ENUM_LINE_SELECTOR_LINE2);
//设置line2模式为input,同样可以设置为outpot,则可以通过相机控制外部设备
status = GXSetEnum(hDevice, GX_ENUM_LINE_MODE, GX_ENUM_LINE_MODE_INPUT);


// GX_ENUM_TRIGGER_MODE: 触发模式, 枚举值参考 GX_TRIGGER_MODE_ENTRY
// GX_COMMAND_TRIGGER_SOFTWARE : 软触发命令
// GX_ENUM_TRIGGER_ACTIVATION : 触发极性, 枚举值参考
// GX_TRIGGER_ACTIVATION_ENTRY GX_ENUM_TRIGGER_SWITCH : 外触发开关, 参考
// GX_TRIGGER_SWITCH_ENTRY GX_ENUM_TRIGGER_SOURCE : 触发源, 枚举值参考
// GX_TRIGGER_SOURCE_ENTRY GX_ENUM_TRIGGER_SELECTOR : 触发类型选择, 参考
// GX_TRIGGER_SELECTOR_ENTRY GX_FLOAT_TRIGGER_DELAY : 触发延迟
//设置曝光和增益等参数和原先在一致
status = GXSetFloat(hDevice, GX_FLOAT_EXPOSURE_TIME, (float)3000);
status = GXSetEnum(hDevice, GX_ENUM_BALANCE_RATIO_SELECTOR, GX_BALANCE_RATIO_SELECTOR_RED);
status = GXSetFloat(hDevice, GX_FLOAT_BALANCE_RATIO, 1.6484);
status = GXSetEnum(hDevice, GX_ENUM_BALANCE_RATIO_SELECTOR, GX_BALANCE_RATIO_SELECTOR_BLUE);
status = GXSetFloat(hDevice, GX_FLOAT_BALANCE_RATIO, 1.5664);
status = GXSetEnum(hDevice, GX_ENUM_BALANCE_RATIO_SELECTOR, GX_BALANCE_RATIO_SELECTOR_GREEN);
status = GXSetFloat(hDevice, GX_FLOAT_BALANCE_RATIO, 1.000);
status = GXSetEnum(hDevice, GX_ENUM_GAIN_SELECTOR, GX_GAIN_SELECTOR_ALL);
status = GXSetFloat(hDevice, GX_FLOAT_GAIN, 10.0);
//注 册 图 像 处 理 回 调 函 数,每次接受到一个电平变化就会回调
status = GXRegisterCaptureCallback(hDevice, NULL, OnFrameCallbackFun);
//发 送 开 采 命 令
status = GXSendCommand(hDevice, GX_COMMAND_ACQUISITION_START);
}
//所有引脚状态
int64_t nAllLineStatus = 0;

while (1)
{
cv::imshow("test", empty);
if (cv::waitKey(1) == 'a')
{
}
if (cv::waitKey(1) == 'b')
{
//输出所有引脚的电平,0xc默认是未触发状态,但是实际上0xe是未触发
GX_STATUS Status = GXGetInt(hDevice, GX_INT_LINE_STATUS_ALL, &nAllLineStatus);
std::cout
<< "line status:" << nAllLineStatus << std::endl;
}
if (cv::waitKey(1) == 'q')
{
//
//在 发 送 停 采 命 令 前 如 果 产 生 了 有 效 触 发 , 那 么 图 像
//会 通 过 OnFrameCallbackFun 接 口 返 给 用 户
//---------------------
//发 送 停 采 命 令
status = GXSendCommand(hDevice, GX_COMMAND_ACQUISITION_STOP);
//注 销 采 集 回 调
status = GXUnregisterCaptureCallback(hDevice);
status = GXCloseDevice(hDevice);
hDevice = NULL;
status = GXCloseLib();
std::cout << "end captrue" << std::endl;
return 0;
}
}
}

IO控制的电控代码

我设计的电控方案是摁一下摁建就会有回调函数触发,回调函数就会展示这张照片,如果没有摁摁建就不会有图片,不会触发。如有需要可以联系我

设置曝光为3000us,查看大恒的图像传输过程大概是300us,取一次传图的周期为5000us,即200hz,则也应设置电控发送200hz的IO变化电平,实际在视觉收到的图片速率也在200hz作有,有不到10hz的变化,这个挺简单的,我就不切系统复制电控的代码了。