【相机硬触发】大恒相机硬触发说明文档

  • Post author:
  • Post category:其他




大恒相机硬触发说明文档

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

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

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



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

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2pAw5Fxg-1659436674790)(/home/houbosen/Pictures/Screenshot 2022-07-14 14:00:47.png)]

````
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include "time.h"
#include "opencv2/opencv.hpp"
#include "../libFSM/include/StateMachine.h"
#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的变化,这个挺简单的,我就不切系统复制了。

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



版权声明:本文为outbreakrmb原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。