知微传感Lkam系列线扫轮廓仪SDK例程篇:设置工作逻辑
写在前面
- 本人从事机器视觉细分的3D相机行业。编写此系列文章主要目的有:
- 1、便利他人应用3D相机,本系列文章包含公司所出售相机的SDK的使用例程及详细注释;
- 2、促进行业发展及交流。
- 知微传感Lkam系列3D相机可以应用于3C行业,电子制造,汽车,工业等场景的检测测量
- 欢迎与我深入交流:微信号:liu_zhisensor
设备工作模式
为满足多种现场应用要求,设备具备多种工作模式,其设置流程如下所示:
如图所示,配置设备工作,需要首先设置设备的工作模式,其中:
- I/O上升沿 代表指定引脚收到上升沿后,再触发设备,设备才会采集数据,直至收到下降沿
- I/O下降沿 代表指定引脚收到下降沿后,再触发设备,设备才会采集数据,直至收到上升沿沿
- 条件模式 指其他可自由配置的条件,条件模式下,需要配置数据采集的条件,即图中所示前置条件,包括
- 开始条件
- 软件,即由软件作为开始条件
- I/O上升沿,即指定引脚收到上升沿作为开始条件
- I/O下降沿,即指定引脚收到下降沿作为开始条件
- 结束条件
- 软件,即软件作为结束条件
- 固定轮廓线,即采集指定的轮廓线数量作为结束条件
- 固定时间,即采集固定时间长度作为结束条件
- 开始条件
数据采集的触发源有三种:
- 内部时钟,即设备内部时钟作为触发源
- 软件触发,即使用软件作为触发源
- 编码器,即编码器作为触发源
示例
假设现场要求使用I/O触发设备采集数据,当I/O接收到上升沿后,采集100组数据,采集频率为100Hz,则可以使用如下工作模式:条件模式+开始条件:I/O上升沿+结束条件:固定轮廓线100+触发源:内部时钟
示例代码如下(设备是为高速场景设计,因此在输出灰度图时是抽帧输出的,在本例钟并不会输出100张照片,而是保存13张):
代码如下:
// lineTestSDK.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <string>
#include <Windows.h>
#include <vector>
#include <fstream>
#include <iomanip>//zhisensor
#include "lkam_camera.h"
#include "lkam_log.h"
#include "lkam_base_type.h"LSCamera lCamera; //设备对象//=======================================================
//
// 获取图像
//
//=======================================================
void getImg(unsigned int deviceID, const LKAM_Data* image, void* userData) {static int p = 0;LKAM_Data img = *image;img.DataBuffer = malloc(img.DataSize);p++;if (nullptr != img.DataBuffer && nullptr != image->DataBuffer){memcpy(img.DataBuffer, image->DataBuffer, img.DataSize);}std::cout << "数量:" << p << std::endl;static int grayc = 0;grayc++;//每采集1幅灰度图,保存1幅static int sacou = 0;if (grayc % 1 == 0) {sacou++;std::string pngpath = "E:\\" + std::to_string(sacou) + ".png";std::cout << "saved png" << std::endl;std::string tiffpath = "E:\\" + std::to_string(sacou) + ".tiff";lCamera.SaveImageToPNG(pngpath.data(), &img);lCamera.SaveImageToTIFF(tiffpath.data(), &img);}free(img.DataBuffer);}int main()
{std::cout << "Hello ZhiSENSOR!" << std::endl;unsigned int deviceID = 1; //设备序号,用于连接多台设备时的区分std::vector<LKAM_CameraInfo> discoveryInfo;std::vector<LKAM_CameraInfo>().swap(discoveryInfo);int camCount = -1;int fnd = lCamera.DiscoverCamera(&discoveryInfo, camCount);if (fnd == 0){std::cout << "发现设备数量:" << camCount << std::endl;for (int i = 0; i < camCount; i++)std::cout << "设备IP --- " << discoveryInfo[i].ip << std::endl;}else {std::cout << "局域网内未发现设备" << std::endl;}discoveryInfo.clear();std::string ip_address = "192.168.2.118"; //目标设备ip// 连接相机int conSta = lCamera.ConnectCamera(deviceID, const_cast<char*>(ip_address.c_str()));std::cout << "conSta:" << conSta << std::endl;if (conSta == 0){std::cout << "连接设备正常" << std::endl;//======================SDK及固件号char firmwareVer[100];char SDKver[100];char LCSDKver[90];lCamera.GetFirAndSDKVersion(deviceID, firmwareVer, SDKver, LCSDKver);std::cout << "固件版本号:" << firmwareVer << std::endl;std::cout << "SDK版本号:" << SDKver << std::endl;std::cout << "LCSDK版本号:" << LCSDKver << std::endl;LKAM_DeviceInfo lDeviceInfo;lCamera.GetDeviceInfo(deviceID, &lDeviceInfo);std::cout << "设备基本信息:" << std::endl;std::cout << "设备型号:" << lDeviceInfo.devMode << std::endl;std::cout << "设备序列号:" << lDeviceInfo.SN << std::endl;std::cout << "设备最近测量距离:" << lDeviceInfo.ZScope[0] << std::endl;std::cout << "设备最远测量距离:" << lDeviceInfo.ZScope[1] << std::endl;std::cout << "设备限制工作时间:" << lDeviceInfo.RunLicense << std::endl;std::cout << "设备生产厂家:" << lDeviceInfo.Manufacturer << std::endl;//获取当前相机配置参数LKAM_CameraParameter lcamParameters;int Gcp = -1;Gcp = lCamera.GetCameraParameter(deviceID, &lcamParameters);if (Gcp == 0) {std::cout << "当前相机参数:" << std::endl;std::cout << "工作模式:" << lcamParameters.SnapMode << std::endl;}else {std::cout << "获取设备参数异常" << std::endl;}#if 1 //开始条件:软件;结束条件:固定轮廓线//===============================// 条件模式// 开始条件:软件;结束条件:固定轮廓线// 触发源:内部时钟,采集周期为每秒100次数据采集//===================================工作逻辑================================lcamParameters.SnapMode = LKAM_SNAP_CONDITION; //条件模式lcamParameters.StartCondition = LKAM_GRAB_START_SOFTWARE; //开始条件:软件lcamParameters.StopCondition = LKAM_GRAP_STOP_FIXPROFILES; //结束采集条件:固定轮廓线lcamParameters.StopConditionFixProfilesCount = 100; //固定轮廓线数100lcamParameters.TriggerSource = LKAM_TRG_SRC_INTERNAL; //触发源:内部时钟lcamParameters.GrabFrameRate = 100; //采集帧率//===================================工作参数================================lcamParameters.ExposureDelayUs = 0; //触发延时时间lcamParameters.ExposureHighUs = 150; //曝光时间,单位us,应小于采集周期lcamParameters.CameraHDREnable = 0; //HDR功能lcamParameters.CameraAnalogGain = 3; //模拟增益lcamParameters.SubSampling = LKAM_SUBSAMPLING_1_1; //降采样lcamParameters.ImageWidth = 2048; //图像宽度lcamParameters.ImageHeight = 512; //图像高度lcamParameters.RoiModeEnable = LKAM_FALSE; //ROI区域:关闭lcamParameters.RoiOffsetX = 0; //ROI区域x轴偏移lcamParameters.RoiOffsetY = 0; //ROI区域y轴偏移#endif //设置设备参数,立即生效LKAM_CameraParameter camParameters; //LB_SetCameraParameter会返回设置后的参数,这里用camParameters2暂存int sp = lCamera.SetCameraParameter(deviceID, &lcamParameters, &camParameters);if (sp == 0){std::cout << camParameters.StopConditionFixProfilesCount << std::endl;std::cout << "设备参数设置成功" << std::endl;}else {std::cout << "设备参数设置异常" << std::endl;}//注册接收图像的回调if (LKAM_OK != lCamera.RegisterImageCallBack(deviceID, &getImg, nullptr)){std::cout << "注册接收图像回调异常" << std::endl;}else {std::cout << "注册接收图像回调成功" << std::endl;}//设定接收数据类型if (LKAM_OK != lCamera.SetGrabDataMode(deviceID, LKAM_GrabDataMode::LKAM_RAW_IMAGE)){std::cout << "设定接收数据类型异常" << std::endl;}else {std::cout << "设定接收数据类型成功" << std::endl;}while (1) {if (LKAM_OK != lCamera.StartGrab(deviceID)){continue;}if (LKAM_OK != lCamera.SetCameraGrabFire(deviceID)){continue;}/*if (LKAM_OK != lCamera.StopGrab(deviceID)){continue;}*/}int disConn = lCamera.DisconnectCamera(deviceID);if (disConn == 0){std::cout << "断开设备" << std::endl;}else {std::cout << "断开设备异常" << std::endl;}}else {std::cout << "设备连接异常!!!" << std::endl;}}
运行结果:
小节
示意了线扫设备的工作逻辑设置过程。